Skip to content

Commit de1c831

Browse files
keespmladek
authored andcommitted
slab: Decouple slab_debug and no_hash_pointers
Some system owners use slab_debug=FPZ (or similar) as a hardening option, but do not want to be forced into having kernel addresses exposed due to the implicit "no_hash_pointers" boot param setting.[1] Introduce the "hash_pointers" boot param, which defaults to "auto" (the current behavior), but also includes "always" (forcing on hashing even when "slab_debug=..." is defined), and "never". The existing "no_hash_pointers" boot param becomes an alias for "hash_pointers=never". This makes it possible to boot with "slab_debug=FPZ hash_pointers=always". Link: KSPP/linux#368 [1] Fixes: 7927029 ("slub: force on no_hash_pointers when slub_debug is enabled") Co-developed-by: Sergio Perez Gonzalez <[email protected]> Signed-off-by: Sergio Perez Gonzalez <[email protected]> Acked-by: Vlastimil Babka <[email protected]> Acked-by: David Rientjes <[email protected]> Reviewed-by: Bagas Sanjaya <[email protected]> Signed-off-by: Kees Cook <[email protected]> Reviewed-by: Harry Yoo <[email protected]> Acked-by: Rafael Aquini <[email protected]> Tested-by: Petr Mladek <[email protected]> Reviewed-by: Petr Mladek <[email protected]> Link: https://patch.msgid.link/[email protected] [[email protected]: Add note about hash_pointers into slab_debug kernel parameter documentation.] Signed-off-by: Petr Mladek <[email protected]>
1 parent af54a3a commit de1c831

File tree

4 files changed

+86
-20
lines changed

4 files changed

+86
-20
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,6 +1798,27 @@
17981798
backtraces on all cpus.
17991799
Format: 0 | 1
18001800

1801+
hash_pointers=
1802+
[KNL,EARLY]
1803+
By default, when pointers are printed to the console
1804+
or buffers via the %p format string, that pointer is
1805+
"hashed", i.e. obscured by hashing the pointer value.
1806+
This is a security feature that hides actual kernel
1807+
addresses from unprivileged users, but it also makes
1808+
debugging the kernel more difficult since unequal
1809+
pointers can no longer be compared. The choices are:
1810+
Format: { auto | always | never }
1811+
Default: auto
1812+
1813+
auto - Hash pointers unless slab_debug is enabled.
1814+
always - Always hash pointers (even if slab_debug is
1815+
enabled).
1816+
never - Never hash pointers. This option should only
1817+
be specified when debugging the kernel. Do
1818+
not use on production kernels. The boot
1819+
param "no_hash_pointers" is an alias for
1820+
this mode.
1821+
18011822
hashdist= [KNL,NUMA] Large hashes allocated during boot
18021823
are distributed across NUMA nodes. Defaults on
18031824
for 64-bit NUMA, off otherwise.
@@ -4120,18 +4141,7 @@
41204141

41214142
no_hash_pointers
41224143
[KNL,EARLY]
4123-
Force pointers printed to the console or buffers to be
4124-
unhashed. By default, when a pointer is printed via %p
4125-
format string, that pointer is "hashed", i.e. obscured
4126-
by hashing the pointer value. This is a security feature
4127-
that hides actual kernel addresses from unprivileged
4128-
users, but it also makes debugging the kernel more
4129-
difficult since unequal pointers can no longer be
4130-
compared. However, if this command-line option is
4131-
specified, then all normal pointers will have their true
4132-
value printed. This option should only be specified when
4133-
debugging the kernel. Please do not use on production
4134-
kernels.
4144+
Alias for "hash_pointers=never".
41354145

41364146
nohibernate [HIBERNATION] Disable hibernation and resume.
41374147

@@ -6481,6 +6491,10 @@
64816491
Documentation/mm/slub.rst.
64826492
(slub_debug legacy name also accepted for now)
64836493

6494+
Using this option implies the "no_hash_pointers"
6495+
option which can be undone by adding the
6496+
"hash_pointers=always" option.
6497+
64846498
slab_max_order= [MM]
64856499
Determines the maximum allowed order for slabs.
64866500
A high setting may cause OOMs due to memory

include/linux/sprintf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ __scanf(2, 0) int vsscanf(const char *, const char *, va_list);
2222

2323
/* These are for specific cases, do not use without real need */
2424
extern bool no_hash_pointers;
25-
int no_hash_pointers_enable(char *str);
25+
void hash_pointers_finalize(bool slub_debug);
2626

2727
/* Used for Rust formatting ('%pA') */
2828
char *rust_fmt_argument(char *buf, char *end, const void *ptr);

