mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-01 10:43:43 +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/alternative.h>
|
||||||
#include <asm/export.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
|
* 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)
|
SYM_FUNC_END(__memcpy)
|
||||||
EXPORT_SYMBOL(__memcpy)
|
EXPORT_SYMBOL(__memcpy)
|
||||||
|
|
||||||
SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy)
|
SYM_FUNC_ALIAS(memcpy, __memcpy)
|
||||||
EXPORT_SYMBOL(memcpy)
|
EXPORT_SYMBOL(memcpy)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -184,4 +184,3 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
|
|||||||
RET
|
RET
|
||||||
SYM_FUNC_END(memcpy_orig)
|
SYM_FUNC_END(memcpy_orig)
|
||||||
|
|
||||||
.popsection
|
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
#undef memmove
|
#undef memmove
|
||||||
|
|
||||||
|
.section .noinstr.text, "ax"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implement memmove(). This can handle overlap between src and dst.
|
* Implement memmove(). This can handle overlap between src and dst.
|
||||||
*
|
*
|
||||||
@ -213,5 +215,5 @@ SYM_FUNC_START(__memmove)
|
|||||||
SYM_FUNC_END(__memmove)
|
SYM_FUNC_END(__memmove)
|
||||||
EXPORT_SYMBOL(__memmove)
|
EXPORT_SYMBOL(__memmove)
|
||||||
|
|
||||||
SYM_FUNC_ALIAS_WEAK(memmove, __memmove)
|
SYM_FUNC_ALIAS(memmove, __memmove)
|
||||||
EXPORT_SYMBOL(memmove)
|
EXPORT_SYMBOL(memmove)
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include <asm/alternative.h>
|
#include <asm/alternative.h>
|
||||||
#include <asm/export.h>
|
#include <asm/export.h>
|
||||||
|
|
||||||
|
.section .noinstr.text, "ax"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ISO C memset - set a memory block to a byte value. This function uses fast
|
* 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
|
* string to get better performance than the original function. The code is
|
||||||
@ -43,7 +45,7 @@ SYM_FUNC_START(__memset)
|
|||||||
SYM_FUNC_END(__memset)
|
SYM_FUNC_END(__memset)
|
||||||
EXPORT_SYMBOL(__memset)
|
EXPORT_SYMBOL(__memset)
|
||||||
|
|
||||||
SYM_FUNC_ALIAS_WEAK(memset, __memset)
|
SYM_FUNC_ALIAS(memset, __memset)
|
||||||
EXPORT_SYMBOL(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_f5(const void *addr, size_t size);
|
||||||
void __asan_set_shadow_f8(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_load1_noabort(unsigned long addr);
|
||||||
void __hwasan_store1_noabort(unsigned long addr);
|
void __hwasan_store1_noabort(unsigned long addr);
|
||||||
void __hwasan_load2_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);
|
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
|
#undef memset
|
||||||
void *memset(void *addr, int c, size_t len)
|
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);
|
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)
|
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",
|
"__asan_store16_noabort",
|
||||||
"__kasan_check_read",
|
"__kasan_check_read",
|
||||||
"__kasan_check_write",
|
"__kasan_check_write",
|
||||||
|
"__asan_memset",
|
||||||
|
"__asan_memmove",
|
||||||
|
"__asan_memcpy",
|
||||||
/* KASAN in-line */
|
/* KASAN in-line */
|
||||||
"__asan_report_load_n_noabort",
|
"__asan_report_load_n_noabort",
|
||||||
"__asan_report_load1_noabort",
|
"__asan_report_load1_noabort",
|
||||||
|
Loading…
Reference in New Issue
Block a user