aboutsummaryrefslogtreecommitdiffstats
path: root/mm/kasan
diff options
context:
space:
mode:
authorAndrey Ryabinin <a.ryabinin@samsung.com>2015-02-13 17:39:28 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-14 00:21:41 -0500
commitb8c73fc2493d42517be95cf2c89659fc6c6f4d02 (patch)
tree81e44f58a903a8093617f5db7806f0bfa4cf5691 /mm/kasan
parentef7f0d6a6ca8c9e4b27d78895af86c2fbfaeedb2 (diff)
mm: page_alloc: add kasan hooks on alloc and free paths
Add kernel address sanitizer hooks to mark allocated page's addresses as accessible in corresponding shadow region. Mark freed pages as inaccessible. 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>
Diffstat (limited to 'mm/kasan')
-rw-r--r--mm/kasan/kasan.c14
-rw-r--r--mm/kasan/kasan.h2
-rw-r--r--mm/kasan/report.c11
3 files changed, 27 insertions, 0 deletions
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index def81104772f..b516eb8632b9 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -254,6 +254,20 @@ static __always_inline void check_memory_region(unsigned long addr,
254 kasan_report(addr, size, write, _RET_IP_); 254 kasan_report(addr, size, write, _RET_IP_);
255} 255}
256 256
257void kasan_alloc_pages(struct page *page, unsigned int order)
258{
259 if (likely(!PageHighMem(page)))
260 kasan_unpoison_shadow(page_address(page), PAGE_SIZE << order);
261}
262
263void kasan_free_pages(struct page *page, unsigned int order)
264{
265 if (likely(!PageHighMem(page)))
266 kasan_poison_shadow(page_address(page),
267 PAGE_SIZE << order,
268 KASAN_FREE_PAGE);
269}
270
257#define DEFINE_ASAN_LOAD_STORE(size) \ 271#define DEFINE_ASAN_LOAD_STORE(size) \
258 void __asan_load##size(unsigned long addr) \ 272 void __asan_load##size(unsigned long addr) \
259 { \ 273 { \
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 648b9c006f3f..d3c90d5dd97a 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -6,6 +6,8 @@
6#define KASAN_SHADOW_SCALE_SIZE (1UL << KASAN_SHADOW_SCALE_SHIFT) 6#define KASAN_SHADOW_SCALE_SIZE (1UL << KASAN_SHADOW_SCALE_SHIFT)
7#define KASAN_SHADOW_MASK (KASAN_SHADOW_SCALE_SIZE - 1) 7#define KASAN_SHADOW_MASK (KASAN_SHADOW_SCALE_SIZE - 1)
8 8
9#define KASAN_FREE_PAGE 0xFF /* page was freed */
10
9struct kasan_access_info { 11struct kasan_access_info {
10 const void *access_addr; 12 const void *access_addr;
11 const void *first_bad_addr; 13 const void *first_bad_addr;
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 5835d69563f5..fab8e7882ff1 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -54,6 +54,9 @@ static void print_error_description(struct kasan_access_info *info)
54 shadow_val = *(u8 *)kasan_mem_to_shadow(info->first_bad_addr); 54 shadow_val = *(u8 *)kasan_mem_to_shadow(info->first_bad_addr);
55 55
56 switch (shadow_val) { 56 switch (shadow_val) {
57 case KASAN_FREE_PAGE:
58 bug_type = "use after free";
59 break;
57 case 0 ... KASAN_SHADOW_SCALE_SIZE - 1: 60 case 0 ... KASAN_SHADOW_SCALE_SIZE - 1:
58 bug_type = "out of bounds access"; 61 bug_type = "out of bounds access";
59 break; 62 break;
@@ -69,6 +72,14 @@ static void print_error_description(struct kasan_access_info *info)
69 72
70static void print_address_description(struct kasan_access_info *info) 73static void print_address_description(struct kasan_access_info *info)
71{ 74{
75 const void *addr = info->access_addr;
76
77 if ((addr >= (void *)PAGE_OFFSET) &&
78 (addr < high_memory)) {
79 struct page *page = virt_to_head_page(addr);
80 dump_page(page, "kasan: bad access detected");
81 }
82
72 dump_stack(); 83 dump_stack();
73} 84}
74 85