lib/vsprintf.c

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,20 @@
6060
bool no_hash_pointers __ro_after_init;
6161
EXPORT_SYMBOL_GPL(no_hash_pointers);
6262

63+
/*
64+
* Hashed pointers policy selected by "hash_pointers=..." boot param
65+
*
66+
* `auto` - Hashed pointers enabled unless disabled by slub_debug_enabled=true
67+
* `always` - Hashed pointers enabled unconditionally
68+
* `never` - Hashed pointers disabled unconditionally
69+
*/
70+
enum hash_pointers_policy {
71+
HASH_PTR_AUTO = 0,
72+
HASH_PTR_ALWAYS,
73+
HASH_PTR_NEVER
74+
};
75+
static enum hash_pointers_policy hash_pointers_mode __initdata;
76+
6377
noinline
6478
static unsigned long long simple_strntoull(const char *startp, char **endp, unsigned int base, size_t max_chars)
6579
{
@@ -2271,12 +2285,23 @@ char *resource_or_range(const char *fmt, char *buf, char *end, void *ptr,
22712285
return resource_string(buf, end, ptr, spec, fmt);
22722286
}
22732287

2274-
int __init no_hash_pointers_enable(char *str)
2288+
void __init hash_pointers_finalize(bool slub_debug)
22752289
{
2276-
if (no_hash_pointers)
2277-
return 0;
2290+
switch (hash_pointers_mode) {
2291+
case HASH_PTR_ALWAYS:
2292+
no_hash_pointers = false;
2293+
break;
2294+
case HASH_PTR_NEVER:
2295+
no_hash_pointers = true;
2296+
break;
2297+
case HASH_PTR_AUTO:
2298+
default:
2299+
no_hash_pointers = slub_debug;
2300+
break;
2301+
}
22782302

2279-
no_hash_pointers = true;
2303+
if (!no_hash_pointers)
2304+
return;
22802305

22812306
pr_warn("**********************************************************\n");
22822307
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
@@ -2289,11 +2314,39 @@ int __init no_hash_pointers_enable(char *str)
22892314
pr_warn("** the kernel, report this immediately to your system **\n");
22902315
pr_warn("** administrator! **\n");
22912316
pr_warn("** **\n");
2317+
pr_warn("** Use hash_pointers=always to force this mode off **\n");
2318+
pr_warn("** **\n");
22922319
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
22932320
pr_warn("**********************************************************\n");
2321+
}
2322+
2323+
static int __init hash_pointers_mode_parse(char *str)
2324+
{
2325+
if (!str) {
2326+
pr_warn("Hash pointers mode empty; falling back to auto.\n");
2327+
hash_pointers_mode = HASH_PTR_AUTO;
2328+
} else if (strncmp(str, "auto", 4) == 0) {
2329+
pr_info("Hash pointers mode set to auto.\n");
2330+
hash_pointers_mode = HASH_PTR_AUTO;
2331+
} else if (strncmp(str, "never", 5) == 0) {
2332+
pr_info("Hash pointers mode set to never.\n");
2333+
hash_pointers_mode = HASH_PTR_NEVER;
2334+
} else if (strncmp(str, "always", 6) == 0) {
2335+
pr_info("Hash pointers mode set to always.\n");
2336+
hash_pointers_mode = HASH_PTR_ALWAYS;
2337+
} else {
2338+
pr_warn("Unknown hash_pointers mode '%s' specified; assuming auto.\n", str);
2339+
hash_pointers_mode = HASH_PTR_AUTO;
2340+
}
22942341

22952342
return 0;
22962343
}
2344+
early_param("hash_pointers", hash_pointers_mode_parse);
2345+
2346+
static int __init no_hash_pointers_enable(char *str)
2347+
{
2348+
return hash_pointers_mode_parse("never");
2349+
}
22972350
early_param("no_hash_pointers", no_hash_pointers_enable);
22982351

22992352
/*

mm/slub.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6314,9 +6314,8 @@ void __init kmem_cache_init(void)
63146314
if (debug_guardpage_minorder())
63156315
slub_max_order = 0;
63166316

6317-
/* Print slub debugging pointers without hashing */
6318-
if (__slub_debug_enabled())
6319-
no_hash_pointers_enable(NULL);
6317+
/* Inform pointer hashing choice about slub debugging state. */
6318+
hash_pointers_finalize(__slub_debug_enabled());
63206319

63216320
kmem_cache_node = &boot_kmem_cache_node;
63226321
kmem_cache = &boot_kmem_cache;

0 commit comments

Comments
 (0)