From ab5d4ae2e4c60e9552b304331f3a05efbc7f3157 Mon Sep 17 00:00:00 2001 From: "Se Wang (Patrick) Oh" Date: Thu, 25 Jun 2015 15:15:06 -0700 Subject: mm: switch KASan hook calling order in page alloc/free path When CONFIG_PAGE_POISONING is enabled, the pages are poisoned after setting free page in KASan Shadow memory and KASan reports the read after free warning. The same thing happens in the allocation path. So change the order of calling KASan_alloc/free API so that pages poisoning happens when the pages are in alloc status in KASan shadow memory. following is the KASan report for reference. ================================================================== BUG: KASan: use after free in memset+0x24/0x44 at addr ffffffc000000000 Write of size 4096 by task swapper/0 page:ffffffbac5000000 count:0 mapcount:0 mapping: (null) index:0x0 flags: 0x0() page dumped because: kasan: bad access detected CPU: 0 PID: 0 Comm: swapper Not tainted 3.18.0-g5a4a5d5-07242-g6938a8b-dirty #1 Hardware name: Qualcomm Technologies, Inc. MSM 8996 v2 + PMI8994 MTP (DT) Call trace: [] dump_backtrace+0x0/0x1c4 [] show_stack+0x10/0x1c [] dump_stack+0x74/0xc8 [] kasan_report_error+0x2b0/0x408 [] kasan_report+0x34/0x40 [] __asan_storeN+0x15c/0x168 [] memset+0x20/0x44 [] kernel_map_pages+0x238/0x2a8 [] free_pages_prepare+0x21c/0x25c [] __free_pages_ok+0x20/0xf0 [] __free_pages+0x34/0x44 [] __free_pages_bootmem+0xf4/0x110 [] free_all_bootmem+0x160/0x1f4 [] mem_init+0x70/0x1ec [] start_kernel+0x2b8/0x4e4 [] kasan_early_init+0x154/0x160 Change-Id: Idbd3dc629be57ed55a383b069a735ae3ee7b9f05 Signed-off-by: Se Wang (Patrick) Oh --- mm/compaction.c | 2 +- mm/page_alloc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index de3e1e71cd9f..ad6ee6da933d 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -60,9 +60,9 @@ static void map_pages(struct list_head *list) struct page *page; list_for_each_entry(page, list, lru) { + kasan_alloc_pages(page, 0); arch_alloc_page(page, 0); kernel_map_pages(page, 1, 1); - kasan_alloc_pages(page, 0); } } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 5e7050897ec4..d63689fda9b4 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -972,7 +972,6 @@ static bool free_pages_prepare(struct page *page, unsigned int order) trace_mm_page_free(page, order); kmemcheck_free_shadow(page, order); - kasan_free_pages(page, order); if (PageAnon(page)) page->mapping = NULL; @@ -995,6 +994,7 @@ static bool free_pages_prepare(struct page *page, unsigned int order) } arch_free_page(page, order); kernel_map_pages(page, 1 << order, 0); + kasan_free_pages(page, order); return true; } @@ -1391,9 +1391,9 @@ static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags, set_page_private(page, 0); set_page_refcounted(page); + kasan_alloc_pages(page, order); arch_alloc_page(page, order); kernel_map_pages(page, 1 << order, 1); - kasan_alloc_pages(page, order); if (gfp_flags & __GFP_ZERO) for (i = 0; i < (1 << order); i++) -- cgit v1.2.3