aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Ryabinin <a.ryabinin@samsung.com>2015-02-13 17:39:56 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-14 00:21:41 -0500
commit393f203f5fd54421fddb1e2a263f64d3876eeadb (patch)
treee78e96b38ecd36eec62325cc2cc21e8d79397bc1
parent3f15801cdc2379ca4bf507f48bffd788f9e508ae (diff)
x86_64: kasan: add interceptors for memset/memmove/memcpy functions
Recently instrumentation of builtin functions calls was removed from GCC 5.0. To check the memory accessed by such functions, userspace asan always uses interceptors for them. So now we should do this as well. This patch declares memset/memmove/memcpy as weak symbols. In mm/kasan/kasan.c we have our own implementation of those functions which checks memory before accessing it. Default memset/memmove/memcpy now now always have aliases with '__' prefix. For files that built without kasan instrumentation (e.g. mm/slub.c) original mem* replaced (via #define) with prefixed variants, cause we don't want to check memory accesses there. Signed-off-by: Andrey Ryabinin <a.ryabinin@samsung.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Konstantin Serebryany <kcc@google.com> Cc: Dmitry Chernenkov <dmitryc@google.com> Signed-off-by: Andrey Konovalov <adech.fo@gmail.com> Cc: Yuri Gribov <tetra2005@gmail.com> Cc: Konstantin Khlebnikov <koct9i@gmail.com> Cc: Sasha Levin <sasha.levin@oracle.com> Cc: Christoph Lameter <cl@linux.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Christoph Lameter <cl@linux.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/x86/boot/compressed/eboot.c3
-rw-r--r--arch/x86/boot/compressed/misc.h1
-rw-r--r--arch/x86/include/asm/string_64.h18
-rw-r--r--arch/x86/kernel/x8664_ksyms_64.c10
-rw-r--r--arch/x86/lib/memcpy_64.S6
-rw-r--r--arch/x86/lib/memmove_64.S4
-rw-r--r--arch/x86/lib/memset_64.S10
-rw-r--r--drivers/firmware/efi/libstub/efistub.h4
-rw-r--r--mm/kasan/kasan.c29
9 files changed, 74 insertions, 11 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 92b9a5f2aed6..ef17683484e9 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -13,8 +13,7 @@
13#include <asm/setup.h> 13#include <asm/setup.h>
14#include <asm/desc.h> 14#include <asm/desc.h>
15 15
16#undef memcpy /* Use memcpy from misc.c */ 16#include "../string.h"
17
18#include "eboot.h" 17#include "eboot.h"
19 18
20static efi_system_table_t *sys_table; 19static efi_system_table_t *sys_table;
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 24e3e569a13c..04477d68403f 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -7,6 +7,7 @@
7 * we just keep it from happening 7 * we just keep it from happening
8 */ 8 */
9#undef CONFIG_PARAVIRT 9#undef CONFIG_PARAVIRT
10#undef CONFIG_KASAN
10#ifdef CONFIG_X86_32 11#ifdef CONFIG_X86_32
11#define _ASM_X86_DESC_H 1 12#define _ASM_X86_DESC_H 1
12#endif 13#endif
diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h
index 19e2c468fc2c..e4661196994e 100644
--- a/arch/x86/include/asm/string_64.h
+++ b/arch/x86/include/asm/string_64.h
@@ -27,11 +27,12 @@ static __always_inline void *__inline_memcpy(void *to, const void *from, size_t
27 function. */ 27 function. */
28 28
29#define __HAVE_ARCH_MEMCPY 1 29#define __HAVE_ARCH_MEMCPY 1
30extern void *__memcpy(void *to, const void *from, size_t len);
31
30#ifndef CONFIG_KMEMCHECK 32#ifndef CONFIG_KMEMCHECK
31#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4 33#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
32extern void *memcpy(void *to, const void *from, size_t len); 34extern void *memcpy(void *to, const void *from, size_t len);
33#else 35#else
34extern void *__memcpy(void *to, const void *from, size_t len);
35#define memcpy(dst, src, len) \ 36#define memcpy(dst, src, len) \
36({ \ 37({ \
37 size_t __len = (len); \ 38 size_t __len = (len); \
@@ -53,9 +54,11 @@ extern void *__memcpy(void *to, const void *from, size_t len);
53 54
54#define __HAVE_ARCH_MEMSET 55#define __HAVE_ARCH_MEMSET
55void *memset(void *s, int c, size_t n); 56void *memset(void *s, int c, size_t n);
57void *__memset(void *s, int c, size_t n);
56 58
57#define __HAVE_ARCH_MEMMOVE 59#define __HAVE_ARCH_MEMMOVE
58void *memmove(void *dest, const void *src, size_t count); 60void *memmove(void *dest, const void *src, size_t count);
61void *__memmove(void *dest, const void *src, size_t count);
59 62
60int memcmp(const void *cs, const void *ct, size_t count); 63int memcmp(const void *cs, const void *ct, size_t count);
61size_t strlen(const char *s); 64size_t strlen(const char *s);
@@ -63,6 +66,19 @@ char *strcpy(char *dest, const char *src);
63char *strcat(char *dest, const char *src); 66char *strcat(char *dest, const char *src);
64int strcmp(const char *cs, const char *ct); 67int strcmp(const char *cs, const char *ct);
65 68
69#if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
70
71/*
72 * For files that not instrumented (e.g. mm/slub.c) we
73 * should use not instrumented version of mem* functions.
74 */
75
76#undef memcpy
77#define memcpy(dst, src, len) __memcpy(dst, src, len)
78#define memmove(dst, src, len) __memmove(dst, src, len)
79#define memset(s, c, n) __memset(s, c, n)
80#endif
81
66#endif /* __KERNEL__ */ 82#endif /* __KERNEL__ */
67 83
68#endif /* _ASM_X86_STRING_64_H */ 84#endif /* _ASM_X86_STRING_64_H */
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 040681928e9d..37d8fa4438f0 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -50,13 +50,19 @@ EXPORT_SYMBOL(csum_partial);
50#undef memset 50#undef memset
51#undef memmove 51#undef memmove
52 52
53extern void *__memset(void *, int, __kernel_size_t);
54extern void *__memcpy(void *, const void *, __kernel_size_t);
55extern void *__memmove(void *, const void *, __kernel_size_t);
53extern void *memset(void *, int, __kernel_size_t); 56extern void *memset(void *, int, __kernel_size_t);
54extern void *memcpy(void *, const void *, __kernel_size_t); 57extern void *memcpy(void *, const void *, __kernel_size_t);
55extern void *__memcpy(void *, const void *, __kernel_size_t); 58extern void *memmove(void *, const void *, __kernel_size_t);
59
60EXPORT_SYMBOL(__memset);
61EXPORT_SYMBOL(__memcpy);
62EXPORT_SYMBOL(__memmove);
56 63
57EXPORT_SYMBOL(memset); 64EXPORT_SYMBOL(memset);
58EXPORT_SYMBOL(memcpy); 65EXPORT_SYMBOL(memcpy);
59EXPORT_SYMBOL(__memcpy);
60EXPORT_SYMBOL(memmove); 66EXPORT_SYMBOL(memmove);
61 67
62#ifndef CONFIG_DEBUG_VIRTUAL 68#ifndef CONFIG_DEBUG_VIRTUAL
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
index 56313a326188..89b53c9968e7 100644
--- a/arch/x86/lib/memcpy_64.S
+++ b/arch/x86/lib/memcpy_64.S
@@ -53,6 +53,8 @@
53.Lmemcpy_e_e: 53.Lmemcpy_e_e:
54 .previous 54 .previous
55 55
56.weak memcpy
57
56ENTRY(__memcpy) 58ENTRY(__memcpy)
57ENTRY(memcpy) 59ENTRY(memcpy)
58 CFI_STARTPROC 60 CFI_STARTPROC
@@ -199,8 +201,8 @@ ENDPROC(__memcpy)
199 * only outcome... 201 * only outcome...
200 */ 202 */
201 .section .altinstructions, "a" 203 .section .altinstructions, "a"
202 altinstruction_entry memcpy,.Lmemcpy_c,X86_FEATURE_REP_GOOD,\ 204 altinstruction_entry __memcpy,.Lmemcpy_c,X86_FEATURE_REP_GOOD,\
203 .Lmemcpy_e-.Lmemcpy_c,.Lmemcpy_e-.Lmemcpy_c 205 .Lmemcpy_e-.Lmemcpy_c,.Lmemcpy_e-.Lmemcpy_c
204 altinstruction_entry memcpy,.Lmemcpy_c_e,X86_FEATURE_ERMS, \ 206 altinstruction_entry __memcpy,.Lmemcpy_c_e,X86_FEATURE_ERMS, \
205 .Lmemcpy_e_e-.Lmemcpy_c_e,.Lmemcpy_e_e-.Lmemcpy_c_e 207 .Lmemcpy_e_e-.Lmemcpy_c_e,.Lmemcpy_e_e-.Lmemcpy_c_e
206 .previous 208 .previous
diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S
index 65268a6104f4..9c4b530575da 100644
--- a/arch/x86/lib/memmove_64.S
+++ b/arch/x86/lib/memmove_64.S
@@ -24,7 +24,10 @@
24 * Output: 24 * Output:
25 * rax: dest 25 * rax: dest
26 */ 26 */
27.weak memmove
28
27ENTRY(memmove) 29ENTRY(memmove)
30ENTRY(__memmove)
28 CFI_STARTPROC 31 CFI_STARTPROC
29 32
30 /* Handle more 32 bytes in loop */ 33 /* Handle more 32 bytes in loop */
@@ -220,4 +223,5 @@ ENTRY(memmove)
220 .Lmemmove_end_forward-.Lmemmove_begin_forward, \ 223 .Lmemmove_end_forward-.Lmemmove_begin_forward, \
221 .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs 224 .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs
222 .previous 225 .previous
226ENDPROC(__memmove)
223ENDPROC(memmove) 227ENDPROC(memmove)
diff --git a/arch/x86/lib/memset_64.S b/arch/x86/lib/memset_64.S
index 2dcb3808cbda..6f44935c6a60 100644
--- a/arch/x86/lib/memset_64.S
+++ b/arch/x86/lib/memset_64.S
@@ -56,6 +56,8 @@
56.Lmemset_e_e: 56.Lmemset_e_e:
57 .previous 57 .previous
58 58
59.weak memset
60
59ENTRY(memset) 61ENTRY(memset)
60ENTRY(__memset) 62ENTRY(__memset)
61 CFI_STARTPROC 63 CFI_STARTPROC
@@ -147,8 +149,8 @@ ENDPROC(__memset)
147 * feature to implement the right patch order. 149 * feature to implement the right patch order.
148 */ 150 */
149 .section .altinstructions,"a" 151 .section .altinstructions,"a"
150 altinstruction_entry memset,.Lmemset_c,X86_FEATURE_REP_GOOD,\ 152 altinstruction_entry __memset,.Lmemset_c,X86_FEATURE_REP_GOOD,\
151 .Lfinal-memset,.Lmemset_e-.Lmemset_c 153 .Lfinal-__memset,.Lmemset_e-.Lmemset_c
152 altinstruction_entry memset,.Lmemset_c_e,X86_FEATURE_ERMS, \ 154 altinstruction_entry __memset,.Lmemset_c_e,X86_FEATURE_ERMS, \
153 .Lfinal-memset,.Lmemset_e_e-.Lmemset_c_e 155 .Lfinal-__memset,.Lmemset_e_e-.Lmemset_c_e
154 .previous 156 .previous
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 2be10984a67a..47437b16b186 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -5,6 +5,10 @@
5/* error code which can't be mistaken for valid address */ 5/* error code which can't be mistaken for valid address */
6#define EFI_ERROR (~0UL) 6#define EFI_ERROR (~0UL)
7 7
8#undef memcpy
9#undef memset
10#undef memmove
11
8void efi_char16_printk(efi_system_table_t *, efi_char16_t *); 12void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
9 13
10efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image, 14efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index dc83f070edb6..799c52b9826c 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -255,6 +255,35 @@ static __always_inline void check_memory_region(unsigned long addr,
255 kasan_report(addr, size, write, _RET_IP_); 255 kasan_report(addr, size, write, _RET_IP_);
256} 256}
257 257
258void __asan_loadN(unsigned long addr, size_t size);
259void __asan_storeN(unsigned long addr, size_t size);
260
261#undef memset
262void *memset(void *addr, int c, size_t len)
263{
264 __asan_storeN((unsigned long)addr, len);
265
266 return __memset(addr, c, len);
267}
268
269#undef memmove
270void *memmove(void *dest, const void *src, size_t len)
271{
272 __asan_loadN((unsigned long)src, len);
273 __asan_storeN((unsigned long)dest, len);
274
275 return __memmove(dest, src, len);
276}
277
278#undef memcpy
279void *memcpy(void *dest, const void *src, size_t len)
280{
281 __asan_loadN((unsigned long)src, len);
282 __asan_storeN((unsigned long)dest, len);
283
284 return __memcpy(dest, src, len);
285}
286
258void kasan_alloc_pages(struct page *page, unsigned int order) 287void kasan_alloc_pages(struct page *page, unsigned int order)
259{ 288{
260 if (likely(!PageHighMem(page))) 289 if (likely(!PageHighMem(page)))