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


Reply via email to