mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 09:13:38 +00:00
entry, kasan, x86: Disallow overriding mem*() functions
KASAN cannot just hijack the mem*() functions, it needs to emit __asan_mem*() variants if it wants instrumentation (other sanitizers already do this). vmlinux.o: warning: objtool: sync_regs+0x24: call to memcpy() leaves .noinstr.text section vmlinux.o: warning: objtool: vc_switch_off_ist+0xbe: call to memcpy() leaves .noinstr.text section vmlinux.o: warning: objtool: fixup_bad_iret+0x36: call to memset() leaves .noinstr.text section vmlinux.o: warning: objtool: __sev_get_ghcb+0xa0: call to memcpy() leaves .noinstr.text section vmlinux.o: warning: objtool: __sev_put_ghcb+0x35: call to memcpy() leaves .noinstr.text section Remove the weak aliases to ensure nobody hijacks these functions and add them to the noinstr section. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Tested-by: Tony Lindgren <tony@atomide.com> Tested-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Frederic Weisbecker <frederic@kernel.org> Link: https://lore.kernel.org/r/20230112195542.028523143@infradead.org
This commit is contained in:
parent
365bd03ff6
commit
69d4c0d321
@ -8,7 +8,7 @@
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/export.h>
|
||||
|
||||
.pushsection .noinstr.text, "ax"
|
||||
.section .noinstr.text, "ax"
|
||||
|
||||
/*
|
||||
* We build a jump to memcpy_orig by default which gets NOPped out on
|
||||
@ -43,7 +43,7 @@ SYM_TYPED_FUNC_START(__memcpy)
|
||||
SYM_FUNC_END(__memcpy)
|
||||
EXPORT_SYMBOL(__memcpy)
|
||||
|
||||
SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy)
|
||||
SYM_FUNC_ALIAS(memcpy, __memcpy)
|
||||
EXPORT_SYMBOL(memcpy)
|
||||
|
||||
/*
|
||||
@ -184,4 +184,3 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
|
||||
RET
|
||||
SYM_FUNC_END(memcpy_orig)
|
||||
|
||||
.popsection
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
#undef memmove
|
||||
|
||||
.section .noinstr.text, "ax"
|
||||
|
||||
/*
|
||||
* Implement memmove(). This can handle overlap between src and dst.
|
||||
*
|
||||
@ -213,5 +215,5 @@ SYM_FUNC_START(__memmove)
|
||||
SYM_FUNC_END(__memmove)
|
||||
EXPORT_SYMBOL(__memmove)
|
||||
|
||||
SYM_FUNC_ALIAS_WEAK(memmove, __memmove)
|
||||
SYM_FUNC_ALIAS(memmove, __memmove)
|
||||
EXPORT_SYMBOL(memmove)
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/export.h>
|
||||
|
||||
.section .noinstr.text, "ax"
|
||||
|
||||
/*
|
||||
* ISO C memset - set a memory block to a byte value. This function uses fast
|
||||
* string to get better performance than the original function. The code is
|
||||
@ -43,7 +45,7 @@ SYM_FUNC_START(__memset)
|
||||
SYM_FUNC_END(__memset)
|
||||
EXPORT_SYMBOL(__memset)
|
||||
|
||||
SYM_FUNC_ALIAS_WEAK(memset, __memset)
|
||||
SYM_FUNC_ALIAS(memset, __memset)
|
||||
EXPORT_SYMBOL(memset)
|
||||
|
||||
/*
|
||||
|
@ -618,6 +618,10 @@ void __asan_set_shadow_f3(const void *addr, size_t size);
|
||||
void __asan_set_shadow_f5(const void *addr, size_t size);
|
||||
void __asan_set_shadow_f8(const void *addr, size_t size);
|
||||
|
||||
void *__asan_memset(void *addr, int c, size_t len);
|
||||
void *__asan_memmove(void *dest, const void *src, size_t len);
|
||||
void *__asan_memcpy(void *dest, const void *src, size_t len);
|
||||
|
||||
void __hwasan_load1_noabort(unsigned long addr);
|
||||
void __hwasan_store1_noabort(unsigned long addr);
|
||||
void __hwasan_load2_noabort(unsigned long addr);
|
||||
|
@ -38,6 +38,12 @@ bool __kasan_check_write(const volatile void *p, unsigned int size)
|
||||
}
|
||||
EXPORT_SYMBOL(__kasan_check_write);
|
||||
|
||||
#ifndef CONFIG_GENERIC_ENTRY
|
||||
/*
|
||||
* CONFIG_GENERIC_ENTRY relies on compiler emitted mem*() calls to not be
|
||||
* instrumented. KASAN enabled toolchains should emit __asan_mem*() functions
|
||||
* for the sites they want to instrument.
|
||||
*/
|
||||
#undef memset
|
||||
void *memset(void *addr, int c, size_t len)
|
||||
{
|
||||
@ -68,6 +74,38 @@ void *memcpy(void *dest, const void *src, size_t len)
|
||||
|
||||
return __memcpy(dest, src, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *__asan_memset(void *addr, int c, size_t len)
|
||||
{
|
||||
if (!kasan_check_range((unsigned long)addr, len, true, _RET_IP_))
|
||||
return NULL;
|
||||
|
||||
return __memset(addr, c, len);
|
||||
}
|
||||
EXPORT_SYMBOL(__asan_memset);
|
||||
|
||||
#ifdef __HAVE_ARCH_MEMMOVE
|
||||
void *__asan_memmove(void *dest, const void *src, size_t len)
|
||||
{
|
||||
if (!kasan_check_range((unsigned long)src, len, false, _RET_IP_) ||
|
||||
!kasan_check_range((unsigned long)dest, len, true, _RET_IP_))
|
||||
return NULL;
|
||||
|
||||
return __memmove(dest, src, len);
|
||||
}
|
||||
EXPORT_SYMBOL(__asan_memmove);
|
||||
#endif
|
||||
|
||||
void *__asan_memcpy(void *dest, const void *src, size_t len)
|
||||
{
|
||||
if (!kasan_check_range((unsigned long)src, len, false, _RET_IP_) ||
|
||||
!kasan_check_range((unsigned long)dest, len, true, _RET_IP_))
|
||||
return NULL;
|
||||
|
||||
return __memcpy(dest, src, len);
|
||||
}
|
||||
EXPORT_SYMBOL(__asan_memcpy);
|
||||
|
||||
void kasan_poison(const void *addr, size_t size, u8 value, bool init)
|
||||
{
|
||||
|
@ -1074,6 +1074,9 @@ static const char *uaccess_safe_builtin[] = {
|
||||
"__asan_store16_noabort",
|
||||
"__kasan_check_read",
|
||||
"__kasan_check_write",
|
||||
"__asan_memset",
|
||||
"__asan_memmove",
|
||||
"__asan_memcpy",
|
||||
/* KASAN in-line */
|
||||
"__asan_report_load_n_noabort",
|
||||
"__asan_report_load1_noabort",
|
||||
|
Loading…
Reference in New Issue
Block a user