Skip to content

Commit db2ff25

Browse files
keesintel-lab-lkp
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#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]> Reviewed-by: Harry Yoo <[email protected]> Acked-by: Rafael Aquini <[email protected]> Tested-by: Petr Mladek <[email protected]> Reviewed-by: Petr Mladek <[email protected]> Signed-off-by: Kees Cook <[email protected]>
1 parent b2b2e9e commit db2ff25

File tree

4 files changed

+86
-20
lines changed

4 files changed

+86
-20
lines changed

Documentation/admin-guide/kernel-parameters.txt

+26-12
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,27 @@
17951795
backtraces on all cpus.
17961796
Format: 0 | 1
17971797

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

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

41334143
nohibernate [HIBERNATION] Disable hibernation and resume.
41344144

@@ -6478,6 +6488,10 @@
64786488
Documentation/mm/slub.rst.
64796489
(slub_debug legacy name also accepted for now)
64806490

6491+
Using this option implies the "no_hash_pointers"
6492+
option which can be undone by adding the
6493+
"hash_pointers=always" option.
6494+
64816495
slab_max_order= [MM]
64826496
Determines the maximum allowed order for slabs.
64836497
A high setting may cause OOMs due to memory

include/linux/sprintf.h

+1-1
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

+57-4
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

+2-3
Original file line numberDiff line numberDiff line change
@@ -6324,9 +6324,8 @@ void __init kmem_cache_init(void)
63246324
if (debug_guardpage_minorder())
63256325
slub_max_order = 0;
63266326

6327-
/* Print slub debugging pointers without hashing */
6328-
if (__slub_debug_enabled())
6329-
no_hash_pointers_enable(NULL);
6327+
/* Inform pointer hashing choice about slub debugging state. */
6328+
hash_pointers_finalize(__slub_debug_enabled());
63306329

63316330
kmem_cache_node = &boot_kmem_cache_node;
63326331
kmem_cache = &boot_kmem_cache;

0 commit comments

Comments
 (0)