Skip to content

Commit 7599da6

Browse files
author
CKI KWF Bot
committed
Merge: CVE-2025-39843 kernel: mm: slub: avoid wake up kswapd in set_track_prepare
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7548 JIRA: https://issues.redhat.com/browse/RHEL-125520 CVE: CVE-2025-39843 mm: slub: avoid wake up kswapd in set_track_prepare set_track_prepare() can incur lock recursion. The issue is that it is called from hrtimer_start_range_ns holding the per_cpu(hrtimer_bases)[n].lock, but when enabled CONFIG_DEBUG_OBJECTS_TIMERS, may wake up kswapd in set_track_prepare, and try to hold the per_cpu(hrtimer_bases)[n].lock. Avoid deadlock caused by implicitly waking up kswapd by passing in allocation flags, which do not contain __GFP_KSWAPD_RECLAIM in the debug_objects_fill_pool() case. Inside stack depot they are processed by gfp_nested_mask(). Since ___slab_alloc() has preemption disabled, we mask out __GFP_DIRECT_RECLAIM from the flags there. Signed-off-by: Audra Mitchell <audra@redhat.com> Approved-by: Rafael Aquini <raquini@redhat.com> Approved-by: Herton R. Krzesinski <herton@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents f0e256f + ce2874e commit 7599da6

File tree

1 file changed

+34
-25
lines changed

1 file changed

+34
-25
lines changed

mm/slub.c

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -897,19 +897,19 @@ static struct track *get_track(struct kmem_cache *s, void *object,
897897
}
898898

899899
#ifdef CONFIG_STACKDEPOT
900-
static noinline depot_stack_handle_t set_track_prepare(void)
900+
static noinline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags)
901901
{
902902
depot_stack_handle_t handle;
903903
unsigned long entries[TRACK_ADDRS_COUNT];
904904
unsigned int nr_entries;
905905

906906
nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 3);
907-
handle = stack_depot_save(entries, nr_entries, GFP_NOWAIT);
907+
handle = stack_depot_save(entries, nr_entries, gfp_flags);
908908

909909
return handle;
910910
}
911911
#else
912-
static inline depot_stack_handle_t set_track_prepare(void)
912+
static inline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags)
913913
{
914914
return 0;
915915
}
@@ -931,9 +931,9 @@ static void set_track_update(struct kmem_cache *s, void *object,
931931
}
932932

933933
static __always_inline void set_track(struct kmem_cache *s, void *object,
934-
enum track_item alloc, unsigned long addr)
934+
enum track_item alloc, unsigned long addr, gfp_t gfp_flags)
935935
{
936-
depot_stack_handle_t handle = set_track_prepare();
936+
depot_stack_handle_t handle = set_track_prepare(gfp_flags);
937937

938938
set_track_update(s, object, alloc, addr, handle);
939939
}
@@ -1826,9 +1826,9 @@ static inline bool free_debug_processing(struct kmem_cache *s,
18261826
static inline void slab_pad_check(struct kmem_cache *s, struct slab *slab) {}
18271827
static inline int check_object(struct kmem_cache *s, struct slab *slab,
18281828
void *object, u8 val) { return 1; }
1829-
static inline depot_stack_handle_t set_track_prepare(void) { return 0; }
1829+
static inline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags) { return 0; }
18301830
static inline void set_track(struct kmem_cache *s, void *object,
1831-
enum track_item alloc, unsigned long addr) {}
1831+
enum track_item alloc, unsigned long addr, gfp_t gfp_flags) {}
18321832
static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n,
18331833
struct slab *slab) {}
18341834
static inline void remove_full(struct kmem_cache *s, struct kmem_cache_node *n,
@@ -3514,8 +3514,26 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
35143514
pc.slab = &slab;
35153515
pc.orig_size = orig_size;
35163516
freelist = get_partial(s, node, &pc);
3517-
if (freelist)
3518-
goto check_new_slab;
3517+
if (freelist) {
3518+
if (kmem_cache_debug(s)) {
3519+
/*
3520+
* For debug caches here we had to go through
3521+
* alloc_single_from_partial() so just store the
3522+
* tracking info and return the object.
3523+
*
3524+
* Due to disabled preemption we need to disallow
3525+
* blocking. The flags are further adjusted by
3526+
* gfp_nested_mask() in stack_depot itself.
3527+
*/
3528+
if (s->flags & SLAB_STORE_USER)
3529+
set_track(s, freelist, TRACK_ALLOC, addr,
3530+
gfpflags & ~(__GFP_DIRECT_RECLAIM));
3531+
3532+
return freelist;
3533+
}
3534+
3535+
goto retry_load_slab;
3536+
}
35193537

35203538
slub_put_cpu_ptr(s->cpu_slab);
35213539
slab = new_slab(s, gfpflags, node);
@@ -3535,7 +3553,8 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
35353553
goto new_objects;
35363554

35373555
if (s->flags & SLAB_STORE_USER)
3538-
set_track(s, freelist, TRACK_ALLOC, addr);
3556+
set_track(s, freelist, TRACK_ALLOC, addr,
3557+
gfpflags & ~(__GFP_DIRECT_RECLAIM));
35393558

35403559
return freelist;
35413560
}
@@ -3551,20 +3570,6 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
35513570

35523571
inc_slabs_node(s, slab_nid(slab), slab->objects);
35533572

3554-
check_new_slab:
3555-
3556-
if (kmem_cache_debug(s)) {
3557-
/*
3558-
* For debug caches here we had to go through
3559-
* alloc_single_from_partial() so just store the tracking info
3560-
* and return the object
3561-
*/
3562-
if (s->flags & SLAB_STORE_USER)
3563-
set_track(s, freelist, TRACK_ALLOC, addr);
3564-
3565-
return freelist;
3566-
}
3567-
35683573
if (unlikely(!pfmemalloc_match(slab, gfpflags))) {
35693574
/*
35703575
* For !pfmemalloc_match() case we don't load freelist so that
@@ -4027,8 +4032,12 @@ static noinline void free_to_partial_list(
40274032
unsigned long flags;
40284033
depot_stack_handle_t handle = 0;
40294034

4035+
/*
4036+
* We cannot use GFP_NOWAIT as there are callsites where waking up
4037+
* kswapd could deadlock
4038+
*/
40304039
if (s->flags & SLAB_STORE_USER)
4031-
handle = set_track_prepare();
4040+
handle = set_track_prepare(__GFP_NOWARN);
40324041

40334042
spin_lock_irqsave(&n->list_lock, flags);
40344043

0 commit comments

Comments
 (0)