Skip to content

Commit a2f7757

Browse files
xairytorvalds
authored andcommitted
kmemleak: account for tagged pointers when calculating pointer range
kmemleak keeps two global variables, min_addr and max_addr, which store the range of valid (encountered by kmemleak) pointer values, which it later uses to speed up pointer lookup when scanning blocks. With tagged pointers this range will get bigger than it needs to be. This patch makes kmemleak untag pointers before saving them to min_addr and max_addr and when performing a lookup. Link: http://lkml.kernel.org/r/16e887d442986ab87fe87a755815ad92fa431a5f.1550066133.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Tested-by: Qian Cai <cai@lca.pw> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Alexander Potapenko <glider@google.com> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Christoph Lameter <cl@linux.com> Cc: David Rientjes <rientjes@google.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Evgeniy Stepanov <eugenis@google.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Kostya Serebryany <kcc@google.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: Vincenzo Frascino <vincenzo.frascino@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 5312824 commit a2f7757

File tree

4 files changed

+10
-3
lines changed

4 files changed

+10
-3
lines changed

mm/kmemleak.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size,
574574
unsigned long flags;
575575
struct kmemleak_object *object, *parent;
576576
struct rb_node **link, *rb_parent;
577+
unsigned long untagged_ptr;
577578

578579
object = kmem_cache_alloc(object_cache, gfp_kmemleak_mask(gfp));
579580
if (!object) {
@@ -619,8 +620,9 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size,
619620

620621
write_lock_irqsave(&kmemleak_lock, flags);
621622

622-
min_addr = min(min_addr, ptr);
623-
max_addr = max(max_addr, ptr + size);
623+
untagged_ptr = (unsigned long)kasan_reset_tag((void *)ptr);
624+
min_addr = min(min_addr, untagged_ptr);
625+
max_addr = max(max_addr, untagged_ptr + size);
624626
link = &object_tree_root.rb_node;
625627
rb_parent = NULL;
626628
while (*link) {
@@ -1333,6 +1335,7 @@ static void scan_block(void *_start, void *_end,
13331335
unsigned long *start = PTR_ALIGN(_start, BYTES_PER_POINTER);
13341336
unsigned long *end = _end - (BYTES_PER_POINTER - 1);
13351337
unsigned long flags;
1338+
unsigned long untagged_ptr;
13361339

13371340
read_lock_irqsave(&kmemleak_lock, flags);
13381341
for (ptr = start; ptr < end; ptr++) {
@@ -1347,7 +1350,8 @@ static void scan_block(void *_start, void *_end,
13471350
pointer = *ptr;
13481351
kasan_enable_current();
13491352

1350-
if (pointer < min_addr || pointer >= max_addr)
1353+
untagged_ptr = (unsigned long)kasan_reset_tag((void *)pointer);
1354+
if (untagged_ptr < min_addr || untagged_ptr >= max_addr)
13511355
continue;
13521356

13531357
/*

mm/slab.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
438438
flags &= gfp_allowed_mask;
439439
for (i = 0; i < size; i++) {
440440
p[i] = kasan_slab_alloc(s, p[i], flags);
441+
/* As p[i] might get tagged, call kmemleak hook after KASAN. */
441442
kmemleak_alloc_recursive(p[i], s->object_size, 1,
442443
s->flags, flags);
443444
}

mm/slab_common.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,7 @@ void *kmalloc_order(size_t size, gfp_t flags, unsigned int order)
12291229
page = alloc_pages(flags, order);
12301230
ret = page ? page_address(page) : NULL;
12311231
ret = kasan_kmalloc_large(ret, size, flags);
1232+
/* As ret might get tagged, call kmemleak hook after KASAN. */
12321233
kmemleak_alloc(ret, size, 1, flags);
12331234
return ret;
12341235
}

mm/slub.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,6 +1375,7 @@ static inline void dec_slabs_node(struct kmem_cache *s, int node,
13751375
static inline void *kmalloc_large_node_hook(void *ptr, size_t size, gfp_t flags)
13761376
{
13771377
ptr = kasan_kmalloc_large(ptr, size, flags);
1378+
/* As ptr might get tagged, call kmemleak hook after KASAN. */
13781379
kmemleak_alloc(ptr, size, 1, flags);
13791380
return ptr;
13801381
}

0 commit comments

Comments
 (0)