From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id C79C2C433EF for ; Mon, 22 Nov 2021 12:26:20 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 37D0A6B0071; Mon, 22 Nov 2021 07:26:05 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 32C4E6B0072; Mon, 22 Nov 2021 07:26:05 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 21B016B0073; Mon, 22 Nov 2021 07:26:05 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0018.hostedemail.com [216.40.44.18]) by kanga.kvack.org (Postfix) with ESMTP id 109046B0071 for ; Mon, 22 Nov 2021 07:26:05 -0500 (EST) Received: from smtpin22.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id C597E1828C628 for ; Mon, 22 Nov 2021 12:25:54 +0000 (UTC) X-FDA: 78836487828.22.7A000BD Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) by imf15.hostedemail.com (Postfix) with ESMTP id 7C9C3D0000B1 for ; Mon, 22 Nov 2021 12:25:48 +0000 (UTC) Received: from dggpemm500020.china.huawei.com (unknown [172.30.72.54]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4HyRLK6hFsz91H2; Mon, 22 Nov 2021 20:25:13 +0800 (CST) Received: from dggpemm500001.china.huawei.com (7.185.36.107) by dggpemm500020.china.huawei.com (7.185.36.49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.20; Mon, 22 Nov 2021 20:25:39 +0800 Received: from [10.174.177.243] (10.174.177.243) by dggpemm500001.china.huawei.com (7.185.36.107) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.2308.20; Mon, 22 Nov 2021 20:25:38 +0800 Message-ID: <50a584a4-8164-2715-41a4-99468d50a0a0@huawei.com> Date: Mon, 22 Nov 2021 20:25:37 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Thunderbird/91.2.0 Subject: Re: [PATCH] mm: Delay kmemleak object creation of module_alloc() Content-Language: en-US To: Andrey Ryabinin , Dmitry Vyukov , Andrew Morton , , , , , CC: Catalin Marinas , Will Deacon , Heiko Carstens , Vasily Gorbik , Christian Borntraeger , Alexander Gordeev , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , Alexander Potapenko , Yongqiang Liu References: <20211122121742.142203-1-wangkefeng.wang@huawei.com> From: Kefeng Wang In-Reply-To: <20211122121742.142203-1-wangkefeng.wang@huawei.com> Content-Type: text/plain; charset="UTF-8"; format=flowed X-Originating-IP: [10.174.177.243] X-ClientProxiedBy: dggeme704-chm.china.huawei.com (10.1.199.100) To dggpemm500001.china.huawei.com (7.185.36.107) X-CFilter-Loop: Reflected X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: 7C9C3D0000B1 X-Stat-Signature: 79j8gr8sm8oipc9obypqw5hn3s69dsqc Authentication-Results: imf15.hostedemail.com; dkim=none; spf=pass (imf15.hostedemail.com: domain of wangkefeng.wang@huawei.com designates 45.249.212.188 as permitted sender) smtp.mailfrom=wangkefeng.wang@huawei.com; dmarc=pass (policy=quarantine) header.from=huawei.com X-HE-Tag: 1637583948-348151 Content-Transfer-Encoding: quoted-printable 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: On 2021/11/22 20:17, Kefeng Wang wrote: > Yongqiang reports a kmemleak panic when module ismod/rmmod with KASAN > enabled[1] on x86. > > The module allocate memory, and it's kmemleak_object is created success= fully, > but the KASAN shadow memory of module allocation is not ready, when kme= mleak > scan the module's pointer, it will panic due to no shadow memory. > > module_alloc > __vmalloc_node_range > kmemleak_vmalloc > kmemleak_scan > update_checksum > kasan_module_alloc > kmemleak_ignore > > The bug should exist on ARM64/S390 too, add a VM_DELAY_KMEMLEAK flags, = delay > vmalloc'ed object register of kmemleak in module_alloc(). > > [1] https://lore.kernel.org/all/6d41e2b9-4692-5ec4-b1cd-cbe29ae89739@hu= awei.com/ > Reported-by: Yongqiang Liu > Signed-off-by: Kefeng Wang > --- > arch/arm64/kernel/module.c | 4 ++-- > arch/s390/kernel/module.c | 5 +++-- > arch/x86/kernel/module.c | 7 ++++--- > include/linux/kasan.h | 4 ++-- > include/linux/vmalloc.h | 7 +++++++ > mm/kasan/shadow.c | 9 +++++++-- > mm/vmalloc.c | 3 ++- > 7 files changed, 27 insertions(+), 12 deletions(-) > > diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c > index b5ec010c481f..e6da010716d0 100644 > --- a/arch/arm64/kernel/module.c > +++ b/arch/arm64/kernel/module.c > @@ -36,7 +36,7 @@ void *module_alloc(unsigned long size) > module_alloc_end =3D MODULES_END; > =20 > p =3D __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, > - module_alloc_end, gfp_mask, PAGE_KERNEL, 0, > + module_alloc_end, gfp_mask, PAGE_KERNEL, VM_DELAY_KMEMLEAK, > NUMA_NO_NODE, __builtin_return_address(0)); > =20 > if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && > @@ -58,7 +58,7 @@ void *module_alloc(unsigned long size) > PAGE_KERNEL, 0, NUMA_NO_NODE, > __builtin_return_address(0)); > =20 > - if (p && (kasan_module_alloc(p, size) < 0)) { > + if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) { > vfree(p); > return NULL; > } > diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c > index b01ba460b7ca..8d66a93562ca 100644 > --- a/arch/s390/kernel/module.c > +++ b/arch/s390/kernel/module.c > @@ -37,14 +37,15 @@ > =20 > void *module_alloc(unsigned long size) > { > + gfp_t gfp_mask =3D GFP_KERNEL; > void *p; > =20 > if (PAGE_ALIGN(size) > MODULES_LEN) > return NULL; > p =3D __vmalloc_node_range(size, MODULE_ALIGN, MODULES_VADDR, MODULE= S_END, > - GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, > + gfp_mask, PAGE_KERNEL_EXEC, VM_DELAY_KMEMLEAK, NUMA_NO_NODE, > __builtin_return_address(0)); > - if (p && (kasan_module_alloc(p, size) < 0)) { > + if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) { > vfree(p); > return NULL; > } > diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c > index 169fb6f4cd2e..ff134d0f1ca1 100644 > --- a/arch/x86/kernel/module.c > +++ b/arch/x86/kernel/module.c > @@ -67,6 +67,7 @@ static unsigned long int get_module_load_offset(void) > =20 > void *module_alloc(unsigned long size) > { > + gfp_t gfp_mask =3D GFP_KERNEL; > void *p; > =20 > if (PAGE_ALIGN(size) > MODULES_LEN) > @@ -74,10 +75,10 @@ void *module_alloc(unsigned long size) > =20 > p =3D __vmalloc_node_range(size, MODULE_ALIGN, > MODULES_VADDR + get_module_load_offset(), > - MODULES_END, GFP_KERNEL, > - PAGE_KERNEL, 0, NUMA_NO_NODE, > + MODULES_END, gfp_mask, > + PAGE_KERNEL, VM_DELAY_KMEMLEAK, NUMA_NO_NODE, > __builtin_return_address(0)); > - if (p && (kasan_module_alloc(p, size) < 0)) { > + if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) { > vfree(p); > return NULL; > } > diff --git a/include/linux/kasan.h b/include/linux/kasan.h > index d8783b682669..89c99e5e67de 100644 > --- a/include/linux/kasan.h > +++ b/include/linux/kasan.h > @@ -474,12 +474,12 @@ static inline void kasan_populate_early_vm_area_s= hadow(void *start, > * allocations with real shadow memory. With KASAN vmalloc, the speci= al > * case is unnecessary, as the work is handled in the generic case. > */ > -int kasan_module_alloc(void *addr, size_t size); > +int kasan_module_alloc(void *addr, size_t size, gfp_t gfp_mask); > void kasan_free_shadow(const struct vm_struct *vm); > =20 > #else /* (CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS) && !CONFIG_KA= SAN_VMALLOC */ > =20 > -static inline int kasan_module_alloc(void *addr, size_t size) { return= 0; } > +static inline int kasan_module_alloc(void *addr, size_t size, gfp_t gf= p_mask) { return 0; } > static inline void kasan_free_shadow(const struct vm_struct *vm) {} > =20 > #endif /* (CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS) && !CONFIG_K= ASAN_VMALLOC */ > diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h > index 6e022cc712e6..56d2b7828b31 100644 > --- a/include/linux/vmalloc.h > +++ b/include/linux/vmalloc.h > @@ -28,6 +28,13 @@ struct notifier_block; /* in notifier.h */ > #define VM_MAP_PUT_PAGES 0x00000200 /* put pages and free array in vf= ree */ > #define VM_NO_HUGE_VMAP 0x00000400 /* force PAGE_SIZE pte mapping */ > =20 > +#if defined(CONFIG_KASAN) && (defined(CONFIG_KASAN_GENERIC) || \ > + defined(CONFIG_KASAN_SW_TAGS)) && !defined(CONFIG_KASAN_VMALLOC) > +#define VM_DELAY_KMEMLEAK 0x00000800 /* delay kmemleak object create *= / > +#else > +#define VM_DELAY_KMEMLEAK 0 > +#endif > + > /* > * VM_KASAN is used slightly differently depending on CONFIG_KASAN_VM= ALLOC. > * > diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c > index 4a4929b29a23..6ca43b43419b 100644 > --- a/mm/kasan/shadow.c > +++ b/mm/kasan/shadow.c > @@ -498,7 +498,7 @@ void kasan_release_vmalloc(unsigned long start, uns= igned long end, > =20 > #else /* CONFIG_KASAN_VMALLOC */ > =20 > -int kasan_module_alloc(void *addr, size_t size) > +int kasan_module_alloc(void *addr, size_t size, gfp_mask) > { > void *ret; > size_t scaled_size; > @@ -520,9 +520,14 @@ int kasan_module_alloc(void *addr, size_t size) > __builtin_return_address(0)); > =20 > if (ret) { > + struct vm_struct *vm =3D find_vm_area(addr); > __memset(ret, KASAN_SHADOW_INIT, shadow_size); > - find_vm_area(addr)->flags |=3D VM_KASAN; > + vm->flags |=3D VM_KASAN; > kmemleak_ignore(ret); > + > + if (vm->flags | VM_DELAY_KMEMLEAK) should=C2=A0=C2=A0=C2=A0 if (vm->flags & VM_DELAY_KMEMLEAK),=C2=A0 let's = wait more comments,=20 and will update. > + kmemleak_vmalloc(vm, size, gfp_mask); > + > return 0; > } > =20 > diff --git a/mm/vmalloc.c b/mm/vmalloc.c > index d2a00ad4e1dd..23c595b15839 100644 > --- a/mm/vmalloc.c > +++ b/mm/vmalloc.c > @@ -3074,7 +3074,8 @@ void *__vmalloc_node_range(unsigned long size, un= signed long align, > clear_vm_uninitialized_flag(area); > =20 > size =3D PAGE_ALIGN(size); > - kmemleak_vmalloc(area, size, gfp_mask); > + if (!(vm_flags & VM_DELAY_KMEMLEAK)) > + kmemleak_vmalloc(area, size, gfp_mask); > =20 > return addr; > =20