lkml.org 
[lkml]   [2022]   [Feb]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH] mm/slub: initialize stack depot in boot process
On Mon, Feb 28, 2022 at 03:09PM +0000, Hyeonggon Yoo wrote:
> commit ba10d4b46655 ("mm/slub: use stackdepot to save stack trace in
> objects") initializes stack depot while creating cache if SLAB_STORE_USER
> flag is set.
>
> This can make kernel crash because a cache can be created in various
> contexts. For example if user sets slub_debug=U, kernel crashes
> because create_boot_cache() calls stack_depot_init(), which tries to
> allocate hash table using memblock_alloc() if slab is not available.
> But memblock is also not available at that time.
>
> This patch solves the problem by initializing stack depot early
> in boot process if SLAB_STORE_USER debug flag is set globally
> or the flag is set to at least one cache.
>
> [ elver@google.com: initialize stack depot depending on slub_debug
> parameter instead of allowing stack_depot_init() can be called
> in kmem_cache_init() for simplicity. ]
>
> Link: https://lkml.org/lkml/2022/2/28/238

This would be a better permalink:
https://lore.kernel.org/all/YhyeaP8lrzKgKm5A@ip-172-31-19-208.ap-northeast-1.compute.internal/

> Fixes: ba10d4b46655 ("mm/slub: use stackdepot to save stack trace in objects")

This commit does not exist in -next.

I assume you intend that "lib/stackdepot: Use page allocator if both
slab and memblock is unavailable" should be dropped now.

> Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
> ---
> include/linux/slab.h | 1 +
> init/main.c | 1 +
> mm/slab.c | 4 ++++
> mm/slob.c | 4 ++++
> mm/slub.c | 28 +++++++++++++++++++++++++---
> 5 files changed, 35 insertions(+), 3 deletions(-)
[...]
>
> +/* Initialize stack depot if needed */
> +void __init kmem_cache_init_early(void)
> +{
> +#ifdef CONFIG_STACKDEPOT
> + slab_flags_t block_flags;
> + char *next_block;
> + char *slab_list;
> +
> + if (slub_debug & SLAB_STORE_USER)
> + goto init_stack_depot;
> +
> + next_block = slub_debug_string;
> + while (next_block) {
> + next_block = parse_slub_debug_flags(next_block, &block_flags, &slab_list, false);
> + if (block_flags & SLAB_STORE_USER)
> + goto init_stack_depot;
> + }
> +
> + return;
> +
> +init_stack_depot:
> + stack_depot_init();
> +#endif
> +}

You can simplify this function to avoid the goto:

/* Initialize stack depot if needed */
void __init kmem_cache_init_early(void)
{
#ifdef CONFIG_STACKDEPOT
slab_flags_t flags = slub_debug;
char *next_block = slub_debug_string;
char *slab_list;

for (;;) {
if (flags & SLAB_STORE_USER) {
stack_depot_init();
break;
}
if (!next_block)
break;
next_block = parse_slub_debug_flags(next_block, &flags, &slab_list, false);
}
#endif
}

^^ with this version, it'd also be much easier and less confusing to add
other initialization logic unrelated to stackdepot later after the loop
(should it ever be required).

\
 
 \ /
  Last update: 2022-02-28 17:29    [W:0.088 / U:0.924 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site