Skip to content

Commit fb5eda0

Browse files
ftang1tehcaster
authored andcommitted
mm/kasan: Don't store metadata inside kmalloc object when slub_debug_orig_size is on
For a kmalloc object, when both kasan and slub redzone sanity check are enabled, they could both manipulate its data space like storing kasan free meta data and setting up kmalloc redzone, and may affect accuracy of that object's 'orig_size'. As an accurate 'orig_size' will be needed by some function like krealloc() soon, save kasan's free meta data in slub's metadata area instead of inside object when 'orig_size' is enabled. This will make it easier to maintain/understand the code. Size wise, when these two options are both enabled, the slub meta data space is already huge, and this just slightly increase the overall size. Signed-off-by: Feng Tang <[email protected]> Acked-by: Andrey Konovalov <[email protected]> Signed-off-by: Vlastimil Babka <[email protected]>
1 parent 7045738 commit fb5eda0

File tree

3 files changed

+11
-19
lines changed

3 files changed

+11
-19
lines changed

mm/kasan/generic.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,12 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
392392
* 1. Object is SLAB_TYPESAFE_BY_RCU, which means that it can
393393
* be touched after it was freed, or
394394
* 2. Object has a constructor, which means it's expected to
395-
* retain its content until the next allocation.
395+
* retain its content until the next allocation, or
396+
* 3. It is from a kmalloc cache which enables the debug option
397+
* to store original size.
396398
*/
397-
if ((cache->flags & SLAB_TYPESAFE_BY_RCU) || cache->ctor) {
399+
if ((cache->flags & SLAB_TYPESAFE_BY_RCU) || cache->ctor ||
400+
slub_debug_orig_size(cache)) {
398401
cache->kasan_info.free_meta_offset = *size;
399402
*size += sizeof(struct kasan_free_meta);
400403
goto free_meta_added;

mm/slab.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,12 @@ void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab)
695695
void __check_heap_object(const void *ptr, unsigned long n,
696696
const struct slab *slab, bool to_user);
697697

698+
static inline bool slub_debug_orig_size(struct kmem_cache *s)
699+
{
700+
return (kmem_cache_debug_flags(s, SLAB_STORE_USER) &&
701+
(s->flags & SLAB_KMALLOC));
702+
}
703+
698704
#ifdef CONFIG_SLUB_DEBUG
699705
void skip_orig_size_check(struct kmem_cache *s, const void *object);
700706
#endif

mm/slub.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,6 @@ static inline bool kmem_cache_debug(struct kmem_cache *s)
230230
return kmem_cache_debug_flags(s, SLAB_DEBUG_FLAGS);
231231
}
232232

233-
static inline bool slub_debug_orig_size(struct kmem_cache *s)
234-
{
235-
return (kmem_cache_debug_flags(s, SLAB_STORE_USER) &&
236-
(s->flags & SLAB_KMALLOC));
237-
}
238-
239233
void *fixup_red_left(struct kmem_cache *s, void *p)
240234
{
241235
if (kmem_cache_debug_flags(s, SLAB_RED_ZONE))
@@ -760,21 +754,10 @@ static inline void set_orig_size(struct kmem_cache *s,
760754
void *object, unsigned int orig_size)
761755
{
762756
void *p = kasan_reset_tag(object);
763-
unsigned int kasan_meta_size;
764757

765758
if (!slub_debug_orig_size(s))
766759
return;
767760

768-
/*
769-
* KASAN can save its free meta data inside of the object at offset 0.
770-
* If this meta data size is larger than 'orig_size', it will overlap
771-
* the data redzone in [orig_size+1, object_size]. Thus, we adjust
772-
* 'orig_size' to be as at least as big as KASAN's meta data.
773-
*/
774-
kasan_meta_size = kasan_metadata_size(s, true);
775-
if (kasan_meta_size > orig_size)
776-
orig_size = kasan_meta_size;
777-
778761
p += get_info_end(s);
779762
p += sizeof(struct track) * 2;
780763

0 commit comments

Comments
 (0)