From patchwork Mon May 11 02:31:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Wu X-Patchwork-Id: 11539623 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3CE14913 for ; Mon, 11 May 2020 02:32:06 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id E2B6A208CA for ; Mon, 11 May 2020 02:32:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="RrigfM2l" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E2B6A208CA Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 1955E8E000A; Sun, 10 May 2020 22:32:05 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 148318E0001; Sun, 10 May 2020 22:32:05 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 05CCE8E000A; Sun, 10 May 2020 22:32:05 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0085.hostedemail.com [216.40.44.85]) by kanga.kvack.org (Postfix) with ESMTP id E24788E0001 for ; Sun, 10 May 2020 22:32:04 -0400 (EDT) Received: from smtpin05.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id A7957180AD80F for ; Mon, 11 May 2020 02:32:04 +0000 (UTC) X-FDA: 76802863368.05.cause26_2f110853b510f X-Spam-Summary: 2,0,0,5f6755dcbc6039f6,d41d8cd98f00b204,walter-zh.wu@mediatek.com,,RULES_HIT:1:2:41:69:355:379:541:800:960:965:966:967:968:973:988:989:1185:1260:1277:1311:1313:1314:1345:1431:1437:1514:1515:1516:1518:1585:1605:1730:1747:1777:1792:1981:2194:2196:2198:2199:2200:2201:2393:2525:2559:2563:2682:2685:2693:2731:2859:2892:2933:2937:2939:2942:2945:2947:2951:2954:3022:3138:3139:3140:3141:3142:3865:3866:3867:3870:3871:3872:3874:3934:3936:3938:3941:3944:3947:3950:3953:3956:3959:4050:4250:4321:4385:4390:4395:5007:6261:6653:7875:8555:8603:9025:9592:10004:11026:11473:11658:11914:12043:12048:12291:12296:12297:12438:12521:12555:12683:12698:12737:12895:12986:14394:21080:21451:21627:21990:30045:30054:30070:30075,0,RBL:210.61.82.184:@mediatek.com:.lbl8.mailshell.net-62.2.12.100 64.100.201.201,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:24,LUA_SUMMARY:none X-HE-Tag: cause26_2f110853b510f X-Filterd-Recvd-Size: 12018 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) by imf22.hostedemail.com (Postfix) with ESMTP for ; Mon, 11 May 2020 02:32:03 +0000 (UTC) X-UUID: 2c9984473f0248cbbc37d7100aa5dae1-20200511 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID:Date:Subject:CC:To:From; bh=AKvJsme/BN0IY0oO7wwke7B4wAJvK+2g3DFOzBvrhf0=; b=RrigfM2lQhETnypvFTLuZl8aFBr0LH8YjK9jp09D0jR7PKCh1HZX+jDGk2OeMVOss6TqaOv7iOh6Z2sCNtEPO6lqXrjpOw8yIok8j0Lr1lKkG/w9pXaAAyMg69L8nyW/Cq7IVsfDIV1/FxYpI9ollOKKkSo9JbCc4DdoyS7fuVA=; X-UUID: 2c9984473f0248cbbc37d7100aa5dae1-20200511 Received: from mtkcas06.mediatek.inc [(172.21.101.30)] by mailgw02.mediatek.com (envelope-from ) (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) with ESMTP id 1731409954; Mon, 11 May 2020 10:31:56 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs01n1.mediatek.inc (172.21.101.68) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 11 May 2020 10:31:55 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 11 May 2020 10:31:55 +0800 From: Walter Wu To: Andrey Ryabinin , Alexander Potapenko , Dmitry Vyukov , Matthias Brugger CC: , , , , wsd_upstream , , Walter Wu Subject: [PATCH v2 2/3] kasan: record and print the free track Date: Mon, 11 May 2020 10:31:53 +0800 Message-ID: <20200511023153.15376-1-walter-zh.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 MIME-Version: 1.0 X-MTK: N X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: In order not to enlarge slub meta-data size, so we move free track from slub meta-data (struct kasan_alloc_meta) into freed object. Modification of struct kasan_alloc_meta: - add two call_rcu() stack into kasan_alloc_meta, size is 8 bytes. - remove free track from kasan_alloc_meta, size is 8 bytes. Because free track is stored in freed object, so that if it is an allocation objects, then it will not have free track information in KASAN report. This feature is only suitable for generic KASAN, because we need to know whether objects are allocation or free. - if slub object is allocation state, it will not print free stack. - if slub oeject is free state, it will print free stack. [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437 Signed-off-by: Walter Wu Suggested-by: Dmitry Vyukov Cc: Andrey Ryabinin Cc: Dmitry Vyukov Cc: Alexander Potapenko --- mm/kasan/common.c | 22 ++-------------------- mm/kasan/generic.c | 22 ++++++++++++++++++++++ mm/kasan/kasan.h | 4 ++++ mm/kasan/report.c | 28 +++++----------------------- mm/kasan/tags.c | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 43 deletions(-) diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 8bc618289bb1..47b53912f322 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags) return stack_depot_save(entries, nr_entries, flags); } -static inline void set_track(struct kasan_track *track, gfp_t flags) +void kasan_set_track(struct kasan_track *track, gfp_t flags) { track->pid = current->pid; track->stack = kasan_save_stack(flags); @@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct kmem_cache *cache, return (void *)object + cache->kasan_info.free_meta_offset; } - -static void kasan_set_free_info(struct kmem_cache *cache, - void *object, u8 tag) -{ - struct kasan_alloc_meta *alloc_meta; - u8 idx = 0; - - alloc_meta = get_alloc_info(cache, object); - -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY - idx = alloc_meta->free_track_idx; - alloc_meta->free_pointer_tag[idx] = tag; - alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS; -#endif - - set_track(&alloc_meta->free_track[idx], GFP_NOWAIT); -} - void kasan_poison_slab(struct page *page) { unsigned long i; @@ -492,7 +474,7 @@ static void *__kasan_kmalloc(struct kmem_cache *cache, const void *object, KASAN_KMALLOC_REDZONE); if (cache->flags & SLAB_KASAN) - set_track(&get_alloc_info(cache, object)->alloc_track, flags); + kasan_set_track(&get_alloc_info(cache, object)->alloc_track, flags); return set_tag(object, tag); } diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c index b86880c338e2..dacff05a8107 100644 --- a/mm/kasan/generic.c +++ b/mm/kasan/generic.c @@ -354,3 +354,25 @@ struct kasan_track *kasan_get_aux_stack(struct kasan_alloc_meta *alloc_info, return container_of(&alloc_info->rcu_stack[idx], struct kasan_track, stack); } + +void kasan_set_free_info(struct kmem_cache *cache, + void *object, u8 tag) +{ + /* store free track into freed object */ + kasan_set_track((struct kasan_track *)(object + SIZEOF_PTR), GFP_NOWAIT); +} + +struct kasan_track *kasan_get_free_track(struct kmem_cache *cache, + void *object, u8 tag, const void *addr) +{ + u8 *shadow_addr = (u8 *)kasan_mem_to_shadow(addr); + + /* + * Only the freed object can get free track, + * because free track information is stored to freed object. + */ + if (*shadow_addr == KASAN_KMALLOC_FREE) + return (struct kasan_track *)(object + SIZEOF_PTR); + else + return NULL; +} diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index 1cc1fb7b0de3..f88d13f86ed3 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -173,6 +173,10 @@ void kasan_report_invalid_free(void *object, unsigned long ip); struct page *kasan_addr_to_page(const void *addr); depot_stack_handle_t kasan_save_stack(gfp_t flags); +void kasan_set_track(struct kasan_track *track, gfp_t flags); +void kasan_set_free_info(struct kmem_cache *cache, void *object, u8 tag); +struct kasan_track *kasan_get_free_track(struct kmem_cache *cache, + void *object, u8 tag, const void *addr); #if defined(CONFIG_KASAN_GENERIC) && \ (defined(CONFIG_SLAB) || defined(CONFIG_SLUB)) diff --git a/mm/kasan/report.c b/mm/kasan/report.c index f16a1a210815..51813f02992c 100644 --- a/mm/kasan/report.c +++ b/mm/kasan/report.c @@ -163,26 +163,6 @@ static void describe_object_addr(struct kmem_cache *cache, void *object, (void *)(object_addr + cache->object_size)); } -static struct kasan_track *kasan_get_free_track(struct kmem_cache *cache, - void *object, u8 tag) -{ - struct kasan_alloc_meta *alloc_meta; - int i = 0; - - alloc_meta = get_alloc_info(cache, object); - -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY - for (i = 0; i < KASAN_NR_FREE_STACKS; i++) { - if (alloc_meta->free_pointer_tag[i] == tag) - break; - } - if (i == KASAN_NR_FREE_STACKS) - i = alloc_meta->free_track_idx; -#endif - - return &alloc_meta->free_track[i]; -} - static void describe_object(struct kmem_cache *cache, void *object, const void *addr, u8 tag) { @@ -193,9 +173,11 @@ static void describe_object(struct kmem_cache *cache, void *object, print_track(&alloc_info->alloc_track, "Allocated", false); pr_err("\n"); - free_track = kasan_get_free_track(cache, object, tag); - print_track(free_track, "Freed", false); - pr_err("\n"); + free_track = kasan_get_free_track(cache, object, tag, addr); + if (free_track) { + print_track(free_track, "Freed", false); + pr_err("\n"); + } if (IS_ENABLED(CONFIG_KASAN_GENERIC)) { free_track = kasan_get_aux_stack(alloc_info, 0); diff --git a/mm/kasan/tags.c b/mm/kasan/tags.c index 25b7734e7013..30a27f8c1e6e 100644 --- a/mm/kasan/tags.c +++ b/mm/kasan/tags.c @@ -162,3 +162,40 @@ void __hwasan_tag_memory(unsigned long addr, u8 tag, unsigned long size) kasan_poison_shadow((void *)addr, size, tag); } EXPORT_SYMBOL(__hwasan_tag_memory); + +void kasan_set_free_info(struct kmem_cache *cache, + void *object, u8 tag) +{ + struct kasan_alloc_meta *alloc_meta; + u8 idx = 0; + + alloc_meta = get_alloc_info(cache, object); + +#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY + idx = alloc_meta->free_track_idx; + alloc_meta->free_pointer_tag[idx] = tag; + alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS; +#endif + + kasan_set_track(&alloc_meta->free_track[idx], GFP_NOWAIT); +} + +struct kasan_track *kasan_get_free_track(struct kmem_cache *cache, + void *object, u8 tag, const void *addr) +{ + struct kasan_alloc_meta *alloc_meta; + int i = 0; + + alloc_meta = get_alloc_info(cache, object); + +#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY + for (i = 0; i < KASAN_NR_FREE_STACKS; i++) { + if (alloc_meta->free_pointer_tag[i] == tag) + break; + } + if (i == KASAN_NR_FREE_STACKS) + i = alloc_meta->free_track_idx; +#endif + + return &alloc_meta->free_track[i]; +}