]>
Commit | Line | Data |
---|---|---|
04fd09d4 SL |
1 | From d34e9055c024414a624f5ab8a6bb86d369286b7b Mon Sep 17 00:00:00 2001 |
2 | From: Qian Cai <cai@lca.pw> | |
3 | Date: Tue, 5 Mar 2019 15:41:24 -0800 | |
4 | Subject: page_poison: play nicely with KASAN | |
5 | ||
6 | [ Upstream commit 4117992df66a26fa33908b4969e04801534baab1 ] | |
7 | ||
8 | KASAN does not play well with the page poisoning (CONFIG_PAGE_POISONING). | |
9 | It triggers false positives in the allocation path: | |
10 | ||
11 | BUG: KASAN: use-after-free in memchr_inv+0x2ea/0x330 | |
12 | Read of size 8 at addr ffff88881f800000 by task swapper/0 | |
13 | CPU: 0 PID: 0 Comm: swapper Not tainted 5.0.0-rc1+ #54 | |
14 | Call Trace: | |
15 | dump_stack+0xe0/0x19a | |
16 | print_address_description.cold.2+0x9/0x28b | |
17 | kasan_report.cold.3+0x7a/0xb5 | |
18 | __asan_report_load8_noabort+0x19/0x20 | |
19 | memchr_inv+0x2ea/0x330 | |
20 | kernel_poison_pages+0x103/0x3d5 | |
21 | get_page_from_freelist+0x15e7/0x4d90 | |
22 | ||
23 | because KASAN has not yet unpoisoned the shadow page for allocation | |
24 | before it checks memchr_inv() but only found a stale poison pattern. | |
25 | ||
26 | Also, false positives in free path, | |
27 | ||
28 | BUG: KASAN: slab-out-of-bounds in kernel_poison_pages+0x29e/0x3d5 | |
29 | Write of size 4096 at addr ffff8888112cc000 by task swapper/0/1 | |
30 | CPU: 5 PID: 1 Comm: swapper/0 Not tainted 5.0.0-rc1+ #55 | |
31 | Call Trace: | |
32 | dump_stack+0xe0/0x19a | |
33 | print_address_description.cold.2+0x9/0x28b | |
34 | kasan_report.cold.3+0x7a/0xb5 | |
35 | check_memory_region+0x22d/0x250 | |
36 | memset+0x28/0x40 | |
37 | kernel_poison_pages+0x29e/0x3d5 | |
38 | __free_pages_ok+0x75f/0x13e0 | |
39 | ||
40 | due to KASAN adds poisoned redzones around slab objects, but the page | |
41 | poisoning needs to poison the whole page. | |
42 | ||
43 | Link: http://lkml.kernel.org/r/20190114233405.67843-1-cai@lca.pw | |
44 | Signed-off-by: Qian Cai <cai@lca.pw> | |
45 | Acked-by: Andrey Ryabinin <aryabinin@virtuozzo.com> | |
46 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
47 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
48 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
49 | --- | |
50 | mm/page_alloc.c | 2 +- | |
51 | mm/page_poison.c | 4 ++++ | |
52 | 2 files changed, 5 insertions(+), 1 deletion(-) | |
53 | ||
54 | diff --git a/mm/page_alloc.c b/mm/page_alloc.c | |
55 | index 40075c1946b3..923deb33bf34 100644 | |
56 | --- a/mm/page_alloc.c | |
57 | +++ b/mm/page_alloc.c | |
58 | @@ -1764,8 +1764,8 @@ inline void post_alloc_hook(struct page *page, unsigned int order, | |
59 | ||
60 | arch_alloc_page(page, order); | |
61 | kernel_map_pages(page, 1 << order, 1); | |
62 | - kernel_poison_pages(page, 1 << order, 1); | |
63 | kasan_alloc_pages(page, order); | |
64 | + kernel_poison_pages(page, 1 << order, 1); | |
65 | set_page_owner(page, order, gfp_flags); | |
66 | } | |
67 | ||
68 | diff --git a/mm/page_poison.c b/mm/page_poison.c | |
69 | index e83fd44867de..a7ba9e315a12 100644 | |
70 | --- a/mm/page_poison.c | |
71 | +++ b/mm/page_poison.c | |
72 | @@ -6,6 +6,7 @@ | |
73 | #include <linux/page_ext.h> | |
74 | #include <linux/poison.h> | |
75 | #include <linux/ratelimit.h> | |
76 | +#include <linux/kasan.h> | |
77 | ||
78 | static bool want_page_poisoning __read_mostly; | |
79 | ||
80 | @@ -34,7 +35,10 @@ static void poison_page(struct page *page) | |
81 | { | |
82 | void *addr = kmap_atomic(page); | |
83 | ||
84 | + /* KASAN still think the page is in-use, so skip it. */ | |
85 | + kasan_disable_current(); | |
86 | memset(addr, PAGE_POISON, PAGE_SIZE); | |
87 | + kasan_enable_current(); | |
88 | kunmap_atomic(addr); | |
89 | } | |
90 | ||
91 | -- | |
92 | 2.19.1 | |
93 |