From 97b7d8586673843ca73c5aa5067b95e51136b51a Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Fri, 17 Sep 2021 08:40:41 +0530 Subject: [PATCH] ANDROID: mm: add get_each_object_track function Add and export get_each_object_track which helps in looping through all the slab objects of a page and gets the track structure of each object, also make track_item and track structure public, these will be used by the minidump module to get slab owner info. Includes commit 0e00d7c46b36 ("ANDROID: mm/slub: Fix Kasan issue with for_each_object_track") from android13-5.15 as a bug fix. Bug: 199236943 Change-Id: Id9922b57053be277f8042ad8199fbbf9faa984ef Signed-off-by: Vijayanand Jitta Signed-off-by: Jaskaran Singh --- mm/slab.h | 31 +++++++++++++++++++++++++++++++ mm/slub.c | 52 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/mm/slab.h b/mm/slab.h index 0202a8c2f0d2..553228999c32 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -282,6 +282,24 @@ void __kmem_cache_free(struct kmem_cache *s, void *x, unsigned long caller); gfp_t kmalloc_fix_flags(gfp_t flags); +#ifdef CONFIG_SLUB +/* + * Tracking user of a slab. + */ +#define TRACK_ADDRS_COUNT 16 +struct track { + unsigned long addr; /* Called from address */ +#ifdef CONFIG_STACKDEPOT + depot_stack_handle_t handle; +#endif + int cpu; /* Was running on cpu */ + int pid; /* Pid context */ + unsigned long when; /* When did the operation occur */ +}; + +enum track_item { TRACK_ALLOC, TRACK_FREE }; +#endif + /* Functions provided by the slab allocators */ int __kmem_cache_create(struct kmem_cache *, slab_flags_t flags); @@ -399,6 +417,10 @@ DECLARE_STATIC_KEY_FALSE(slub_debug_enabled); #endif extern void print_tracking(struct kmem_cache *s, void *object); long validate_slab_cache(struct kmem_cache *s); +extern unsigned long get_each_object_track(struct kmem_cache *s, + struct page *page, enum track_item alloc, + int (*fn)(const struct kmem_cache *, const void *, + const struct track *, void *), void *private); static inline bool __slub_debug_enabled(void) { return static_branch_unlikely(&slub_debug_enabled); @@ -407,6 +429,15 @@ static inline bool __slub_debug_enabled(void) static inline void print_tracking(struct kmem_cache *s, void *object) { } +#ifdef CONFIG_SLUB +static inline unsigned long get_each_object_track(struct kmem_cache *s, + struct page *page, enum track_item alloc, + int (*fn)(const struct kmem_cache *, const void *, + const struct track *, void *), void *private) +{ + return 0; +} +#endif static inline bool __slub_debug_enabled(void) { return false; diff --git a/mm/slub.c b/mm/slub.c index a1e1eb1c158f..3c9d4e333963 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -282,22 +282,6 @@ static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s) /* Use cmpxchg_double */ #define __CMPXCHG_DOUBLE ((slab_flags_t __force)0x40000000U) -/* - * Tracking user of a slab. - */ -#define TRACK_ADDRS_COUNT 16 -struct track { - unsigned long addr; /* Called from address */ -#ifdef CONFIG_STACKDEPOT - depot_stack_handle_t handle; -#endif - int cpu; /* Was running on cpu */ - int pid; /* Pid context */ - unsigned long when; /* When did the operation occur */ -}; - -enum track_item { TRACK_ALLOC, TRACK_FREE }; - #ifdef CONFIG_SYSFS static int sysfs_slab_add(struct kmem_cache *); static int sysfs_slab_alias(struct kmem_cache *, const char *); @@ -725,6 +709,42 @@ static struct track *get_track(struct kmem_cache *s, void *object, return kasan_reset_tag(p + alloc); } +/* + * This function will be used to loop through all the slab objects in + * a page to give track structure for each object, the function fn will + * be using this track structure and extract required info into its private + * data, the return value will be the number of track structures that are + * processed. + */ +unsigned long get_each_object_track(struct kmem_cache *s, + struct page *page, enum track_item alloc, + int (*fn)(const struct kmem_cache *, const void *, + const struct track *, void *), void *private) +{ + void *p; + struct track *t; + int ret; + unsigned long num_track = 0; + struct slab *p_slab = page_slab(page); + + if (!slub_debug || !(s->flags & SLAB_STORE_USER) || !p_slab) + return 0; + + slab_lock(p_slab); + for_each_object(p, s, page_address(page), p_slab->objects) { + t = get_track(s, p, alloc); + metadata_access_enable(); + ret = fn(s, p, t, private); + metadata_access_disable(); + if (ret < 0) + break; + num_track += 1; + } + slab_unlock(p_slab); + return num_track; +} +EXPORT_SYMBOL_NS_GPL(get_each_object_track, MINIDUMP); + #ifdef CONFIG_STACKDEPOT static noinline depot_stack_handle_t set_track_prepare(void) {