* [PATCH v2 0/6] mm/slab: Support selecting slab hardening features at boot
@ 2026-10-29 6:07 Chris Down
2026-10-29 6:07 ` [PATCH v2 1/6] mm/slab: Enable SLAB_FREELIST_HARDENED by default Chris Down
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Chris Down @ 2026-10-29 6:07 UTC (permalink / raw)
To: Vlastimil Babka, Harry Yoo, Andrew Morton
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Kees Cook, Marco Elver, GONG Ruiqi, Jonathan Corbet, linux-mm,
linux-hardening, linux-doc, linux-kernel, kernel-team
Slab hardening settings are currently all build time choices. This means
that, unfortunately, hosts with different requirements end up needing
separate kernel images. At Meta, for example, some hosts are built with
these options and the rest of the fleet isn't, and that's one of the
things that keeps those kernels apart.
Following the discussion on v1, this series now does two things:
- SLAB_FREELIST_HARDENED and SLAB_FREELIST_RANDOM are cheap enough with
sheaves that it makes more sense to just enable them by default than
to make them switchable. With both on, system level benchmarks didn't
change measurably, only slowpath heavy microbenchmarks did [1].
- SLAB_BUCKETS and KMALLOC_PARTITION_CACHES cost memory (Harry measured
about 1 MiB and 18 MiB respectively after boot on a 64 CPU VM [2]), so
they get slab_buckets= and kmalloc_partition= boot parameters, which
default to on when the option is built in.
Changes in v2:
- Make SLAB_FREELIST_HARDENED and SLAB_FREELIST_RANDOM default y instead
of adding boot parameters for them (Vlastimil).
- Skip the memdup_user() part of the slab_buckets test on !MMU
(Sashiko).
- Keep slab_buckets= and kmalloc_partition= separate for now. We can
discuss whether to merge them into slab_hardening= or similar, as
Harry suggested.
v1: https://lore.kernel.org/r/cover.1793086056.git.chris@chrisdown.name
[1] https://lore.kernel.org/r/auITixAJMfLtfa7i@chrisdown.name
[2] https://lore.kernel.org/r/179312451613.474906.1475329637924619088@kernel.org
Chris Down (6):
mm/slab: Enable SLAB_FREELIST_HARDENED by default
mm/slab: Enable SLAB_FREELIST_RANDOM by default
mm/slab: Support disabling SLAB_BUCKETS at boot
slub_kunit: Add a test for the slab_buckets boot parameter
mm/slab: Support disabling KMALLOC_PARTITION_CACHES at boot
slub_kunit: Add a test for the kmalloc_partition boot parameter
.../admin-guide/kernel-parameters.txt | 15 ++++
lib/tests/slub_kunit.c | 87 +++++++++++++++++++
mm/Kconfig | 11 +++
mm/slab.h | 8 ++
mm/slab_common.c | 48 ++++++++--
5 files changed, 163 insertions(+), 6 deletions(-)
base-commit: d15d7703166daf7bd62c844a3cb1b3a6279adb4c
--
2.54.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/6] mm/slab: Enable SLAB_FREELIST_HARDENED by default
2026-10-29 6:07 [PATCH v2 0/6] mm/slab: Support selecting slab hardening features at boot Chris Down
@ 2026-10-29 6:07 ` Chris Down
2026-10-29 6:07 ` [PATCH v2 2/6] mm/slab: Enable SLAB_FREELIST_RANDOM " Chris Down
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Chris Down @ 2026-10-29 6:07 UTC (permalink / raw)
To: Vlastimil Babka, Harry Yoo, Andrew Morton
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Kees Cook, Marco Elver, GONG Ruiqi, Jonathan Corbet, linux-mm,
linux-hardening, linux-doc, linux-kernel, kernel-team
SLAB_FREELIST_HARDENED obfuscates the free pointers stored in free
objects, and catches naive double frees and frees to the wrong cache.
Most distros already enable it, and with sheaves its cost is small,
since the per-cpu fast paths don't touch freelists. Measurements also
show this quite clearly [1][2].
So let's just enable it by default. SLAB_BUCKETS defaults to
SLAB_FREELIST_HARDENED, so it's now enabled by default too.
Link: https://lore.kernel.org/all/auITixAJMfLtfa7i@chrisdown.name/ [1]
Link: https://lore.kernel.org/all/179312451613.474906.1475329637924619088@kernel.org/ [2]
Suggested-by: Vlastimil Babka <vbabka@kernel.org>
Signed-off-by: Chris Down <chris@chrisdown.name>
---
mm/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/mm/Kconfig b/mm/Kconfig
index 604c58199acb..17d017e8fbef 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -208,6 +208,7 @@ config SLAB_FREELIST_RANDOM
config SLAB_FREELIST_HARDENED
bool "Harden slab freelist metadata"
depends on !SLUB_TINY
+ default y
help
Many kernel heap attacks try to target slab cache metadata and
other infrastructure. This options makes minor performance
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/6] mm/slab: Enable SLAB_FREELIST_RANDOM by default
2026-10-29 6:07 [PATCH v2 0/6] mm/slab: Support selecting slab hardening features at boot Chris Down
2026-10-29 6:07 ` [PATCH v2 1/6] mm/slab: Enable SLAB_FREELIST_HARDENED by default Chris Down
@ 2026-10-29 6:07 ` Chris Down
2026-10-29 6:08 ` [PATCH v2 3/6] mm/slab: Support disabling SLAB_BUCKETS at boot Chris Down
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Chris Down @ 2026-10-29 6:07 UTC (permalink / raw)
To: Vlastimil Babka, Harry Yoo, Andrew Morton
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Kees Cook, Marco Elver, GONG Ruiqi, Jonathan Corbet, linux-mm,
linux-hardening, linux-doc, linux-kernel, kernel-team
SLAB_FREELIST_RANDOM randomises the order in which the objects in a new
slab are handed out. Like SLAB_FREELIST_HARDENED, most distros already
enable it, and its cost is only paid when a new slab is set up.
With it on, the same system level benchmarks didn't change measurably.
Allocating from new slabs does get slower, by up to about 30% per object
in a microbenchmark which does little else.
So let's enable it by default too. SHUFFLE_PAGE_ALLOCATOR defaults to
SLAB_FREELIST_RANDOM && ACPI_NUMA, so it's now built in by default on
those systems, but page shuffling itself stays off unless it's enabled
with page_alloc.shuffle.
Suggested-by: Vlastimil Babka <vbabka@kernel.org>
Signed-off-by: Chris Down <chris@chrisdown.name>
---
mm/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/mm/Kconfig b/mm/Kconfig
index 17d017e8fbef..92ff97ff24fb 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -200,6 +200,7 @@ config SLAB_MERGE_DEFAULT
config SLAB_FREELIST_RANDOM
bool "Randomize slab freelist"
depends on !SLUB_TINY
+ default y
help
Randomizes the freelist order used on creating new pages. This
security feature reduces the predictability of the kernel slab
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 3/6] mm/slab: Support disabling SLAB_BUCKETS at boot
2026-10-29 6:07 [PATCH v2 0/6] mm/slab: Support selecting slab hardening features at boot Chris Down
2026-10-29 6:07 ` [PATCH v2 1/6] mm/slab: Enable SLAB_FREELIST_HARDENED by default Chris Down
2026-10-29 6:07 ` [PATCH v2 2/6] mm/slab: Enable SLAB_FREELIST_RANDOM " Chris Down
@ 2026-10-29 6:08 ` Chris Down
2026-10-29 6:08 ` [PATCH v2 4/6] slub_kunit: Add a test for the slab_buckets boot parameter Chris Down
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Chris Down @ 2026-10-29 6:08 UTC (permalink / raw)
To: Vlastimil Babka, Harry Yoo, Andrew Morton
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Kees Cook, Marco Elver, GONG Ruiqi, Jonathan Corbet, linux-mm,
linux-hardening, linux-doc, linux-kernel, kernel-team
SLAB_BUCKETS gives allocations with user-controlled size and contents,
like memdup_user() and msg_msg, their own set of kmalloc caches, at the
cost of the memory for those caches. It can only be chosen at build
time, so hosts which want it and hosts which would rather not pay for it
need separate kernels.
Add a slab_buckets= early parameter, enabled by default on kernels built
with CONFIG_SLAB_BUCKETS=y, so that it can be turned off at boot.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
.../admin-guide/kernel-parameters.txt | 8 ++++++
mm/Kconfig | 4 +++
mm/slab_common.c | 26 +++++++++++++++----
3 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 68647ff4bdd2..de2fd6963a16 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -7001,6 +7001,14 @@ Kernel parameters
apic=verbose is specified.
Example: apic=debug show_lapic=all
+ slab_buckets= [MM,EARLY]
+ Format: <bool>
+ Enable or disable separate kmalloc buckets on kernels
+ built with CONFIG_SLAB_BUCKETS=y. When disabled,
+ allocations use regular kmalloc caches. Ignored
+ without that option.
+ Default: on.
+
slab_debug[=options[,slabs][;[options[,slabs]]...]] [MM]
Enabling slab_debug allows one to determine the
culprit if slab objects become corrupted. Enabling
diff --git a/mm/Kconfig b/mm/Kconfig
index 92ff97ff24fb..48078c1fd26f 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -231,6 +231,10 @@ config SLAB_BUCKETS
of extra pages since the bulk of user-controlled allocations
are relatively long-lived.
+ The separate buckets can be disabled at boot with the
+ "slab_buckets=0" kernel parameter, in which case these
+ allocations use the regular kmalloc caches.
+
If unsure, say Y.
config SLUB_STATS
diff --git a/mm/slab_common.c b/mm/slab_common.c
index e66c0778ee98..b7a46c368ab1 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -410,6 +410,16 @@ EXPORT_SYMBOL(__kmem_cache_create_args);
static struct kmem_cache *kmem_buckets_cache __ro_after_init;
+static bool slab_buckets_enabled __ro_after_init = IS_ENABLED(CONFIG_SLAB_BUCKETS);
+
+#ifdef CONFIG_SLAB_BUCKETS
+static int __init setup_slab_buckets(char *str)
+{
+ return kstrtobool(str, &slab_buckets_enabled);
+}
+early_param("slab_buckets", setup_slab_buckets);
+#endif
+
/**
* kmem_buckets_create - Create a set of caches that handle dynamic sized
* allocations via kmem_buckets_alloc()
@@ -424,10 +434,12 @@ static struct kmem_cache *kmem_buckets_cache __ro_after_init;
*
* Context: Cannot be called within an interrupt, but can be interrupted.
*
- * Return: a pointer to the cache on success, NULL on failure. When
- * CONFIG_SLAB_BUCKETS is not enabled, ZERO_SIZE_PTR is returned, and
- * subsequent calls to kmem_buckets_alloc() will fall back to kmalloc().
- * (i.e. callers only need to check for NULL on failure.)
+ * Return: a pointer to the cache on success, NULL on failure or when the
+ * separate buckets were disabled with the "slab_buckets=0" boot parameter.
+ * When CONFIG_SLAB_BUCKETS is not enabled, ZERO_SIZE_PTR is returned. In all
+ * of these cases subsequent calls to kmem_buckets_alloc() with the returned
+ * value fall back to kmalloc(), so callers that can live without separate
+ * buckets do not need to check the return value.
*/
kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags,
unsigned int useroffset,
@@ -448,6 +460,10 @@ kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags,
if (!IS_ENABLED(CONFIG_SLAB_BUCKETS))
return ZERO_SIZE_PTR;
+ /* NULL makes kmalloc_slab() use the regular kmalloc caches. */
+ if (!slab_buckets_enabled)
+ return NULL;
+
if (WARN_ON(!kmem_buckets_cache))
return NULL;
@@ -1059,7 +1075,7 @@ void __init create_kmalloc_caches(void)
/* Kmalloc array is now usable */
slab_state = UP;
- if (IS_ENABLED(CONFIG_SLAB_BUCKETS))
+ if (IS_ENABLED(CONFIG_SLAB_BUCKETS) && slab_buckets_enabled)
kmem_buckets_cache = kmem_cache_create("kmalloc_buckets",
sizeof(kmem_buckets),
0, SLAB_NO_MERGE, NULL);
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 4/6] slub_kunit: Add a test for the slab_buckets boot parameter
2026-10-29 6:07 [PATCH v2 0/6] mm/slab: Support selecting slab hardening features at boot Chris Down
` (2 preceding siblings ...)
2026-10-29 6:08 ` [PATCH v2 3/6] mm/slab: Support disabling SLAB_BUCKETS at boot Chris Down
@ 2026-10-29 6:08 ` Chris Down
2026-10-29 6:09 ` [PATCH v2 5/6] mm/slab: Support disabling KMALLOC_PARTITION_CACHES at boot Chris Down
2026-10-29 6:09 ` [PATCH v2 6/6] slub_kunit: Add a test for the kmalloc_partition boot parameter Chris Down
5 siblings, 0 replies; 7+ messages in thread
From: Chris Down @ 2026-10-29 6:08 UTC (permalink / raw)
To: Vlastimil Babka, Harry Yoo, Andrew Morton
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Kees Cook, Marco Elver, GONG Ruiqi, Jonathan Corbet, linux-mm,
linux-hardening, linux-doc, linux-kernel, kernel-team
Check that memdup_user() allocates from the memdup_user buckets by
default, and from the regular kmalloc caches when they're turned off
with slab_buckets=0.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
lib/tests/slub_kunit.c | 41 +++++++++++++++++++++++++++++++++++++++++
mm/slab.h | 4 ++++
mm/slab_common.c | 4 +++-
3 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/lib/tests/slub_kunit.c b/lib/tests/slub_kunit.c
index e3b63f0338d5..670645875b27 100644
--- a/lib/tests/slub_kunit.c
+++ b/lib/tests/slub_kunit.c
@@ -9,6 +9,8 @@
#include <linux/delay.h>
#include <linux/perf_event.h>
#include <linux/kprobes.h>
+#include <linux/mman.h>
+#include <linux/string.h>
#include "../mm/slab.h"
static struct kunit_resource resource;
@@ -296,6 +298,41 @@ static void test_krealloc_redzone_zeroing(struct kunit *test)
kmem_cache_destroy(s);
}
+#ifdef CONFIG_SLAB_BUCKETS
+static void test_slab_buckets(struct kunit *test)
+{
+ unsigned long user_addr;
+ const char *name;
+ void *p;
+
+ if (!slab_buckets_enabled)
+ KUNIT_EXPECT_NULL(test, kmem_buckets_create("TestSlub_buckets",
+ 0, 0, INT_MAX, NULL));
+
+ if (!IS_ENABLED(CONFIG_MMU))
+ kunit_skip(test, "userspace allocation needs an MMU");
+
+ user_addr = kunit_vm_mmap(test, NULL, 0, PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, 0);
+ KUNIT_ASSERT_NE_MSG(test, user_addr, 0, "Could not create userspace mm");
+ KUNIT_ASSERT_LT_MSG(test, user_addr, (unsigned long)TASK_SIZE,
+ "Failed to allocate user memory");
+
+ p = memdup_user((void __user *)user_addr, 64);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p);
+
+ name = virt_to_slab(p)->slab_cache->name;
+ if (slab_buckets_enabled)
+ KUNIT_EXPECT_TRUE_MSG(test, strstarts(name, "memdup_user-"),
+ "allocated from %s", name);
+ else
+ KUNIT_EXPECT_TRUE_MSG(test, strstarts(name, "kmalloc-"),
+ "allocated from %s", name);
+ kfree(p);
+}
+#endif
+
#if defined(CONFIG_PERF_EVENTS) || (defined(CONFIG_KPROBES) && defined(CONFIG_SMP))
#define NR_ITERATIONS 1000
#define NR_OBJECTS 1000
@@ -489,6 +526,9 @@ static struct kunit_case test_cases[] = {
KUNIT_CASE(test_kfree_rcu_wq_destroy),
KUNIT_CASE(test_leak_destroy),
KUNIT_CASE(test_krealloc_redzone_zeroing),
+#ifdef CONFIG_SLAB_BUCKETS
+ KUNIT_CASE(test_slab_buckets),
+#endif
#ifdef CONFIG_PERF_EVENTS
KUNIT_CASE_SLOW(test_kmalloc_nolock_and_friends_perf),
#endif
@@ -505,5 +545,6 @@ static struct kunit_suite test_suite = {
};
kunit_test_suite(test_suite);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
MODULE_DESCRIPTION("Kunit tests for slub allocator");
MODULE_LICENSE("GPL");
diff --git a/mm/slab.h b/mm/slab.h
index e94ac63d10dc..b5b344d6e402 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -390,6 +390,10 @@ extern struct list_head slab_caches;
/* The slab cache that manages slab cache information */
extern struct kmem_cache *kmem_cache;
+#if IS_ENABLED(CONFIG_KUNIT)
+extern bool slab_buckets_enabled;
+#endif
+
/* A table of kmalloc cache names and sizes */
extern const struct kmalloc_info_struct {
const char *name[NR_KMALLOC_TYPES];
diff --git a/mm/slab_common.c b/mm/slab_common.c
index b7a46c368ab1..9fe48da12010 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -29,6 +29,7 @@
#include <linux/memcontrol.h>
#include <linux/stackdepot.h>
#include <trace/events/rcu.h>
+#include <kunit/visibility.h>
#include "../kernel/rcu/rcu.h"
#include "internal.h"
@@ -410,7 +411,8 @@ EXPORT_SYMBOL(__kmem_cache_create_args);
static struct kmem_cache *kmem_buckets_cache __ro_after_init;
-static bool slab_buckets_enabled __ro_after_init = IS_ENABLED(CONFIG_SLAB_BUCKETS);
+VISIBLE_IF_KUNIT bool slab_buckets_enabled __ro_after_init = IS_ENABLED(CONFIG_SLAB_BUCKETS);
+EXPORT_SYMBOL_IF_KUNIT(slab_buckets_enabled);
#ifdef CONFIG_SLAB_BUCKETS
static int __init setup_slab_buckets(char *str)
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 5/6] mm/slab: Support disabling KMALLOC_PARTITION_CACHES at boot
2026-10-29 6:07 [PATCH v2 0/6] mm/slab: Support selecting slab hardening features at boot Chris Down
` (3 preceding siblings ...)
2026-10-29 6:08 ` [PATCH v2 4/6] slub_kunit: Add a test for the slab_buckets boot parameter Chris Down
@ 2026-10-29 6:09 ` Chris Down
2026-10-29 6:09 ` [PATCH v2 6/6] slub_kunit: Add a test for the kmalloc_partition boot parameter Chris Down
5 siblings, 0 replies; 7+ messages in thread
From: Chris Down @ 2026-10-29 6:09 UTC (permalink / raw)
To: Vlastimil Babka, Harry Yoo, Andrew Morton
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Kees Cook, Marco Elver, GONG Ruiqi, Jonathan Corbet, linux-mm,
linux-hardening, linux-doc, linux-kernel, kernel-team
KMALLOC_PARTITION_CACHES creates several copies of each normal kmalloc
cache and spreads allocations across them. That costs a fair bit of
memory: Harry measured about 18 MiB more slab memory after boot on a 64
CPU, 64 GiB VM, mostly from under-used slabs [1]. Like SLAB_BUCKETS, it
can only be chosen at build time.
Add a kmalloc_partition= early parameter, enabled by default on kernels
built with CONFIG_KMALLOC_PARTITION_CACHES=y. When it's off, the copies
alias the normal caches rather than being created.
Let's leave kmalloc_type() unchanged since each index simply resolves to
the same cache when partitioning is off.
Link: https://lore.kernel.org/r/179312451613.474906.1475329637924619088@kernel.org [1]
Signed-off-by: Chris Down <chris@chrisdown.name>
---
.../admin-guide/kernel-parameters.txt | 7 +++++++
mm/Kconfig | 5 +++++
mm/slab_common.c | 19 ++++++++++++++++++-
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index de2fd6963a16..6633a553a79c 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3054,6 +3054,13 @@ Kernel parameters
Configure the RouterBoard 532 series on-chip
Ethernet adapter MAC address.
+ kmalloc_partition= [MM,EARLY]
+ Format: <bool>
+ Enable or disable kmalloc cache partitioning on
+ kernels built with CONFIG_KMALLOC_PARTITION_CACHES=y.
+ Ignored without that option.
+ Default: on.
+
kmemleak= [KNL,EARLY] Boot-time kmemleak enable/disable
Valid arguments: on, off
Default: on
diff --git a/mm/Kconfig b/mm/Kconfig
index 48078c1fd26f..b90b3915fcd5 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -266,6 +266,11 @@ config KMALLOC_PARTITION_CACHES
limited degree of memory and CPU overhead that relates to hardware
and system workload.
+ The partitioning can be disabled at boot with the
+ "kmalloc_partition=0" kernel parameter, in which case the copies
+ are not created and all normal kmalloc allocations use the
+ regular kmalloc caches.
+
choice
prompt "Partitioned slab cache mode"
depends on KMALLOC_PARTITION_CACHES
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 9fe48da12010..5391149a2eed 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -781,6 +781,16 @@ unsigned long random_kmalloc_seed __ro_after_init;
EXPORT_SYMBOL(random_kmalloc_seed);
#endif
+#ifdef CONFIG_KMALLOC_PARTITION_CACHES
+static bool kmalloc_partition_enabled __ro_after_init = true;
+
+static int __init setup_kmalloc_partition(char *str)
+{
+ return kstrtobool(str, &kmalloc_partition_enabled);
+}
+early_param("kmalloc_partition", setup_kmalloc_partition);
+#endif
+
/*
* Conversion table for small slabs sizes / 8 to the index in the
* kmalloc array. This is necessary for slabs < 192 since we have non power
@@ -1013,8 +1023,15 @@ new_kmalloc_cache(int idx, enum kmalloc_cache_type type)
}
#ifdef CONFIG_KMALLOC_PARTITION_CACHES
- if (type >= KMALLOC_PARTITION_START && type <= KMALLOC_PARTITION_END)
+ if (!kmalloc_partition_enabled) {
+ /* Use the normal caches, which have already been created. */
+ if (type > KMALLOC_PARTITION_START && type <= KMALLOC_PARTITION_END) {
+ kmalloc_caches[type][idx] = kmalloc_caches[KMALLOC_NORMAL][idx];
+ return;
+ }
+ } else if (type >= KMALLOC_PARTITION_START && type <= KMALLOC_PARTITION_END) {
flags |= SLAB_NO_MERGE;
+ }
#endif
/*
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 6/6] slub_kunit: Add a test for the kmalloc_partition boot parameter
2026-10-29 6:07 [PATCH v2 0/6] mm/slab: Support selecting slab hardening features at boot Chris Down
` (4 preceding siblings ...)
2026-10-29 6:09 ` [PATCH v2 5/6] mm/slab: Support disabling KMALLOC_PARTITION_CACHES at boot Chris Down
@ 2026-10-29 6:09 ` Chris Down
5 siblings, 0 replies; 7+ messages in thread
From: Chris Down @ 2026-10-29 6:09 UTC (permalink / raw)
To: Vlastimil Babka, Harry Yoo, Andrew Morton
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Kees Cook, Marco Elver, GONG Ruiqi, Jonathan Corbet, linux-mm,
linux-hardening, linux-doc, linux-kernel, kernel-team
Check that the kmalloc partitions are separate caches by default, and
alias the normal kmalloc caches when they're turned off with
kmalloc_partition=0.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
lib/tests/slub_kunit.c | 46 ++++++++++++++++++++++++++++++++++++++++++
mm/slab.h | 4 ++++
mm/slab_common.c | 3 ++-
3 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/lib/tests/slub_kunit.c b/lib/tests/slub_kunit.c
index 670645875b27..e3035864577d 100644
--- a/lib/tests/slub_kunit.c
+++ b/lib/tests/slub_kunit.c
@@ -333,6 +333,49 @@ static void test_slab_buckets(struct kunit *test)
}
#endif
+#ifdef CONFIG_KMALLOC_PARTITION_CACHES
+/*
+ * Each partition copy is a separate cache, unless the copies were disabled
+ * with kmalloc_partition=0: then they alias the KMALLOC_NORMAL caches.
+ */
+static void test_kmalloc_partition(struct kunit *test)
+{
+ enum kmalloc_cache_type type;
+ struct kmem_cache *s;
+ unsigned int idx;
+ bool found;
+ void *p;
+
+ for (type = KMALLOC_PARTITION_START + 1; type <= KMALLOC_PARTITION_END; type++) {
+ for (idx = 0; idx < ARRAY_SIZE(kmalloc_caches[type]); idx++) {
+ struct kmem_cache *normal = kmalloc_caches[KMALLOC_NORMAL][idx];
+ struct kmem_cache *part = kmalloc_caches[type][idx];
+
+ if (!kmalloc_partition_enabled) {
+ KUNIT_EXPECT_PTR_EQ(test, part, normal);
+ } else if (normal) {
+ KUNIT_EXPECT_NOT_NULL(test, part);
+ KUNIT_EXPECT_PTR_NE(test, part, normal);
+ }
+ }
+ }
+
+ p = kmalloc(64, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, p);
+ s = virt_to_slab(p)->slab_cache;
+ idx = kmalloc_index(64);
+ if (!kmalloc_partition_enabled) {
+ KUNIT_EXPECT_PTR_EQ(test, s, kmalloc_caches[KMALLOC_NORMAL][idx]);
+ } else {
+ found = false;
+ for (type = KMALLOC_PARTITION_START; type <= KMALLOC_PARTITION_END; type++)
+ found |= s == kmalloc_caches[type][idx];
+ KUNIT_EXPECT_TRUE_MSG(test, found, "allocated from %s", s->name);
+ }
+ kfree(p);
+}
+#endif
+
#if defined(CONFIG_PERF_EVENTS) || (defined(CONFIG_KPROBES) && defined(CONFIG_SMP))
#define NR_ITERATIONS 1000
#define NR_OBJECTS 1000
@@ -529,6 +572,9 @@ static struct kunit_case test_cases[] = {
#ifdef CONFIG_SLAB_BUCKETS
KUNIT_CASE(test_slab_buckets),
#endif
+#ifdef CONFIG_KMALLOC_PARTITION_CACHES
+ KUNIT_CASE(test_kmalloc_partition),
+#endif
#ifdef CONFIG_PERF_EVENTS
KUNIT_CASE_SLOW(test_kmalloc_nolock_and_friends_perf),
#endif
diff --git a/mm/slab.h b/mm/slab.h
index b5b344d6e402..8e1e5a3f044b 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -394,6 +394,10 @@ extern struct kmem_cache *kmem_cache;
extern bool slab_buckets_enabled;
#endif
+#if IS_ENABLED(CONFIG_KUNIT) && defined(CONFIG_KMALLOC_PARTITION_CACHES)
+extern bool kmalloc_partition_enabled;
+#endif
+
/* A table of kmalloc cache names and sizes */
extern const struct kmalloc_info_struct {
const char *name[NR_KMALLOC_TYPES];
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 5391149a2eed..406e8688ee0e 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -782,7 +782,8 @@ EXPORT_SYMBOL(random_kmalloc_seed);
#endif
#ifdef CONFIG_KMALLOC_PARTITION_CACHES
-static bool kmalloc_partition_enabled __ro_after_init = true;
+VISIBLE_IF_KUNIT bool kmalloc_partition_enabled __ro_after_init = true;
+EXPORT_SYMBOL_IF_KUNIT(kmalloc_partition_enabled);
static int __init setup_kmalloc_partition(char *str)
{
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-10-29 6:09 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29 6:07 [PATCH v2 0/6] mm/slab: Support selecting slab hardening features at boot Chris Down
2026-10-29 6:07 ` [PATCH v2 1/6] mm/slab: Enable SLAB_FREELIST_HARDENED by default Chris Down
2026-10-29 6:07 ` [PATCH v2 2/6] mm/slab: Enable SLAB_FREELIST_RANDOM " Chris Down
2026-10-29 6:08 ` [PATCH v2 3/6] mm/slab: Support disabling SLAB_BUCKETS at boot Chris Down
2026-10-29 6:08 ` [PATCH v2 4/6] slub_kunit: Add a test for the slab_buckets boot parameter Chris Down
2026-10-29 6:09 ` [PATCH v2 5/6] mm/slab: Support disabling KMALLOC_PARTITION_CACHES at boot Chris Down
2026-10-29 6:09 ` [PATCH v2 6/6] slub_kunit: Add a test for the kmalloc_partition boot parameter Chris Down
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox