From nobody Tue Apr 28 07:43:03 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60A56C43334 for ; Fri, 3 Jun 2022 03:54:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237485AbiFCDyh (ORCPT ); Thu, 2 Jun 2022 23:54:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46316 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235311AbiFCDy2 (ORCPT ); Thu, 2 Jun 2022 23:54:28 -0400 Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B20E5313AE for ; Thu, 2 Jun 2022 20:54:26 -0700 (PDT) Received: by mail-pf1-x42c.google.com with SMTP id z17so6301941pff.7 for ; Thu, 02 Jun 2022 20:54:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AE33Ihqv1t9aLq7UPLG/US1ju2jh1U/6t4mE/T1uzCg=; b=O+PNjUduciX7Xx08NHo//9gZ1MAEWBk7QW4BZVAqte9EfoplTolcAt+C4rlOHX5Y7s XpVXx6r7vudrBQucENUyiRG9cLbeMhQSpAdY9AgLB0F5sPYCGcLVM4Y/wLLz8rAZWtXi 9HjRYy00A3RgYoP6Pe3jIAc4UOWe9+8jDWcFlPjrf8P0OZQOdcx/Bq2Sm1lb1xfnPRDw CxkUOpF30dsuRuMIerewZZj3TdikR2r1SdQqI6DBsY1ogN5ZJIlQO2QRdpehdy1M+9f3 iHYnrtfvugrsRyx1qI0D+fnq3WYXzcDJ0Im55sARe2ngvOex1lZ9ciCymoWdgrvHRCaK hQnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=AE33Ihqv1t9aLq7UPLG/US1ju2jh1U/6t4mE/T1uzCg=; b=XcSHhyeVMteJKbqX3fnFYY5VRX7lLz4vF07WOrW9k4pLFOuDscdnEVIYacm3Vlxd8f TcryVsPJhAwTI41hJKaPt9FT+AiHszqgKcvBg5UkSp73s2+5gHiI7ULDx/YuUem/TKO9 G/Fw7rAIOdHJGKaxxKjALHMS5Zv8PafGPfr3F4g7A+46LXr3lREpj7Limq7CcnQnK4Wx m9pkeTL7JwwBgwZ8/UNO04b2w95XuZlJKd6nC3fAHw4rMgxfsVvtTf/s/pUuNmazHoIr OSvsUi4J2aiP0ZxTDZVo+NqmaeJYCxHSFo4lKJgC+SaRsmh7i62ztEg4/z3DKgDkIIhY SDRA== X-Gm-Message-State: AOAM530+OWYdEgj8VvqHknM8Rwd+aCP87HJytWy0pEXRge86nmV4lEst Ovc1mUApZUDftjkFD5/BOU8= X-Google-Smtp-Source: ABdhPJzWnPOllcltScI/t1jtuBfhDPeuf9KuowCerL9DyIRZH7cGHTf3p+2+jOgVwDd3tiwi8WffoQ== X-Received: by 2002:a62:7cca:0:b0:4fd:e594:fac0 with SMTP id x193-20020a627cca000000b004fde594fac0mr8389022pfc.79.1654228466183; Thu, 02 Jun 2022 20:54:26 -0700 (PDT) Received: from localhost ([101.86.206.159]) by smtp.gmail.com with ESMTPSA id 4-20020a631744000000b003fbdf7cc750sm4069329pgx.89.2022.06.02.20.54.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 02 Jun 2022 20:54:25 -0700 (PDT) From: Patrick Wang To: catalin.marinas@arm.com, akpm@linux-foundation.org Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, yee.lee@mediatek.com, patrick.wang.shcn@gmail.com Subject: [PATCH v2 1/4] mm: kmemleak: add OBJECT_PHYS flag for objects allocated with physical address Date: Fri, 3 Jun 2022 11:54:12 +0800 Message-Id: <20220603035415.1243913-2-patrick.wang.shcn@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220603035415.1243913-1-patrick.wang.shcn@gmail.com> References: <20220603035415.1243913-1-patrick.wang.shcn@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add OBJECT_PHYS flag for object. This flag is used to identify the objects allocated with physical address.The create_object() function is added an argument to set that flag. Suggested-by: Catalin Marinas Signed-off-by: Patrick Wang --- mm/kmemleak.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index a182f5ddaf68..1e9e0aa93ae5 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -172,6 +172,8 @@ struct kmemleak_object { #define OBJECT_NO_SCAN (1 << 2) /* flag set to fully scan the object when scan_area allocation failed */ #define OBJECT_FULL_SCAN (1 << 3) +/* flag set for object allocated with physical address */ +#define OBJECT_PHYS (1 << 4) =20 #define HEX_PREFIX " " /* number of bytes to print per line; must be 16 or 32 */ @@ -575,7 +577,8 @@ static int __save_stack_trace(unsigned long *trace) * memory block and add it to the object_list and object_tree_root. */ static struct kmemleak_object *create_object(unsigned long ptr, size_t siz= e, - int min_count, gfp_t gfp) + int min_count, gfp_t gfp, + bool is_phys) { unsigned long flags; struct kmemleak_object *object, *parent; @@ -595,7 +598,7 @@ static struct kmemleak_object *create_object(unsigned l= ong ptr, size_t size, INIT_HLIST_HEAD(&object->area_list); raw_spin_lock_init(&object->lock); atomic_set(&object->use_count, 1); - object->flags =3D OBJECT_ALLOCATED; + object->flags =3D OBJECT_ALLOCATED | (is_phys ? OBJECT_PHYS : 0); object->pointer =3D ptr; object->size =3D kfence_ksize((void *)ptr) ?: size; object->excess_ref =3D 0; @@ -729,10 +732,10 @@ static void delete_object_part(unsigned long ptr, siz= e_t size) end =3D object->pointer + object->size; if (ptr > start) create_object(start, ptr - start, object->min_count, - GFP_KERNEL); + GFP_KERNEL, object->flags & OBJECT_PHYS); if (ptr + size < end) create_object(ptr + size, end - ptr - size, object->min_count, - GFP_KERNEL); + GFP_KERNEL, object->flags & OBJECT_PHYS); =20 __delete_object(object); } @@ -904,7 +907,7 @@ void __ref kmemleak_alloc(const void *ptr, size_t size,= int min_count, pr_debug("%s(0x%p, %zu, %d)\n", __func__, ptr, size, min_count); =20 if (kmemleak_enabled && ptr && !IS_ERR(ptr)) - create_object((unsigned long)ptr, size, min_count, gfp); + create_object((unsigned long)ptr, size, min_count, gfp, false); } EXPORT_SYMBOL_GPL(kmemleak_alloc); =20 @@ -931,7 +934,7 @@ void __ref kmemleak_alloc_percpu(const void __percpu *p= tr, size_t size, if (kmemleak_enabled && ptr && !IS_ERR(ptr)) for_each_possible_cpu(cpu) create_object((unsigned long)per_cpu_ptr(ptr, cpu), - size, 0, gfp); + size, 0, gfp, false); } EXPORT_SYMBOL_GPL(kmemleak_alloc_percpu); =20 @@ -953,7 +956,7 @@ void __ref kmemleak_vmalloc(const struct vm_struct *are= a, size_t size, gfp_t gfp * the virtual address of the vmalloc'ed block. */ if (kmemleak_enabled) { - create_object((unsigned long)area->addr, size, 2, gfp); + create_object((unsigned long)area->addr, size, 2, gfp, false); object_set_excess_ref((unsigned long)area, (unsigned long)area->addr); } @@ -1966,14 +1969,14 @@ void __init kmemleak_init(void) =20 /* register the data/bss sections */ create_object((unsigned long)_sdata, _edata - _sdata, - KMEMLEAK_GREY, GFP_ATOMIC); + KMEMLEAK_GREY, GFP_ATOMIC, false); create_object((unsigned long)__bss_start, __bss_stop - __bss_start, - KMEMLEAK_GREY, GFP_ATOMIC); + KMEMLEAK_GREY, GFP_ATOMIC, false); /* only register .data..ro_after_init if not within .data */ if (&__start_ro_after_init < &_sdata || &__end_ro_after_init > &_edata) create_object((unsigned long)__start_ro_after_init, __end_ro_after_init - __start_ro_after_init, - KMEMLEAK_GREY, GFP_ATOMIC); + KMEMLEAK_GREY, GFP_ATOMIC, false); } =20 /* --=20 2.25.1 From nobody Tue Apr 28 07:43:03 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 61B0FC43334 for ; Fri, 3 Jun 2022 03:54:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237699AbiFCDyq (ORCPT ); Thu, 2 Jun 2022 23:54:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46484 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236531AbiFCDyb (ORCPT ); Thu, 2 Jun 2022 23:54:31 -0400 Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9979A31513 for ; Thu, 2 Jun 2022 20:54:29 -0700 (PDT) Received: by mail-pj1-x102f.google.com with SMTP id n13-20020a17090a394d00b001e30a60f82dso11137439pjf.5 for ; Thu, 02 Jun 2022 20:54:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lq9PaAAUkOHkx4AcYY1vM1d5i0BVbXyZKhkfL+qmMNk=; b=S8V6YFCOFgX8PDLZsDNJWzJsn/waZfRN2onxmJaVeXwtTEbhc8Sr74wIeEYFO7M65D KBAvBCTzPAHhFCxO/wfLlg+xYcdmK6bCuq1+8rKRtTtL6ov7PIi8sQ6IZJ+mN+LMcRVk b9ioEe7c03t+ve8kMODATqS5c9eWG97nySgXQi0nxWTHTe8C0UoRgTZ6jsehpUXDsP4D UhVYw5TUJ3P8mlEAQljHnV7y07LirOOliVUimuCVAoUQGkgruAV+tNIFxy+wUwb/YZgJ oatO0pLTRhuc03m/XlFRD3yCSL/AErzL6kqaW/aBilunXT4fOiVOolFJGxZh7ApH7kaW qYKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lq9PaAAUkOHkx4AcYY1vM1d5i0BVbXyZKhkfL+qmMNk=; b=JHBrRgyDqh/7++y1E1toj3Y829pNpsl7yhS+V/OZRiYkI/AOcviy5SPeA1iKuXiVRF j4g7NRyiGp/9rnRpw/74CecHWhyS+m85VwSBYHwp+xStLgzfCdT298EDwwxWkxlIcGM8 faN1ZC+MvqH2N0ZMdDX+1nSKe0LFU0aQklpZEip0FoRa7m4ApDmwxkzH88iW8MG+bXhX oKJUCHN9eu561cUkl0fJ+z6bgS0HQ9RwmES6WmmUSZYXPKi04fcL61Fky+yEilQIOct8 ev7fq3Mx1lS0ud1jQSFuL0wyBlmxeZ0qTjcreBtKEkF+5LLfu03sqhN/9kF4j4dVKAG+ /oaQ== X-Gm-Message-State: AOAM530Er9Ymdu9HznUyFTdROhDIEERUA6A0jV5gp6HAF66/gkJEWtvh zqvE80GuyeNLq4iIneqQjk4= X-Google-Smtp-Source: ABdhPJynxSbkQybaJsrmvd7I5qxXJyHbTUa/u2cCWN2Ll5D77yawEg+TVEUA/BZkcawq0jWXMw6TBA== X-Received: by 2002:a17:90b:3b8a:b0:1e2:f1da:bf9b with SMTP id pc10-20020a17090b3b8a00b001e2f1dabf9bmr27399469pjb.77.1654228468890; Thu, 02 Jun 2022 20:54:28 -0700 (PDT) Received: from localhost ([101.86.206.159]) by smtp.gmail.com with ESMTPSA id g7-20020a170902934700b0015e8d4eb1e5sm4245281plp.47.2022.06.02.20.54.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 02 Jun 2022 20:54:28 -0700 (PDT) From: Patrick Wang To: catalin.marinas@arm.com, akpm@linux-foundation.org Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, yee.lee@mediatek.com, patrick.wang.shcn@gmail.com Subject: [PATCH v2 2/4] mm: kmemleak: add rbtree for objects allocated with physical address Date: Fri, 3 Jun 2022 11:54:13 +0800 Message-Id: <20220603035415.1243913-3-patrick.wang.shcn@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220603035415.1243913-1-patrick.wang.shcn@gmail.com> References: <20220603035415.1243913-1-patrick.wang.shcn@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add object_phys_tree_root to store the objects allocated with physical address. Distinguish it from object_tree_root by OBJECT_PHYS flag or function argument. Suggested-by: Catalin Marinas Signed-off-by: Patrick Wang --- mm/kmemleak.c | 99 +++++++++++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 42 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 1e9e0aa93ae5..218144392446 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -14,14 +14,16 @@ * The following locks and mutexes are used by kmemleak: * * - kmemleak_lock (raw_spinlock_t): protects the object_list modification= s and - * accesses to the object_tree_root. The object_list is the main list - * holding the metadata (struct kmemleak_object) for the allocated memory - * blocks. The object_tree_root is a red black tree used to look-up - * metadata based on a pointer to the corresponding memory block. The - * kmemleak_object structures are added to the object_list and - * object_tree_root in the create_object() function called from the - * kmemleak_alloc() callback and removed in delete_object() called from = the - * kmemleak_free() callback + * accesses to the object_tree_root (or object_phys_tree_root). The + * object_list is the main list holding the metadata (struct kmemleak_ob= ject) + * for the allocated memory blocks. The object_tree_root and object_phys= _tree_root + * are red black trees used to look-up metadata based on a pointer to the + * corresponding memory block. The object_phys_tree_root is for objects + * allocated with physical address. The kmemleak_object structures are + * added to the object_list and object_tree_root (or object_phys_tree_ro= ot) + * in the create_object() function called from the kmemleak_alloc() (or + * kmemleak_alloc_phys()) callback and removed in delete_object() called= from + * the kmemleak_free() callback * - kmemleak_object.lock (raw_spinlock_t): protects a kmemleak_object. * Accesses to the metadata (e.g. count) are protected by this lock. Note * that some members of this structure may be protected by other means @@ -195,7 +197,9 @@ static int mem_pool_free_count =3D ARRAY_SIZE(mem_pool); static LIST_HEAD(mem_pool_free_list); /* search tree for object boundaries */ static struct rb_root object_tree_root =3D RB_ROOT; -/* protecting the access to object_list and object_tree_root */ +/* search tree for object (with OBJECT_PHYS flag) boundaries */ +static struct rb_root object_phys_tree_root =3D RB_ROOT; +/* protecting the access to object_list, object_tree_root (or object_phys_= tree_root) */ static DEFINE_RAW_SPINLOCK(kmemleak_lock); =20 /* allocation caches for kmemleak internal data */ @@ -380,9 +384,11 @@ static void dump_object_info(struct kmemleak_object *o= bject) * beginning of the memory block are allowed. The kmemleak_lock must be he= ld * when calling this function. */ -static struct kmemleak_object *lookup_object(unsigned long ptr, int alias) +static struct kmemleak_object *lookup_object(unsigned long ptr, int alias, + bool is_phys) { - struct rb_node *rb =3D object_tree_root.rb_node; + struct rb_node *rb =3D is_phys ? object_phys_tree_root.rb_node : + object_tree_root.rb_node; unsigned long untagged_ptr =3D (unsigned long)kasan_reset_tag((void *)ptr= ); =20 while (rb) { @@ -517,14 +523,15 @@ static void put_object(struct kmemleak_object *object) /* * Look up an object in the object search tree and increase its use_count. */ -static struct kmemleak_object *find_and_get_object(unsigned long ptr, int = alias) +static struct kmemleak_object *find_and_get_object(unsigned long ptr, int = alias, + bool is_phys) { unsigned long flags; struct kmemleak_object *object; =20 rcu_read_lock(); raw_spin_lock_irqsave(&kmemleak_lock, flags); - object =3D lookup_object(ptr, alias); + object =3D lookup_object(ptr, alias, is_phys); raw_spin_unlock_irqrestore(&kmemleak_lock, flags); =20 /* check whether the object is still available */ @@ -536,27 +543,32 @@ static struct kmemleak_object *find_and_get_object(un= signed long ptr, int alias) } =20 /* - * Remove an object from the object_tree_root and object_list. Must be cal= led - * with the kmemleak_lock held _if_ kmemleak is still enabled. + * Remove an object from the object_tree_root (or object_phys_tree_root) + * and object_list. Must be called with the kmemleak_lock held _if_ kmemle= ak + * is still enabled. */ static void __remove_object(struct kmemleak_object *object) { - rb_erase(&object->rb_node, &object_tree_root); + rb_erase(&object->rb_node, object->flags & OBJECT_PHYS ? + &object_phys_tree_root : + &object_tree_root); list_del_rcu(&object->object_list); } =20 /* * Look up an object in the object search tree and remove it from both - * object_tree_root and object_list. The returned object's use_count shoul= d be - * at least 1, as initially set by create_object(). + * object_tree_root (or object_phys_tree_root) and object_list. The + * returned object's use_count should be at least 1, as initially set + * by create_object(). */ -static struct kmemleak_object *find_and_remove_object(unsigned long ptr, i= nt alias) +static struct kmemleak_object *find_and_remove_object(unsigned long ptr, i= nt alias, + bool is_phys) { unsigned long flags; struct kmemleak_object *object; =20 raw_spin_lock_irqsave(&kmemleak_lock, flags); - object =3D lookup_object(ptr, alias); + object =3D lookup_object(ptr, alias, is_phys); if (object) __remove_object(object); raw_spin_unlock_irqrestore(&kmemleak_lock, flags); @@ -574,7 +586,8 @@ static int __save_stack_trace(unsigned long *trace) =20 /* * Create the metadata (struct kmemleak_object) corresponding to an alloca= ted - * memory block and add it to the object_list and object_tree_root. + * memory block and add it to the object_list and object_tree_root (or + * object_phys_tree_root). */ static struct kmemleak_object *create_object(unsigned long ptr, size_t siz= e, int min_count, gfp_t gfp, @@ -633,7 +646,8 @@ static struct kmemleak_object *create_object(unsigned l= ong ptr, size_t size, untagged_ptr =3D (unsigned long)kasan_reset_tag((void *)ptr); min_addr =3D min(min_addr, untagged_ptr); max_addr =3D max(max_addr, untagged_ptr + size); - link =3D &object_tree_root.rb_node; + link =3D is_phys ? &object_phys_tree_root.rb_node : + &object_tree_root.rb_node; rb_parent =3D NULL; while (*link) { rb_parent =3D *link; @@ -657,7 +671,8 @@ static struct kmemleak_object *create_object(unsigned l= ong ptr, size_t size, } } rb_link_node(&object->rb_node, rb_parent, link); - rb_insert_color(&object->rb_node, &object_tree_root); + rb_insert_color(&object->rb_node, is_phys ? &object_phys_tree_root : + &object_tree_root); =20 list_add_tail_rcu(&object->object_list, &object_list); out: @@ -693,7 +708,7 @@ static void delete_object_full(unsigned long ptr) { struct kmemleak_object *object; =20 - object =3D find_and_remove_object(ptr, 0); + object =3D find_and_remove_object(ptr, 0, false); if (!object) { #ifdef DEBUG kmemleak_warn("Freeing unknown object at 0x%08lx\n", @@ -709,12 +724,12 @@ static void delete_object_full(unsigned long ptr) * delete it. If the memory block is partially freed, the function may cre= ate * additional metadata for the remaining parts of the block. */ -static void delete_object_part(unsigned long ptr, size_t size) +static void delete_object_part(unsigned long ptr, size_t size, bool is_phy= s) { struct kmemleak_object *object; unsigned long start, end; =20 - object =3D find_and_remove_object(ptr, 1); + object =3D find_and_remove_object(ptr, 1, is_phys); if (!object) { #ifdef DEBUG kmemleak_warn("Partially freeing unknown object at 0x%08lx (size %zu)\n", @@ -756,11 +771,11 @@ static void paint_it(struct kmemleak_object *object, = int color) raw_spin_unlock_irqrestore(&object->lock, flags); } =20 -static void paint_ptr(unsigned long ptr, int color) +static void paint_ptr(unsigned long ptr, int color, bool is_phys) { struct kmemleak_object *object; =20 - object =3D find_and_get_object(ptr, 0); + object =3D find_and_get_object(ptr, 0, is_phys); if (!object) { kmemleak_warn("Trying to color unknown object at 0x%08lx as %s\n", ptr, @@ -776,18 +791,18 @@ static void paint_ptr(unsigned long ptr, int color) * Mark an object permanently as gray-colored so that it can no longer be * reported as a leak. This is used in general to mark a false positive. */ -static void make_gray_object(unsigned long ptr) +static void make_gray_object(unsigned long ptr, bool is_phys) { - paint_ptr(ptr, KMEMLEAK_GREY); + paint_ptr(ptr, KMEMLEAK_GREY, is_phys); } =20 /* * Mark the object as black-colored so that it is ignored from scans and * reporting. */ -static void make_black_object(unsigned long ptr) +static void make_black_object(unsigned long ptr, bool is_phys) { - paint_ptr(ptr, KMEMLEAK_BLACK); + paint_ptr(ptr, KMEMLEAK_BLACK, is_phys); } =20 /* @@ -802,7 +817,7 @@ static void add_scan_area(unsigned long ptr, size_t siz= e, gfp_t gfp) unsigned long untagged_ptr; unsigned long untagged_objp; =20 - object =3D find_and_get_object(ptr, 1); + object =3D find_and_get_object(ptr, 1, false); if (!object) { kmemleak_warn("Adding scan area to unknown object at 0x%08lx\n", ptr); @@ -852,7 +867,7 @@ static void object_set_excess_ref(unsigned long ptr, un= signed long excess_ref) unsigned long flags; struct kmemleak_object *object; =20 - object =3D find_and_get_object(ptr, 0); + object =3D find_and_get_object(ptr, 0, false); if (!object) { kmemleak_warn("Setting excess_ref on unknown object at 0x%08lx\n", ptr); @@ -875,7 +890,7 @@ static void object_no_scan(unsigned long ptr) unsigned long flags; struct kmemleak_object *object; =20 - object =3D find_and_get_object(ptr, 0); + object =3D find_and_get_object(ptr, 0, false); if (!object) { kmemleak_warn("Not scanning unknown object at 0x%08lx\n", ptr); return; @@ -993,7 +1008,7 @@ void __ref kmemleak_free_part(const void *ptr, size_t = size) pr_debug("%s(0x%p)\n", __func__, ptr); =20 if (kmemleak_enabled && ptr && !IS_ERR(ptr)) - delete_object_part((unsigned long)ptr, size); + delete_object_part((unsigned long)ptr, size, false); } EXPORT_SYMBOL_GPL(kmemleak_free_part); =20 @@ -1034,7 +1049,7 @@ void __ref kmemleak_update_trace(const void *ptr) if (!kmemleak_enabled || IS_ERR_OR_NULL(ptr)) return; =20 - object =3D find_and_get_object((unsigned long)ptr, 1); + object =3D find_and_get_object((unsigned long)ptr, 1, false); if (!object) { #ifdef DEBUG kmemleak_warn("Updating stack trace for unknown object at %p\n", @@ -1063,7 +1078,7 @@ void __ref kmemleak_not_leak(const void *ptr) pr_debug("%s(0x%p)\n", __func__, ptr); =20 if (kmemleak_enabled && ptr && !IS_ERR(ptr)) - make_gray_object((unsigned long)ptr); + make_gray_object((unsigned long)ptr, false); } EXPORT_SYMBOL(kmemleak_not_leak); =20 @@ -1081,7 +1096,7 @@ void __ref kmemleak_ignore(const void *ptr) pr_debug("%s(0x%p)\n", __func__, ptr); =20 if (kmemleak_enabled && ptr && !IS_ERR(ptr)) - make_black_object((unsigned long)ptr); + make_black_object((unsigned long)ptr, false); } EXPORT_SYMBOL(kmemleak_ignore); =20 @@ -1275,7 +1290,7 @@ static void scan_block(void *_start, void *_end, * is still present in object_tree_root and object_list * (with updates protected by kmemleak_lock). */ - object =3D lookup_object(pointer, 1); + object =3D lookup_object(pointer, 1, false); if (!object) continue; if (object =3D=3D scanned) @@ -1299,7 +1314,7 @@ static void scan_block(void *_start, void *_end, raw_spin_unlock(&object->lock); =20 if (excess_ref) { - object =3D lookup_object(excess_ref, 0); + object =3D lookup_object(excess_ref, 0, false); if (!object) continue; if (object =3D=3D scanned) @@ -1728,7 +1743,7 @@ static int dump_str_object_info(const char *str) =20 if (kstrtoul(str, 0, &addr)) return -EINVAL; - object =3D find_and_get_object(addr, 0); + object =3D find_and_get_object(addr, 0, false); if (!object) { pr_info("Unknown object at 0x%08lx\n", addr); return -EINVAL; --=20 2.25.1 From nobody Tue Apr 28 07:43:03 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3ECD8C43334 for ; Fri, 3 Jun 2022 03:54:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238407AbiFCDyx (ORCPT ); Thu, 2 Jun 2022 23:54:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46636 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237059AbiFCDyd (ORCPT ); Thu, 2 Jun 2022 23:54:33 -0400 Received: from mail-pl1-x632.google.com (mail-pl1-x632.google.com [IPv6:2607:f8b0:4864:20::632]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8C5FC31926 for ; Thu, 2 Jun 2022 20:54:32 -0700 (PDT) Received: by mail-pl1-x632.google.com with SMTP id u18so6027641plb.3 for ; Thu, 02 Jun 2022 20:54:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NjAQ9U1RyZ6v//Z9T1/sKRQ+oNLTOeoBnmYJ+dO7aSk=; b=IHyysdxE8wrk06+yrVq66k2wvBC4vdESSMS30QlzhI3DHGQKAUXIl7V74dMRlNxQ+9 sTB/p5AMjwxBD4LIvGbBCKV/UxEGlFmPGt0PaYWmW3MJMP432ZhjnyrhSLGK7xfz7fLT W49Mm3467QKIKBD0UBGFN7qc0bvPjze0VzKhBHMfFM/L9Kj/wk4wLCV3+g6hhzSK1q/g powdBclaqBH32B5e4WVQTygGb8QKt6Cwxy9n5UCSVUObNtZGYTFmDT1y4oX+wLyRq99w Onj9IihcmOzyz04nOIZWBykW5oHPFG5gRjJ2rtZEWYRYlMrPDWMUJnAZMz7tF3c3q3x4 wgAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NjAQ9U1RyZ6v//Z9T1/sKRQ+oNLTOeoBnmYJ+dO7aSk=; b=heW8hy3o1YC3KENVWMMJ3HcrSBH+2rNEp2Rh/D1GoFV9HlDO+jZAYnhICLmdO+CmAX fCKrShPvyVBU2x6Dim16iEguwJo/jP7WGJ1b2IVyYF4qJOEQggwH0tacR59H73hSTuxl 85Jg2VCHVOo3/v1hqwSVdtPQdlwtVTySoCV4bTtlYvRWkSv6l6D4S+eICJjGMKMGglj9 TWWeK+VniX92ESCMJ0MsqKCkhS6l7PAfAW+yQkR6WxE0BBoSPWKas3s76M8I2x+jxC3H BbTkxN0vorSL5WeodlDolnK1yK9/5sec+7EwUvv+k0xhtqp/UdU/PqPl0GcF1pcdY3tJ t1yA== X-Gm-Message-State: AOAM53250dLxVD6HsOFx49kpQ3uiPKkqM46P14BdnMyaj3IMFzfRuBJv uooAKQQ3Qg7rPfYQpyNFSgg= X-Google-Smtp-Source: ABdhPJyRoBzhzCK/ZrLQd0WQrH4EgBt6sszDp+oB0AthomXCVEQasTnQQh8J0A+5To1VrAXOfLSVMA== X-Received: by 2002:a17:902:b18e:b0:15f:b2c:6ca with SMTP id s14-20020a170902b18e00b0015f0b2c06camr8275857plr.84.1654228472011; Thu, 02 Jun 2022 20:54:32 -0700 (PDT) Received: from localhost ([101.86.206.159]) by smtp.gmail.com with ESMTPSA id d124-20020a636882000000b003fac21dc6edsm4166400pgc.21.2022.06.02.20.54.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 02 Jun 2022 20:54:31 -0700 (PDT) From: Patrick Wang To: catalin.marinas@arm.com, akpm@linux-foundation.org Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, yee.lee@mediatek.com, patrick.wang.shcn@gmail.com Subject: [PATCH v2 3/4] mm: kmemleak: handle address stored in object based on its type Date: Fri, 3 Jun 2022 11:54:14 +0800 Message-Id: <20220603035415.1243913-4-patrick.wang.shcn@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220603035415.1243913-1-patrick.wang.shcn@gmail.com> References: <20220603035415.1243913-1-patrick.wang.shcn@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Treat the address stored in object in different way according to its type: - Only use kasan_reset_tag for virtual address - Only update min_addr and max_addr for virtual address - Convert physical address to virtual address in scan_object Suggested-by: Catalin Marinas Signed-off-by: Patrick Wang --- mm/kmemleak.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 218144392446..246a70b7218f 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -297,7 +297,9 @@ static void hex_dump_object(struct seq_file *seq, warn_or_seq_printf(seq, " hex dump (first %zu bytes):\n", len); kasan_disable_current(); warn_or_seq_hex_dump(seq, DUMP_PREFIX_NONE, HEX_ROW_SIZE, - HEX_GROUP_SIZE, kasan_reset_tag((void *)ptr), len, HEX_ASCII); + HEX_GROUP_SIZE, object->flags & OBJECT_PHYS ? ptr : + kasan_reset_tag((void *)ptr), + len, HEX_ASCII); kasan_enable_current(); } =20 @@ -389,14 +391,15 @@ static struct kmemleak_object *lookup_object(unsigned= long ptr, int alias, { struct rb_node *rb =3D is_phys ? object_phys_tree_root.rb_node : object_tree_root.rb_node; - unsigned long untagged_ptr =3D (unsigned long)kasan_reset_tag((void *)ptr= ); + unsigned long untagged_ptr =3D is_phys ? ptr : (unsigned long)kasan_reset= _tag((void *)ptr); =20 while (rb) { struct kmemleak_object *object; unsigned long untagged_objp; =20 object =3D rb_entry(rb, struct kmemleak_object, rb_node); - untagged_objp =3D (unsigned long)kasan_reset_tag((void *)object->pointer= ); + untagged_objp =3D is_phys ? object->pointer : + (unsigned long)kasan_reset_tag((void *)object->pointer); =20 if (untagged_ptr < untagged_objp) rb =3D object->rb_node.rb_left; @@ -643,16 +646,19 @@ static struct kmemleak_object *create_object(unsigned= long ptr, size_t size, =20 raw_spin_lock_irqsave(&kmemleak_lock, flags); =20 - untagged_ptr =3D (unsigned long)kasan_reset_tag((void *)ptr); - min_addr =3D min(min_addr, untagged_ptr); - max_addr =3D max(max_addr, untagged_ptr + size); + untagged_ptr =3D is_phys ? ptr : (unsigned long)kasan_reset_tag((void *)p= tr); + if (!is_phys) { + min_addr =3D min(min_addr, untagged_ptr); + max_addr =3D max(max_addr, untagged_ptr + size); + } link =3D is_phys ? &object_phys_tree_root.rb_node : &object_tree_root.rb_node; rb_parent =3D NULL; while (*link) { rb_parent =3D *link; parent =3D rb_entry(rb_parent, struct kmemleak_object, rb_node); - untagged_objp =3D (unsigned long)kasan_reset_tag((void *)parent->pointer= ); + untagged_objp =3D is_phys ? parent->pointer : + (unsigned long)kasan_reset_tag((void *)parent->pointer); if (untagged_ptr + size <=3D untagged_objp) link =3D &parent->rb_node.rb_left; else if (untagged_objp + parent->size <=3D untagged_ptr) @@ -1202,7 +1208,9 @@ static bool update_checksum(struct kmemleak_object *o= bject) =20 kasan_disable_current(); kcsan_disable_current(); - object->checksum =3D crc32(0, kasan_reset_tag((void *)object->pointer), o= bject->size); + object->checksum =3D crc32(0, object->flags & OBJECT_PHYS ? (void *)objec= t->pointer : + kasan_reset_tag((void *)object->pointer), + object->size); kasan_enable_current(); kcsan_enable_current(); =20 @@ -1353,6 +1361,7 @@ static void scan_object(struct kmemleak_object *objec= t) { struct kmemleak_scan_area *area; unsigned long flags; + void *obj_ptr; =20 /* * Once the object->lock is acquired, the corresponding memory block @@ -1364,10 +1373,15 @@ static void scan_object(struct kmemleak_object *obj= ect) if (!(object->flags & OBJECT_ALLOCATED)) /* already freed object */ goto out; + + obj_ptr =3D object->flags & OBJECT_PHYS ? + __va((void *)object->pointer) : + (void *)object->pointer; + if (hlist_empty(&object->area_list) || object->flags & OBJECT_FULL_SCAN) { - void *start =3D (void *)object->pointer; - void *end =3D (void *)(object->pointer + object->size); + void *start =3D obj_ptr; + void *end =3D obj_ptr + object->size; void *next; =20 do { --=20 2.25.1 From nobody Tue Apr 28 07:43:03 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 18B3EC43334 for ; Fri, 3 Jun 2022 03:55:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238517AbiFCDy7 (ORCPT ); Thu, 2 Jun 2022 23:54:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47026 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236612AbiFCDyj (ORCPT ); Thu, 2 Jun 2022 23:54:39 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C354E31DD6 for ; Thu, 2 Jun 2022 20:54:35 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id q12-20020a17090a304c00b001e2d4fb0eb4so11133778pjl.4 for ; Thu, 02 Jun 2022 20:54:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=gDxq5rt5EfBvQEGX/JbF39Xsu3MLwHYHF4domviF5Aw=; b=ZcAWiVl5MNXHqF9gqoBMhVMeSBj8YV7gkiqwngFfitNG69DQnL05R75t16nEkhz4EG Qf5CF1hphATAOuY2icg7qLXEdZ1jq64mvXSbGdqtF2l1Zk9Xfe/lrOvmgA+i4d9RC8ba m+zdi3W3znACUwxWTUhycqt5Jcl0SO3JvTBq/F08392xPXx29tUknHvi/AC0bvpCVDZ5 zRuCBlExCz83+x29q8fnoTokJShnTZbCUVYjdO7/SgFwlZKawpOP7bcDiQ6R/8qwX9Zo Qr6EyW7MdBZj+2wK0qqxR3ZGmJNc604K8EqLHvXLztZk+PYSx3SWFkbr5Sjy6XMMu7sT ehfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gDxq5rt5EfBvQEGX/JbF39Xsu3MLwHYHF4domviF5Aw=; b=EbDl2bl2lSJw8WYaxhVEbO7C1SZWgMgMQXWOC5RzmHRfE34zHkkrV3WhGXV4Nrv9j8 qAHR+P1/HiA7l8kQc8+yWUqi/E8qXKDUyYf19RbKBRvzgPgu7Nqs7kwk4+xsCd5J5sR1 cekJfP3hqmCTlc45BAW9o5Pqvv+a05eavBT5ZqHsxyUOlE9vTK0qwq1jwfya89WfBVHq CRnUbF+Af6Qbw/fmsKQ6ybpAkr4ah+veB+5cd2ZodQeFXLewa9NcKxoY26In1AbOZbxM 0JBWuiYhDw1mnW0A+eNfAqglKTZTegWHMUAumwK5AnG7UqCSla+9xt8TA//ZVZCLiJoh bzgA== X-Gm-Message-State: AOAM5303xJbDm9Ns6dvZRyd/l8VACAEyp5/nn1kwxariNZ+3zWnnVeEb pjNOEIAvZ8xR+AhQlpsYYus= X-Google-Smtp-Source: ABdhPJyakeYteI7Y7hTx45KhYNBoAbLV1IEg+M8GI7pdT6/wyhfrtWQm941y/qg3ytvpVGlkGNVsTw== X-Received: by 2002:a17:903:120f:b0:15f:99f:9597 with SMTP id l15-20020a170903120f00b0015f099f9597mr8133275plh.45.1654228475075; Thu, 02 Jun 2022 20:54:35 -0700 (PDT) Received: from localhost ([101.86.206.159]) by smtp.gmail.com with ESMTPSA id a4-20020a1709027e4400b00163ac8673edsm4274072pln.35.2022.06.02.20.54.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 02 Jun 2022 20:54:34 -0700 (PDT) From: Patrick Wang To: catalin.marinas@arm.com, akpm@linux-foundation.org Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, yee.lee@mediatek.com, patrick.wang.shcn@gmail.com Subject: [PATCH v2 4/4] mm: kmemleak: kmemleak_*_phys() set address type and check PA when scan Date: Fri, 3 Jun 2022 11:54:15 +0800 Message-Id: <20220603035415.1243913-5-patrick.wang.shcn@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220603035415.1243913-1-patrick.wang.shcn@gmail.com> References: <20220603035415.1243913-1-patrick.wang.shcn@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The kmemleak_*_phys() functions call next level interface by setting address type to physical. And the physical address of objects will be checked for its boundary when scan instead of in kmemleak_*_phys(). Suggested-by: Catalin Marinas Signed-off-by: Patrick Wang --- mm/kmemleak.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 246a70b7218f..62d1ad8f8a44 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1156,8 +1156,12 @@ EXPORT_SYMBOL(kmemleak_no_scan); void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int min_coun= t, gfp_t gfp) { - if (PHYS_PFN(phys) >=3D min_low_pfn && PHYS_PFN(phys) < max_low_pfn) - kmemleak_alloc(__va(phys), size, min_count, gfp); + pr_debug("%s(0x%pa, %zu, %d)\n", __func__, &phys, size, min_count); + + if (kmemleak_enabled && !min_count) + /* create object with OBJECT_PHYS flag */ + create_object((unsigned long)phys, size, min_count, + gfp, true); } EXPORT_SYMBOL(kmemleak_alloc_phys); =20 @@ -1170,8 +1174,10 @@ EXPORT_SYMBOL(kmemleak_alloc_phys); */ void __ref kmemleak_free_part_phys(phys_addr_t phys, size_t size) { - if (PHYS_PFN(phys) >=3D min_low_pfn && PHYS_PFN(phys) < max_low_pfn) - kmemleak_free_part(__va(phys), size); + pr_debug("%s(0x%pa)\n", __func__, &phys); + + if (kmemleak_enabled) + delete_object_part((unsigned long)phys, size, true); } EXPORT_SYMBOL(kmemleak_free_part_phys); =20 @@ -1182,8 +1188,10 @@ EXPORT_SYMBOL(kmemleak_free_part_phys); */ void __ref kmemleak_not_leak_phys(phys_addr_t phys) { - if (PHYS_PFN(phys) >=3D min_low_pfn && PHYS_PFN(phys) < max_low_pfn) - kmemleak_not_leak(__va(phys)); + pr_debug("%s(0x%pa)\n", __func__, &phys); + + if (kmemleak_enabled) + make_gray_object((unsigned long)phys, true); } EXPORT_SYMBOL(kmemleak_not_leak_phys); =20 @@ -1194,8 +1202,10 @@ EXPORT_SYMBOL(kmemleak_not_leak_phys); */ void __ref kmemleak_ignore_phys(phys_addr_t phys) { - if (PHYS_PFN(phys) >=3D min_low_pfn && PHYS_PFN(phys) < max_low_pfn) - kmemleak_ignore(__va(phys)); + pr_debug("%s(0x%pa)\n", __func__, &phys); + + if (kmemleak_enabled) + make_black_object((unsigned long)phys, true); } EXPORT_SYMBOL(kmemleak_ignore_phys); =20 @@ -1468,6 +1478,17 @@ static void kmemleak_scan(void) dump_object_info(object); } #endif + + /* ignore objects outside lowmem (paint them black) */ + if ((object->flags & OBJECT_PHYS) && + !(object->flags & OBJECT_NO_SCAN)) { + unsigned long phys =3D object->pointer; + + if (PHYS_PFN(phys) < min_low_pfn || + PHYS_PFN(phys + object->size) >=3D max_low_pfn) + __paint_it(object, KMEMLEAK_BLACK); + } + /* reset the reference count (whiten the object) */ object->count =3D 0; if (color_gray(object) && get_object(object)) --=20 2.25.1