Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp809164pxu; Fri, 4 Dec 2020 16:44:46 -0800 (PST) X-Google-Smtp-Source: ABdhPJyHwtyQ82f/Qz4wcA/3RqB9e+AFQjCMwm8J0X3yvNyCMZ6bdCmvlj1GimJzQTEtU7gqpqtv X-Received: by 2002:a50:bec4:: with SMTP id e4mr10184346edk.65.1607129086676; Fri, 04 Dec 2020 16:44:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1607129086; cv=none; d=google.com; s=arc-20160816; b=a0AMuhA62+4/dmUTe4o1uEC4x2+GvOlkiZDUkpYnR+tIh05Oi4FCAN2esGYLjP6irx 4fxdQCB2qXfs0+CUOgAH5JN2a7nnAsnDKORi89g6nlJnTR585Kxqa1eyu0xGrtelEsQ+ IHP6oCbYDCphkPEJjW6lzvXQwhoYebcbXZwjMS+90m7gn/eyrJwN2imPoVe28C7wCW1K puqjIqQrqs4X0zTLFBiPMAD/Tk5OQDkxolnS30Io5VxWN7pPZTQxUtgXkjURDj82cotY yYCx14SikVgbuNx40Kx07y7EBuovvgcgurLYoUo9y8/qfzLX/abmfewRYw0MKW0jMIwo j6yw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=N6oxF1k8LAsay1BuwNpcQJXJ+k2ckRELxA0xGWXrEjg=; b=x07cARYsoMX6p7AmiK/FYpIs9Ce9DFC/EdO4Jv6k1Crc2TV8MV2fZCA3iDQP8YIdii TbMpVMYfwpu//KNCetGp342APYF/V+J8xixlKGWbQ0Mb8dpTEANfu61okM7vXmq2LpiK 7OXmkbD/6cQa1J0EPiozNlYAlRKV900cL+dXd6AgiLI+It5jAhRDa1px9nkM5WffDhE6 fLptdcYN2xoLmcisvEFCtu6tE0bojzIJTpLp7ec0NT0HU2rmQN5Nes7thA28i7A1to4n kzn0bVvbmlrYkb01/5NliDwwZS8sqaDt30Yrth+vbBJWYTD9BlVTLrUyLAf227Q85kLo mlZA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id h14si2377764ejt.198.2020.12.04.16.44.24; Fri, 04 Dec 2020 16:44:46 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728273AbgLEAll (ORCPT + 99 others); Fri, 4 Dec 2020 19:41:41 -0500 Received: from mail.kernel.org ([198.145.29.99]:48766 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726080AbgLEAll (ORCPT ); Fri, 4 Dec 2020 19:41:41 -0500 From: paulmck@kernel.org Authentication-Results: mail.kernel.org; dkim=permerror (bad message/signature format) To: rcu@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kernel-team@fb.com, mingo@kernel.org, jiangshanlai@gmail.com, akpm@linux-foundation.org, mathieu.desnoyers@efficios.com, josh@joshtriplett.org, tglx@linutronix.de, peterz@infradead.org, rostedt@goodmis.org, dhowells@redhat.com, edumazet@google.com, fweisbec@gmail.com, oleg@redhat.com, joel@joelfernandes.org, "Paul E. McKenney" , Christoph Lameter , Pekka Enberg , David Rientjes , Joonsoo Kim , linux-mm@kvack.org Subject: [PATCH sl-b 2/6] mm: Add kmem_last_alloc_errstring() to provide more kmem_last_alloc() info Date: Fri, 4 Dec 2020 16:40:53 -0800 Message-Id: <20201205004057.32199-2-paulmck@kernel.org> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20201205004022.GA31166@paulmck-ThinkPad-P72> References: <20201205004022.GA31166@paulmck-ThinkPad-P72> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: "Paul E. McKenney" NULL pointers can be useful, but the NULL pointers from kmem_last_alloc() might be caused by any number of things: A not-to-a-slab pointer, failure to enable all the needed debugging, and bogus slob block-address computations. This commit therefore introduces error codes to the kmem_last_alloc() function using the ERR_PTR() facility, and also introduces kmem_last_alloc_errstring(), which translates the error codes into strings. Cc: Christoph Lameter Cc: Pekka Enberg Cc: David Rientjes Cc: Joonsoo Kim Cc: Andrew Morton Cc: Reported-by: Andrii Nakryiko Signed-off-by: Paul E. McKenney --- include/linux/slab.h | 10 ++++++++++ mm/slab.c | 2 +- mm/slab_common.c | 28 ++++++++++++++++++++++++++-- mm/slob.c | 2 +- mm/slub.c | 4 ++-- 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 06dd56b..031e630 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -133,6 +133,15 @@ #define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) <= \ (unsigned long)ZERO_SIZE_PTR) +/* + * kmem_last_alloc error codes. + */ +#define KMEM_LA_NO_PAGE 1 /* No page structure for pointer. */ +#define KMEM_LA_NO_SLAB 2 /* Pointer not from slab allocator. */ +#define KMEM_LA_SLOB 3 /* No debugging info for slob. */ +#define KMEM_LA_NO_DEBUG 4 /* Debugging not enabled for slab/slub. */ +#define KMEM_LA_INCONSISTENT 5 /* Bogus block within slub page. */ + #include struct mem_cgroup; @@ -188,6 +197,7 @@ size_t __ksize(const void *); size_t ksize(const void *); void *kmem_cache_last_alloc(struct kmem_cache *s, void *object); void *kmem_last_alloc(void *object); +const char *kmem_last_alloc_errstring(void *lastalloc); #ifdef CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR void __check_heap_object(const void *ptr, unsigned long n, struct page *page, diff --git a/mm/slab.c b/mm/slab.c index 2ab93b8..1f3b263 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3610,7 +3610,7 @@ void *kmem_cache_last_alloc(struct kmem_cache *cachep, void *object) struct page *page; if (!(cachep->flags & SLAB_STORE_USER)) - return NULL; + return ERR_PTR(-KMEM_LA_NO_DEBUG); objp = object - obj_offset(cachep); page = virt_to_head_page(objp); objnr = obj_to_index(cachep, page, objp); diff --git a/mm/slab_common.c b/mm/slab_common.c index 3f647982..8430a14 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -537,6 +537,30 @@ bool slab_is_available(void) } /* + * If the pointer corresponds to a kmem_last_alloc() error, return + * a pointer to the corresponding string, otherwise NULL. + */ +const char *kmem_last_alloc_errstring(void *lastalloc) +{ + long klaerrno; + static const char * const es[] = { + "local memory", /* KMEM_LA_NO_PAGE - 1 */ + "non-slab memory", /* KMEM_LA_NO_SLAB - 1 */ + "slob doesn't do debug", /* KMEM_LA_SLOB - 1 */ + "debugging disabled", /* KMEM_LA_NO_DEBUG - 1 */ + "bogus slub block", /* KMEM_LA_INCONSISTENT - 1 */ + }; + + if (!IS_ERR(lastalloc)) + return NULL; + klaerrno = -PTR_ERR(lastalloc) - 1; + if (WARN_ON_ONCE(klaerrno >= ARRAY_SIZE(es))) + return "kmem_last_alloc error out of range"; + return es[klaerrno]; +} +EXPORT_SYMBOL_GPL(kmem_last_alloc_errstring); + +/* * If the pointer references a slab-allocated object and if sufficient * debugging is enabled, return the returrn address for the corresponding * allocation. Otherwise, return NULL. Note that passing random pointers @@ -548,10 +572,10 @@ void *kmem_last_alloc(void *object) struct page *page; if (!virt_addr_valid(object)) - return NULL; + return ERR_PTR(-KMEM_LA_NO_PAGE); page = virt_to_head_page(object); if (!PageSlab(page)) - return NULL; + return ERR_PTR(-KMEM_LA_NO_SLAB); return kmem_cache_last_alloc(page->slab_cache, object); } EXPORT_SYMBOL_GPL(kmem_last_alloc); diff --git a/mm/slob.c b/mm/slob.c index c1f8ed7..e7d6b90 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -463,7 +463,7 @@ static void slob_free(void *block, int size) void *kmem_cache_last_alloc(struct kmem_cache *s, void *object) { - return NULL; + return ERR_PTR(-KMEM_LA_SLOB); } /* diff --git a/mm/slub.c b/mm/slub.c index 8ed3ba2..3ddf16a 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3928,7 +3928,7 @@ void *kmem_cache_last_alloc(struct kmem_cache *s, void *object) struct track *trackp; if (!(s->flags & SLAB_STORE_USER)) - return NULL; + return ERR_PTR(-KMEM_LA_NO_DEBUG); page = virt_to_head_page(object); base = page_address(page); objp = kasan_reset_tag(object); @@ -3936,7 +3936,7 @@ void *kmem_cache_last_alloc(struct kmem_cache *s, void *object) objnr = obj_to_index(s, page, objp); objp = base + s->size * objnr; if (objp < base || objp >= base + page->objects * s->size || (objp - base) % s->size) - return NULL; + return ERR_PTR(-KMEM_LA_INCONSISTENT); trackp = get_track(s, objp, TRACK_ALLOC); return (void *)trackp->addr; #else -- 2.9.5