Skip to content

Commit 69d4c0d

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
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) <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Tested-by: Tony Lindgren <[email protected]> Tested-by: Ulf Hansson <[email protected]> Acked-by: Rafael J. Wysocki <[email protected]> Acked-by: Frederic Weisbecker <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 365bd03 commit 69d4c0d

File tree

6 files changed

+53
-5
lines changed

6 files changed

+53
-5
lines changed

arch/x86/lib/memcpy_64.S

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <asm/alternative.h>
99
#include <asm/export.h>
1010

11-
.pushsection .noinstr.text, "ax"
11+
.section .noinstr.text, "ax"
1212

1313
/*
1414
* We build a jump to memcpy_orig by default which gets NOPped out on
@@ -43,7 +43,7 @@ SYM_TYPED_FUNC_START(__memcpy)
4343
SYM_FUNC_END(__memcpy)
4444
EXPORT_SYMBOL(__memcpy)
4545

46-
SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy)
46+
SYM_FUNC_ALIAS(memcpy, __memcpy)
4747
EXPORT_SYMBOL(memcpy)
4848

4949
/*
@@ -184,4 +184,3 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
184184
RET
185185
SYM_FUNC_END(memcpy_orig)
186186

187-
.popsection

arch/x86/lib/memmove_64.S

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
#undef memmove
1515

16+
.section .noinstr.text, "ax"
17+
1618
/*
1719
* Implement memmove(). This can handle overlap between src and dst.
1820
*
@@ -213,5 +215,5 @@ SYM_FUNC_START(__memmove)
213215
SYM_FUNC_END(__memmove)
214216
EXPORT_SYMBOL(__memmove)
215217

216-
SYM_FUNC_ALIAS_WEAK(memmove, __memmove)
218+
SYM_FUNC_ALIAS(memmove, __memmove)
217219
EXPORT_SYMBOL(memmove)

arch/x86/lib/memset_64.S

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <asm/alternative.h>
77
#include <asm/export.h>
88

9+
.section .noinstr.text, "ax"
10+
911
/*
1012
* ISO C memset - set a memory block to a byte value. This function uses fast
1113
* string to get better performance than the original function. The code is
@@ -43,7 +45,7 @@ SYM_FUNC_START(__memset)
4345
SYM_FUNC_END(__memset)
4446
EXPORT_SYMBOL(__memset)
4547

46-
SYM_FUNC_ALIAS_WEAK(memset, __memset)
48+
SYM_FUNC_ALIAS(memset, __memset)
4749
EXPORT_SYMBOL(memset)
4850

4951
/*

mm/kasan/kasan.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,10 @@ void __asan_set_shadow_f3(const void *addr, size_t size);
618618
void __asan_set_shadow_f5(const void *addr, size_t size);
619619
void __asan_set_shadow_f8(const void *addr, size_t size);
620620

621+
void *__asan_memset(void *addr, int c, size_t len);
622+
void *__asan_memmove(void *dest, const void *src, size_t len);
623+
void *__asan_memcpy(void *dest, const void *src, size_t len);
624+
621625
void __hwasan_load1_noabort(unsigned long addr);
622626
void __hwasan_store1_noabort(unsigned long addr);
623627
void __hwasan_load2_noabort(unsigned long addr);

mm/kasan/shadow.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ bool __kasan_check_write(const volatile void *p, unsigned int size)
3838
}
3939
EXPORT_SYMBOL(__kasan_check_write);
4040

41+
#ifndef CONFIG_GENERIC_ENTRY
42+
/*
43+
* CONFIG_GENERIC_ENTRY relies on compiler emitted mem*() calls to not be
44+
* instrumented. KASAN enabled toolchains should emit __asan_mem*() functions
45+
* for the sites they want to instrument.
46+
*/
4147
#undef memset
4248
void *memset(void *addr, int c, size_t len)
4349
{
@@ -68,6 +74,38 @@ void *memcpy(void *dest, const void *src, size_t len)
6874

6975
return __memcpy(dest, src, len);
7076
}
77+
#endif
78+
79+
void *__asan_memset(void *addr, int c, size_t len)
80+
{
81+
if (!kasan_check_range((unsigned long)addr, len, true, _RET_IP_))
82+
return NULL;
83+
84+
return __memset(addr, c, len);
85+
}
86+
EXPORT_SYMBOL(__asan_memset);
87+
88+
#ifdef __HAVE_ARCH_MEMMOVE
89+
void *__asan_memmove(void *dest, const void *src, size_t len)
90+
{
91+
if (!kasan_check_range((unsigned long)src, len, false, _RET_IP_) ||
92+
!kasan_check_range((unsigned long)dest, len, true, _RET_IP_))
93+
return NULL;
94+
95+
return __memmove(dest, src, len);
96+
}
97+
EXPORT_SYMBOL(__asan_memmove);
98+
#endif
99+
100+
void *__asan_memcpy(void *dest, const void *src, size_t len)
101+
{
102+
if (!kasan_check_range((unsigned long)src, len, false, _RET_IP_) ||
103+
!kasan_check_range((unsigned long)dest, len, true, _RET_IP_))
104+
return NULL;
105+
106+
return __memcpy(dest, src, len);
107+
}
108+
EXPORT_SYMBOL(__asan_memcpy);
71109

72110
void kasan_poison(const void *addr, size_t size, u8 value, bool init)
73111
{

tools/objtool/check.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,9 @@ static const char *uaccess_safe_builtin[] = {
10741074
"__asan_store16_noabort",
10751075
"__kasan_check_read",
10761076
"__kasan_check_write",
1077+
"__asan_memset",
1078+
"__asan_memmove",
1079+
"__asan_memcpy",
10771080
/* KASAN in-line */
10781081
"__asan_report_load_n_noabort",
10791082
"__asan_report_load1_noabort",

0 commit comments

Comments
 (0)