slab fixes for 6.17-rc5

-----BEGIN PGP SIGNATURE-----
 
 iQFPBAABCAA5FiEEe7vIQRWZI0iWSE3xu+CwddJFiJoFAmi5UjobFIAAAAAABAAO
 bWFudTIsMi41KzEuMTEsMiwyAAoJELvgsHXSRYiaXzgH/02xMYsULsZH051JsC55
 ZYa6BQ1LHWT1UIs9cBojjWqrvO21ZGoKIwKX0sKrjnHKoHV/IaXom3AQxqkm34Cc
 sJMZXoBgq0ZpW9XIjoudrVY1oPLBykPkuGvFCD2WI1ecZ4G1P+bvRJVosmF86UyA
 NN6YDp4tMiDoauOYhxBv/deJ47nHvhlP6P0y4w/sfgf9ZQN5smWDxAKPTfRG4UAc
 PeyVArCsUeWcLUicL+nx4qp1owZtqtssIJD1mOYdlA9fyQc3o6GkNuCSO05wdukQ
 RQLL11PzA0xfUH4CEh2OIVtBChE+1m4zNdhjwPTjpPKca7pbwFwwj3mMHiXKVHqV
 LiY=
 =qFr8
 -----END PGP SIGNATURE-----

Merge tag 'slab-for-6.17-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab

Pull slab fixes from Vlastimil Babka:

 - Stable fix to make slub_debug code not access invalid pointers in the
   process of reporting issues (Li Qiong)

 - Stable fix to make object tracking pass gfp flags to stackdepot to
   avoid deadlock in contexts that can't even wake up kswapd due to e.g.
   timers debugging enabled (yangshiguang)

* tag 'slab-for-6.17-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab:
  mm: slub: avoid wake up kswapd in set_track_prepare
  mm/slub: avoid accessing metadata when pointer is invalid in object_err()
This commit is contained in:
Linus Torvalds 2025-09-04 09:54:20 -07:00
commit 68f285e264

View File

@ -962,19 +962,19 @@ static struct track *get_track(struct kmem_cache *s, void *object,
}
#ifdef CONFIG_STACKDEPOT
static noinline depot_stack_handle_t set_track_prepare(void)
static noinline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags)
{
depot_stack_handle_t handle;
unsigned long entries[TRACK_ADDRS_COUNT];
unsigned int nr_entries;
nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 3);
handle = stack_depot_save(entries, nr_entries, GFP_NOWAIT);
handle = stack_depot_save(entries, nr_entries, gfp_flags);
return handle;
}
#else
static inline depot_stack_handle_t set_track_prepare(void)
static inline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags)
{
return 0;
}
@ -996,9 +996,9 @@ static void set_track_update(struct kmem_cache *s, void *object,
}
static __always_inline void set_track(struct kmem_cache *s, void *object,
enum track_item alloc, unsigned long addr)
enum track_item alloc, unsigned long addr, gfp_t gfp_flags)
{
depot_stack_handle_t handle = set_track_prepare();
depot_stack_handle_t handle = set_track_prepare(gfp_flags);
set_track_update(s, object, alloc, addr, handle);
}
@ -1140,7 +1140,12 @@ static void object_err(struct kmem_cache *s, struct slab *slab,
return;
slab_bug(s, reason);
print_trailer(s, slab, object);
if (!object || !check_valid_pointer(s, slab, object)) {
print_slab_info(slab);
pr_err("Invalid pointer 0x%p\n", object);
} else {
print_trailer(s, slab, object);
}
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
WARN_ON(1);
@ -1921,9 +1926,9 @@ static inline bool free_debug_processing(struct kmem_cache *s,
static inline void slab_pad_check(struct kmem_cache *s, struct slab *slab) {}
static inline int check_object(struct kmem_cache *s, struct slab *slab,
void *object, u8 val) { return 1; }
static inline depot_stack_handle_t set_track_prepare(void) { return 0; }
static inline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags) { return 0; }
static inline void set_track(struct kmem_cache *s, void *object,
enum track_item alloc, unsigned long addr) {}
enum track_item alloc, unsigned long addr, gfp_t gfp_flags) {}
static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n,
struct slab *slab) {}
static inline void remove_full(struct kmem_cache *s, struct kmem_cache_node *n,
@ -3876,9 +3881,14 @@ new_objects:
* For debug caches here we had to go through
* alloc_single_from_partial() so just store the
* tracking info and return the object.
*
* Due to disabled preemption we need to disallow
* blocking. The flags are further adjusted by
* gfp_nested_mask() in stack_depot itself.
*/
if (s->flags & SLAB_STORE_USER)
set_track(s, freelist, TRACK_ALLOC, addr);
set_track(s, freelist, TRACK_ALLOC, addr,
gfpflags & ~(__GFP_DIRECT_RECLAIM));
return freelist;
}
@ -3910,7 +3920,8 @@ new_objects:
goto new_objects;
if (s->flags & SLAB_STORE_USER)
set_track(s, freelist, TRACK_ALLOC, addr);
set_track(s, freelist, TRACK_ALLOC, addr,
gfpflags & ~(__GFP_DIRECT_RECLAIM));
return freelist;
}
@ -4421,8 +4432,12 @@ static noinline void free_to_partial_list(
unsigned long flags;
depot_stack_handle_t handle = 0;
/*
* We cannot use GFP_NOWAIT as there are callsites where waking up
* kswapd could deadlock
*/
if (s->flags & SLAB_STORE_USER)
handle = set_track_prepare();
handle = set_track_prepare(__GFP_NOWARN);
spin_lock_irqsave(&n->list_lock, flags);