A bucket set passes its constructor and slab flags to its own caches, but its allocations do not always come from them. With CONFIG_SLAB_BUCKETS=n, kmem_buckets_create() returns ZERO_SIZE_PTR, and when creating the set fails it returns NULL. Either way kmem_buckets_alloc() is served by the general kmalloc caches, which have neither, so a caller cannot depend on them. msg_msg depended on SLAB_ACCOUNT, which it no longer passes since accounting through GFP_KERNEL_ACCOUNT instead.
No caller passes a constructor or flags; drop both arguments. The set's caches keep SLAB_NO_MERGE, which kmem_buckets_create() always added. Assisted-by: LLM Signed-off-by: Kees Cook <[email protected]> --- include/linux/slab.h | 5 ++--- ipc/msgutil.c | 5 ++--- mm/slab_common.c | 14 ++++---------- mm/util.c | 2 +- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index cda126def67a..31f97e2579a7 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -890,9 +890,8 @@ void *kmem_cache_alloc_lru_noprof(struct kmem_cache *s, struct list_lru *lru, bool kmem_cache_charge(void *objp, gfp_t gfpflags); void kmem_cache_free(struct kmem_cache *s, void *objp); -kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags, - unsigned int useroffset, unsigned int usersize, - void (*ctor)(void *)); +kmem_buckets *kmem_buckets_create(const char *name, unsigned int useroffset, + unsigned int usersize); /* * Bulk allocation and freeing operations. These are accelerated in an diff --git a/ipc/msgutil.c b/ipc/msgutil.c index 1ba8e59cb255..10ce3087b089 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -43,9 +43,8 @@ static kmem_buckets *msg_buckets __ro_after_init; static int __init init_msg_buckets(void) { - msg_buckets = kmem_buckets_create("msg_msg", 0, - sizeof(struct msg_msg), - DATALEN_MSG, NULL); + msg_buckets = kmem_buckets_create("msg_msg", sizeof(struct msg_msg), + DATALEN_MSG); return 0; } diff --git a/mm/slab_common.c b/mm/slab_common.c index 270408ce5a9d..f8bb70d76eb4 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -415,12 +415,10 @@ static struct kmem_cache *kmem_buckets_cache __ro_after_init; * allocations via kmem_buckets_alloc() * @name: A prefix string which is used in /proc/slabinfo to identify this * cache. The individual caches with have their sizes as the suffix. - * @flags: SLAB flags (see kmem_cache_create() for details). * @useroffset: Starting offset within an allocation that may be copied * to/from userspace. * @usersize: How many bytes, starting at @useroffset, may be copied * to/from userspace. - * @ctor: A constructor for the objects, run when new allocations are made. * * Context: Cannot be called within an interrupt, but can be interrupted. * @@ -429,10 +427,8 @@ static struct kmem_cache *kmem_buckets_cache __ro_after_init; * subsequent calls to kmem_buckets_alloc() will fall back to kmalloc(). * (i.e. callers only need to check for NULL on failure.) */ -kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags, - unsigned int useroffset, - unsigned int usersize, - void (*ctor)(void *)) +kmem_buckets *kmem_buckets_create(const char *name, unsigned int useroffset, + unsigned int usersize) { unsigned long mask = 0; unsigned int idx; @@ -455,8 +451,6 @@ kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags, if (WARN_ON(!b)) return NULL; - flags |= SLAB_NO_MERGE; - for (idx = 0; idx < ARRAY_SIZE(kmalloc_caches[KMALLOC_NORMAL]); idx++) { char *short_size, *cache_name; unsigned int cache_useroffset, cache_usersize; @@ -487,8 +481,8 @@ kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags, if (WARN_ON(!cache_name)) goto fail; (*b)[aligned_idx] = kmem_cache_create_usercopy(cache_name, size, - 0, flags, cache_useroffset, - cache_usersize, ctor); + 0, SLAB_NO_MERGE, cache_useroffset, + cache_usersize, NULL); kfree(cache_name); if (WARN_ON(!(*b)[aligned_idx])) goto fail; diff --git a/mm/util.c b/mm/util.c index bf0513d1d3d0..0cd125f1ea99 100644 --- a/mm/util.c +++ b/mm/util.c @@ -199,7 +199,7 @@ static kmem_buckets *user_buckets __ro_after_init; static int __init init_user_buckets(void) { - user_buckets = kmem_buckets_create("memdup_user", 0, 0, INT_MAX, NULL); + user_buckets = kmem_buckets_create("memdup_user", 0, INT_MAX); return 0; } -- 2.55.0

