Received: by 2002:a25:c593:0:0:0:0:0 with SMTP id v141csp5994827ybe; Tue, 10 Sep 2019 11:53:53 -0700 (PDT) X-Google-Smtp-Source: APXvYqz89L60rJbYZo4+9yyFhMX9PW4a/T8ZH68JDSZk/NLeBYgY3NSj9q/xLEduY2d9YAgKlSwQ X-Received: by 2002:a17:906:804d:: with SMTP id x13mr25938901ejw.134.1568141633740; Tue, 10 Sep 2019 11:53:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1568141633; cv=none; d=google.com; s=arc-20160816; b=duJ3OilZnu1bCwERBsRXJL8VOlYeTPLe7w3vV1YXxtd+b74uat0JXJ12LPeWjalBYi ScgTKaTsgzl8/xGt21lgDyf5YsHFAZk05alOeWDZtmuYRjOoJnpYOR3ngOvYe5a4pGAw sEOnGpFdaP3BiS+jilt9Jlefm3uJbs9kp+Sb4BajDCCnRTLOSUlWFUaxmNSPwkYPT8lN Ft2tTwwOa9LGKX7efiDNYzighQvvKWq4T+fgWwv0Ir/TJwqYbkbPXsj7EdSq+5WASoMI J5yG0BTZEonmAGsO+eLmLQ6nYW93JJ+gWl2pkTdYCxjqguFAZEPhXVIvQJdxLwyE4ea2 eWKw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:content-transfer-encoding :references:in-reply-to:date:cc:to:from:subject:message-id; bh=uMUjVEOW6+klAW0D/p3IklnpSnYgShMcjEeYN7symRI=; b=h8oFlAkf/fdCZGcxo7CUDSLkArKUT4Gim8PRyD3516z/IGo6jabNCpA7ZuCZl8MZ2h I9ojDdQWuPXjuGDJjoJkfa64m7FfW/+61ImX2ok4qNr4g2MsVLLC9sV4ZjTay7ez/IwJ 35GzAZKIhZ4VQbIyH2PcIdRVoNZOkxj9eQm11UMGqburdQtNNOrqnh8nTEN2j6Dw8G7S GxWsEzF7mmwRT5ddY0uSAW3pJ9aSm0DMYdFSJixruEdtYrtTXCs3abmdeDCE1rIxr19R dE7JP9WB7quhleqLhpQRbe1kxXcS1A2NZTmJQjzjvzKA6YSknlqrw+17/89ZCN5TUdLm Ys5g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a48si11427662edd.196.2019.09.10.11.53.29; Tue, 10 Sep 2019 11:53:53 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391506AbfIJJxb (ORCPT + 99 others); Tue, 10 Sep 2019 05:53:31 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:61529 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1727557AbfIJJxb (ORCPT ); Tue, 10 Sep 2019 05:53:31 -0400 X-UUID: 39136821071a4a61acaf347912375c23-20190910 X-UUID: 39136821071a4a61acaf347912375c23-20190910 Received: from mtkmrs01.mediatek.inc [(172.21.131.159)] by mailgw02.mediatek.com (envelope-from ) (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) with ESMTP id 761175253; Tue, 10 Sep 2019 17:53:25 +0800 Received: from mtkcas08.mediatek.inc (172.21.101.126) by mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Tue, 10 Sep 2019 17:53:23 +0800 Received: from [172.21.84.99] (172.21.84.99) by mtkcas08.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Tue, 10 Sep 2019 17:53:23 +0800 Message-ID: <1568109204.24886.14.camel@mtksdccf07> Subject: Re: [PATCH v2 0/2] mm/kasan: dump alloc/free stack for page allocator From: Walter Wu To: Andrey Ryabinin , Dmitry Vyukov , Andrey Konovalov , "Arnd Bergmann" , Qian Cai CC: Alexander Potapenko , Matthias Brugger , Andrew Morton , "Martin Schwidefsky" , Will Deacon , "Thomas Gleixner" , Michal Hocko , , , , , , Date: Tue, 10 Sep 2019 17:53:24 +0800 In-Reply-To: <20190909082412.24356-1-walter-zh.wu@mediatek.com> References: <20190909082412.24356-1-walter-zh.wu@mediatek.com> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.2.3-0ubuntu6 Content-Transfer-Encoding: 7bit MIME-Version: 1.0 X-MTK: N Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 2019-09-09 at 16:24 +0800, walter-zh.wu@mediatek.com wrote: > From: Walter Wu > > This patch is KASAN report adds the alloc/free stacks for page allocator > in order to help programmer to see memory corruption caused by page. > > By default, KASAN doesn't record alloc and free stack for page allocator. > It is difficult to fix up page use-after-free or dobule-free issue. > > Our patchsets will record the last stack of pages. > It is very helpful for solving the page use-after-free or double-free. > > KASAN report will show the last stack of page, it may be: > a) If page is in-use state, then it prints alloc stack. > It is useful to fix up page out-of-bound issue. > > BUG: KASAN: slab-out-of-bounds in kmalloc_pagealloc_oob_right+0x88/0x90 > Write of size 1 at addr ffffffc0d64ea00a by task cat/115 > ... > Allocation stack of page: > set_page_stack.constprop.1+0x30/0xc8 > kasan_alloc_pages+0x18/0x38 > prep_new_page+0x5c/0x150 > get_page_from_freelist+0xb8c/0x17c8 > __alloc_pages_nodemask+0x1a0/0x11b0 > kmalloc_order+0x28/0x58 > kmalloc_order_trace+0x28/0xe0 > kmalloc_pagealloc_oob_right+0x2c/0x68 > > b) If page is freed state, then it prints free stack. > It is useful to fix up page use-after-free or double-free issue. > > BUG: KASAN: use-after-free in kmalloc_pagealloc_uaf+0x70/0x80 > Write of size 1 at addr ffffffc0d651c000 by task cat/115 > ... > Free stack of page: > kasan_free_pages+0x68/0x70 > __free_pages_ok+0x3c0/0x1328 > __free_pages+0x50/0x78 > kfree+0x1c4/0x250 > kmalloc_pagealloc_uaf+0x38/0x80 > > This has been discussed, please refer below link. > https://bugzilla.kernel.org/show_bug.cgi?id=203967 > > Changes since v1: > - slim page_owner and move it into kasan > - enable the feature by default > > Signed-off-by: Walter Wu > --- > include/linux/kasan.h | 1 + > lib/Kconfig.kasan | 2 ++ > mm/kasan/common.c | 32 ++++++++++++++++++++++++++++++++ > mm/kasan/kasan.h | 5 +++++ > mm/kasan/report.c | 27 +++++++++++++++++++++++++++ > 5 files changed, 67 insertions(+) > > diff --git a/include/linux/kasan.h b/include/linux/kasan.h > index cc8a03cc9674..97e1bcb20489 100644 > --- a/include/linux/kasan.h > +++ b/include/linux/kasan.h > @@ -19,6 +19,7 @@ extern pte_t kasan_early_shadow_pte[PTRS_PER_PTE]; > extern pmd_t kasan_early_shadow_pmd[PTRS_PER_PMD]; > extern pud_t kasan_early_shadow_pud[PTRS_PER_PUD]; > extern p4d_t kasan_early_shadow_p4d[MAX_PTRS_PER_P4D]; > +extern struct page_ext_operations page_stack_ops; > > int kasan_populate_early_shadow(const void *shadow_start, > const void *shadow_end); > diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan > index 4fafba1a923b..b5a9410ba4e8 100644 > --- a/lib/Kconfig.kasan > +++ b/lib/Kconfig.kasan > @@ -41,6 +41,7 @@ config KASAN_GENERIC > select SLUB_DEBUG if SLUB > select CONSTRUCTORS > select STACKDEPOT > + select PAGE_EXTENSION > help > Enables generic KASAN mode. > Supported in both GCC and Clang. With GCC it requires version 4.9.2 > @@ -63,6 +64,7 @@ config KASAN_SW_TAGS > select SLUB_DEBUG if SLUB > select CONSTRUCTORS > select STACKDEPOT > + select PAGE_EXTENSION > help > Enables software tag-based KASAN mode. > This mode requires Top Byte Ignore support by the CPU and therefore > diff --git a/mm/kasan/common.c b/mm/kasan/common.c > index 2277b82902d8..c349143d2587 100644 > --- a/mm/kasan/common.c > +++ b/mm/kasan/common.c > @@ -211,10 +211,38 @@ void kasan_unpoison_stack_above_sp_to(const void *watermark) > kasan_unpoison_shadow(sp, size); > } > > +static bool need_page_stack(void) > +{ > + return true; > +} > + > +struct page_ext_operations page_stack_ops = { > + .size = sizeof(depot_stack_handle_t), > + .need = need_page_stack, > +}; > + > +static void set_page_stack(struct page *page, gfp_t gfp_mask) > +{ > + struct page_ext *page_ext = lookup_page_ext(page); > + depot_stack_handle_t handle; > + depot_stack_handle_t *page_stack; > + > + if (unlikely(!page_ext)) > + return; > + > + handle = save_stack(gfp_mask); > + > + page_stack = get_page_stack(page_ext); > + *page_stack = handle; > +} > + > void kasan_alloc_pages(struct page *page, unsigned int order) > { > u8 tag; > unsigned long i; > + gfp_t gfp_flags = GFP_KERNEL; > + > + set_page_stack(page, gfp_flags); > > if (unlikely(PageHighMem(page))) > return; > @@ -227,6 +255,10 @@ void kasan_alloc_pages(struct page *page, unsigned int order) > > void kasan_free_pages(struct page *page, unsigned int order) > { > + gfp_t gfp_flags = GFP_KERNEL; > + > + set_page_stack(page, gfp_flags); > + > if (likely(!PageHighMem(page))) > kasan_poison_shadow(page_address(page), > PAGE_SIZE << order, > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h > index 014f19e76247..95b3b510d04f 100644 > --- a/mm/kasan/kasan.h > +++ b/mm/kasan/kasan.h > @@ -126,6 +126,11 @@ static inline bool addr_has_shadow(const void *addr) > return (addr >= kasan_shadow_to_mem((void *)KASAN_SHADOW_START)); > } > > +static inline depot_stack_handle_t *get_page_stack(struct page_ext *page_ext) > +{ > + return (void *)page_ext + page_stack_ops.offset; > +} > + > void kasan_poison_shadow(const void *address, size_t size, u8 value); > > /** > diff --git a/mm/kasan/report.c b/mm/kasan/report.c > index 0e5f965f1882..2e26bc192114 100644 > --- a/mm/kasan/report.c > +++ b/mm/kasan/report.c > @@ -344,6 +344,32 @@ static void print_address_stack_frame(const void *addr) > print_decoded_frame_descr(frame_descr); > } > > +static void dump_page_stack(struct page *page) > +{ > + struct page_ext *page_ext = lookup_page_ext(page); > + depot_stack_handle_t handle; > + unsigned long *entries; > + unsigned int nr_entries; > + depot_stack_handle_t *page_stack; > + > + if (unlikely(!page_ext)) > + return; > + > + page_stack = get_page_stack(page_ext); > + > + handle = READ_ONCE(*page_stack); > + if (!handle) > + return; > + > + if ((unsigned long)page->flags & PAGE_FLAGS_CHECK_AT_PREP) > + pr_info("Allocation stack of page:\n"); > + else > + pr_info("Free stack of page:\n"); > + > + nr_entries = stack_depot_fetch(handle, &entries); > + stack_trace_print(entries, nr_entries, 0); > +} > + > static void print_address_description(void *addr) > { > struct page *page = addr_to_page(addr); > @@ -366,6 +392,7 @@ static void print_address_description(void *addr) > if (page) { > pr_err("The buggy address belongs to the page:\n"); > dump_page(page, "kasan: bad access detected"); > + dump_page_stack(page); > } > > print_address_stack_frame(addr); Hi All, We implement another version, it is different with v1. We hope that you can give an ideas and make the KASAN report better. If it is possible, we can use the less memory to show the corruption information that is enough to help programmer to fix up memory corruption. Thanks. Walter