Commit 69d4c0d3 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar

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: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Tested-by: default avatarTony Lindgren <tony@atomide.com>
Tested-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarFrederic Weisbecker <frederic@kernel.org>
Link: https://lore.kernel.org/r/20230112195542.028523143@infradead.org
parent 365bd03f
...@@ -8,7 +8,7 @@ ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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[] = { ...@@ -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",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment