Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753217AbaKYM2f (ORCPT ); Tue, 25 Nov 2014 07:28:35 -0500 Received: from mail-ob0-f182.google.com ([209.85.214.182]:40132 "EHLO mail-ob0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753089AbaKYM2c (ORCPT ); Tue, 25 Nov 2014 07:28:32 -0500 MIME-Version: 1.0 In-Reply-To: <1416852146-9781-5-git-send-email-a.ryabinin@samsung.com> References: <1404905415-9046-1-git-send-email-a.ryabinin@samsung.com> <1416852146-9781-1-git-send-email-a.ryabinin@samsung.com> <1416852146-9781-5-git-send-email-a.ryabinin@samsung.com> From: Dmitry Chernenkov Date: Tue, 25 Nov 2014 16:28:12 +0400 Message-ID: Subject: Re: [PATCH v7 04/12] mm: page_alloc: add kasan hooks on alloc and free paths To: Andrey Ryabinin Cc: Andrew Morton , Dmitry Vyukov , Konstantin Serebryany , Andrey Konovalov , Yuri Gribov , Konstantin Khlebnikov , Sasha Levin , Christoph Lameter , Joonsoo Kim , Dave Hansen , Andi Kleen , Vegard Nossum , "H. Peter Anvin" , Dave Jones , "x86@kernel.org" , "linux-mm@kvack.org" , LKML Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org LGTM On Mon, Nov 24, 2014 at 9:02 PM, Andrey Ryabinin wrote: > 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 > --- > include/linux/kasan.h | 6 ++++++ > mm/compaction.c | 2 ++ > mm/kasan/kasan.c | 14 ++++++++++++++ > mm/kasan/kasan.h | 1 + > mm/kasan/report.c | 7 +++++++ > mm/page_alloc.c | 3 +++ > 6 files changed, 33 insertions(+) > > diff --git a/include/linux/kasan.h b/include/linux/kasan.h > index 01c99fe..9714fba 100644 > --- a/include/linux/kasan.h > +++ b/include/linux/kasan.h > @@ -30,6 +30,9 @@ static inline void kasan_disable_local(void) > > void kasan_unpoison_shadow(const void *address, size_t size); > > +void kasan_alloc_pages(struct page *page, unsigned int order); > +void kasan_free_pages(struct page *page, unsigned int order); > + > #else /* CONFIG_KASAN */ > > static inline void kasan_unpoison_shadow(const void *address, size_t size) {} > @@ -37,6 +40,9 @@ static inline void kasan_unpoison_shadow(const void *address, size_t size) {} > static inline void kasan_enable_local(void) {} > static inline void kasan_disable_local(void) {} > > +static inline void kasan_alloc_pages(struct page *page, unsigned int order) {} > +static inline void kasan_free_pages(struct page *page, unsigned int order) {} > + > #endif /* CONFIG_KASAN */ > > #endif /* LINUX_KASAN_H */ > diff --git a/mm/compaction.c b/mm/compaction.c > index a857225..a5c8e84 100644 > --- a/mm/compaction.c > +++ b/mm/compaction.c > @@ -16,6 +16,7 @@ > #include > #include > #include > +#include > #include "internal.h" > > #ifdef CONFIG_COMPACTION > @@ -61,6 +62,7 @@ static void map_pages(struct list_head *list) > list_for_each_entry(page, list, lru) { > arch_alloc_page(page, 0); > kernel_map_pages(page, 1, 1); > + kasan_alloc_pages(page, 0); > } > } > > diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c > index f77be01..b336073 100644 > --- a/mm/kasan/kasan.c > +++ b/mm/kasan/kasan.c > @@ -247,6 +247,20 @@ static __always_inline void check_memory_region(unsigned long addr, > kasan_report(addr, size, write); > } > > +void kasan_alloc_pages(struct page *page, unsigned int order) > +{ > + if (likely(!PageHighMem(page))) > + kasan_unpoison_shadow(page_address(page), PAGE_SIZE << order); > +} > + > +void kasan_free_pages(struct page *page, unsigned int order) > +{ > + if (likely(!PageHighMem(page))) > + kasan_poison_shadow(page_address(page), > + PAGE_SIZE << order, > + KASAN_FREE_PAGE); > +} > + > void __asan_load1(unsigned long addr) > { > check_memory_region(addr, 1, false); > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h > index 6da1d78..2a6a961 100644 > --- a/mm/kasan/kasan.h > +++ b/mm/kasan/kasan.h > @@ -6,6 +6,7 @@ > #define KASAN_SHADOW_SCALE_SIZE (1UL << KASAN_SHADOW_SCALE_SHIFT) > #define KASAN_SHADOW_MASK (KASAN_SHADOW_SCALE_SIZE - 1) > > +#define KASAN_FREE_PAGE 0xFF /* page was freed */ > #define KASAN_SHADOW_GAP 0xF9 /* address belongs to shadow memory */ > > struct access_info { > diff --git a/mm/kasan/report.c b/mm/kasan/report.c > index 56a2089..8ac3b6b 100644 > --- a/mm/kasan/report.c > +++ b/mm/kasan/report.c > @@ -57,6 +57,9 @@ static void print_error_description(struct access_info *info) > case 0 ... KASAN_SHADOW_SCALE_SIZE - 1: > bug_type = "out of bounds access"; > break; > + case KASAN_FREE_PAGE: > + bug_type = "use after free"; > + break; > case KASAN_SHADOW_GAP: > bug_type = "wild memory access"; > break; > @@ -78,6 +81,10 @@ static void print_address_description(struct access_info *info) > page = virt_to_head_page((void *)info->access_addr); > > switch (shadow_val) { > + case KASAN_FREE_PAGE: > + dump_page(page, "kasan error"); > + dump_stack(); > + break; > case KASAN_SHADOW_GAP: > pr_err("No metainfo is available for this access.\n"); > dump_stack(); > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index b0e6eab..3829589 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -58,6 +58,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -758,6 +759,7 @@ 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; > @@ -940,6 +942,7 @@ static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags) > > arch_alloc_page(page, order); > kernel_map_pages(page, 1 << order, 1); > + kasan_alloc_pages(page, order); > > if (gfp_flags & __GFP_ZERO) > prep_zero_page(page, order, gfp_flags); > -- > 2.1.3 > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/