diff mbox series

[9/9] mm: kmemleak: fix undetected leaks for page aligned objects

Message ID 20230123170419.7292-10-george@enfabrica.net (mailing list archive)
State New
Headers show
Series mm: kmemleak: fix unreported memory leaks | expand

Commit Message

George Prekas Jan. 23, 2023, 5:04 p.m. UTC
If kmalloc returns a page aligned object, then the object has 2
references: the pointer returned by kmalloc and page->s_mem of the first
page of the object. Account for this extra reference, so that kmemleak
can correctly detect leaks for page aligned objects.

Signed-off-by: George Prekas <george@enfabrica.net>
---
 mm/slab.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Comments

Matthew Wilcox Jan. 24, 2023, 4:16 p.m. UTC | #1
On Mon, Jan 23, 2023 at 11:04:19AM -0600, George Prekas wrote:
> If kmalloc returns a page aligned object, then the object has 2
> references: the pointer returned by kmalloc and page->s_mem of the first
> page of the object. Account for this extra reference, so that kmemleak
> can correctly detect leaks for page aligned objects.

Is this true for multi-page slabs?  Imagine if you allocate objects of
size 4kB.  Slab/Slub will allocate slabs of size 32kB and try to
allocate 8 objects from each slab.  Only the first one will have an
s_mem pointing into it.  No?

> -		kmemleak_alloc_recursive(p[i], s->object_size, 1,
> +		min_count = 1;
> +		/* If p[i] is page aligned, then a page->s_mem refers to it. */

Also this comment should read 'slab->s_mem'.  Individual pages within
the slab do not have s_mem pointers, only the slab.

> +		if (((uintptr_t)p[i] & ~PAGE_MASK) == 0)
> +			min_count++;
> +		kmemleak_alloc_recursive(p[i], s->object_size, min_count,
>  					 s->flags, flags);
Christoph Lameter Jan. 26, 2023, 11:21 a.m. UTC | #2
On Mon, 23 Jan 2023, George Prekas wrote:

> If kmalloc returns a page aligned object, then the object has 2
> references: the pointer returned by kmalloc and page->s_mem of the first
> page of the object. Account for this extra reference, so that kmemleak
> can correctly detect leaks for page aligned objects.

s_mem is a reference to the array of slab objects in a SLAB page. It is
not referring to a particular object. s_mem allows access to the Nth
object in a slab page.

See the function index_to_obj() in slab.c



static inline void  *index_to_obj(struct kmem_cache *cache,
                                 const struct slab *slab, unsigned int idx)
{

        return slab->s_mem + cache->size * idx;
}
diff mbox series

Patch

diff --git a/mm/slab.h b/mm/slab.h
index 7cc432969945..76341c7c048e 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -734,6 +734,7 @@  static inline void slab_post_alloc_hook(struct kmem_cache *s,
 					unsigned int orig_size)
 {
 	unsigned int zero_size = s->object_size;
+	int min_count;
 	size_t i;
 
 	flags &= gfp_allowed_mask;
@@ -761,7 +762,11 @@  static inline void slab_post_alloc_hook(struct kmem_cache *s,
 		p[i] = kasan_slab_alloc(s, p[i], flags, init);
 		if (p[i] && init && !kasan_has_integrated_init())
 			memset(p[i], 0, zero_size);
-		kmemleak_alloc_recursive(p[i], s->object_size, 1,
+		min_count = 1;
+		/* If p[i] is page aligned, then a page->s_mem refers to it. */
+		if (((uintptr_t)p[i] & ~PAGE_MASK) == 0)
+			min_count++;
+		kmemleak_alloc_recursive(p[i], s->object_size, min_count,
 					 s->flags, flags);
 		kmsan_slab_alloc(s, p[i], flags);
 	}