Skip to content

Commit

Permalink
kasan: unify code between kasan_slab_free() and kasan_poison_kfree()
Browse files Browse the repository at this point in the history
Both of these functions deal with freeing of slab objects.
However, kasan_poison_kfree() mishandles SLAB_TYPESAFE_BY_RCU
(must also not poison such objects) and does not detect double-frees.

Unify code between these functions.

This solves both of the problems and allows to add more common code
(e.g. detection of invalid frees).

Link: http://lkml.kernel.org/r/385493d863acf60408be219a021c3c8e27daa96f.1514378558.git.dvyukov@google.com
Signed-off-by: Dmitry Vyukov <[email protected]>
Cc: Andrey Ryabinin <[email protected]>a
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
dvyukov authored and torvalds committed Feb 7, 2018
1 parent 6860f63 commit 1db0e0f
Showing 1 changed file with 12 additions and 16 deletions.
28 changes: 12 additions & 16 deletions mm/kasan/kasan.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,21 +489,11 @@ void kasan_slab_alloc(struct kmem_cache *cache, void *object, gfp_t flags)
kasan_kmalloc(cache, object, cache->object_size, flags);
}

static void kasan_poison_slab_free(struct kmem_cache *cache, void *object)
{
unsigned long size = cache->object_size;
unsigned long rounded_up_size = round_up(size, KASAN_SHADOW_SCALE_SIZE);

/* RCU slabs could be legally used after free within the RCU period */
if (unlikely(cache->flags & SLAB_TYPESAFE_BY_RCU))
return;

kasan_poison_shadow(object, rounded_up_size, KASAN_KMALLOC_FREE);
}

bool kasan_slab_free(struct kmem_cache *cache, void *object, unsigned long ip)
static bool __kasan_slab_free(struct kmem_cache *cache, void *object,
unsigned long ip, bool quarantine)
{
s8 shadow_byte;
unsigned long rounded_up_size;

/* RCU slabs could be legally used after free within the RCU period */
if (unlikely(cache->flags & SLAB_TYPESAFE_BY_RCU))
Expand All @@ -515,16 +505,22 @@ bool kasan_slab_free(struct kmem_cache *cache, void *object, unsigned long ip)
return true;
}

kasan_poison_slab_free(cache, object);
rounded_up_size = round_up(cache->object_size, KASAN_SHADOW_SCALE_SIZE);
kasan_poison_shadow(object, rounded_up_size, KASAN_KMALLOC_FREE);

if (unlikely(!(cache->flags & SLAB_KASAN)))
if (!quarantine || unlikely(!(cache->flags & SLAB_KASAN)))
return false;

set_track(&get_alloc_info(cache, object)->free_track, GFP_NOWAIT);
quarantine_put(get_free_info(cache, object), cache);
return true;
}

bool kasan_slab_free(struct kmem_cache *cache, void *object, unsigned long ip)
{
return __kasan_slab_free(cache, object, ip, true);
}

void kasan_kmalloc(struct kmem_cache *cache, const void *object, size_t size,
gfp_t flags)
{
Expand Down Expand Up @@ -602,7 +598,7 @@ void kasan_poison_kfree(void *ptr, unsigned long ip)
kasan_poison_shadow(ptr, PAGE_SIZE << compound_order(page),
KASAN_FREE_PAGE);
} else {
kasan_poison_slab_free(page->slab_cache, ptr);
__kasan_slab_free(page->slab_cache, ptr, ip, false);
}
}

Expand Down

0 comments on commit 1db0e0f

Please sign in to comment.