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

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
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -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
+3 −1
Original line number Diff line number Diff line
@@ -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)
+3 −1
Original line number Diff line number Diff line
@@ -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)

/*
+4 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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)
{
Loading