slab: Decouple slab_debug and no_hash_pointers
Subsystems (5)
PATCH v3 1/1 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".
---
v3: add docs about implicit "no_hash_pointers" when using "slab_debug" (harry.yoo)
v2: https://lore.kernel.org/all/[email protected]/
v1: https://lore.kernel.org/lkml/[email protected]/
--- .../admin-guide/kernel-parameters.txt | 38 ++++++++---- include/linux/sprintf.h | 2 +- lib/vsprintf.c | 61 +++++++++++++++++-- mm/slub.c | 5 +- 4 files changed, 86 insertions(+), 20 deletions(-)
Documentation/admin-guide/kernel-parameters.txt +26 -12
@@ -1795,6 +1795,27 @@ backtraces on all cpus. Format: 0 | 1 + hash_pointers= + [KNL,EARLY] + By default, when pointers are printed to the console + or buffers via the %p format string, that pointer is + "hashed", i.e. obscured by hashing the pointer value. + This is a security feature that hides actual kernel + addresses from unprivileged users, but it also makes + debugging the kernel more difficult since unequal + pointers can no longer be compared. The choices are: + Format: { auto | always | never } + Default: auto + + auto - Hash pointers unless slab_debug is enabled. + always - Always hash pointers (even if slab_debug is + enabled). + never - Never hash pointers. This option should only + be specified when debugging the kernel. Do + not use on production kernels. The boot + param "no_hash_pointers" is an alias for + this mode. + hashdist= [KNL,NUMA] Large hashes allocated during boot are distributed across NUMA nodes. Defaults on for 64-bit NUMA, off otherwise.
@@ -4117,18 +4138,7 @@ no_hash_pointers [KNL,EARLY] - Force pointers printed to the console or buffers to be - unhashed. By default, when a pointer is printed via %p - format string, that pointer is "hashed", i.e. obscured - by hashing the pointer value. This is a security feature - that hides actual kernel addresses from unprivileged - users, but it also makes debugging the kernel more - difficult since unequal pointers can no longer be - compared. However, if this command-line option is - specified, then all normal pointers will have their true - value printed. This option should only be specified when - debugging the kernel. Please do not use on production - kernels. + Alias for "hash_pointers=never". nohibernate [HIBERNATION] Disable hibernation and resume.
@@ -6478,6 +6488,10 @@ Documentation/mm/slub.rst. (slub_debug legacy name also accepted for now) + Using this option implies the "no_hash_pointers" + option which can be undone by adding the + "hash_pointers=always" option. + slab_max_order= [MM] Determines the maximum allowed order for slabs. A high setting may cause OOMs due to memory
include/linux/sprintf.h +1 -1
@@ -22,7 +22,7 @@ __scanf(2, 0) int vsscanf(const char *, const char *, va_list);/* These are for specific cases, do not use without real need */ extern bool no_hash_pointers; -int no_hash_pointers_enable (char *str); +void hash_pointers_finalize (bool slub_debug);/* Used for Rust formatting ('%pA') */ char *rust_fmt_argument (char *buf,char *end,const void *ptr);
lib/vsprintf.c +57 -4
86 lines not on this page · raw message
mm/slub.c +2 -3
@@ -6314,9 +6314,8 @@ void __init kmem_cache_init(void)if (debug_guardpage_minorder ()) slub_max_order =0 ; -/* Print slub debugging pointers without hashing */ -if (__slub_debug_enabled ()) -no_hash_pointers_enable (NULL ); +/* Inform pointer hashing choice about slub debugging state. */ +hash_pointers_finalize (__slub_debug_enabled ()); kmem_cache_node = &boot_kmem_cache_node; kmem_cache = &boot_kmem_cache;
Signature · 1 line
2.34.1
Quoted 223 lines · Kees Cook
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".
Fixes 792702911f58 ("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]>---
v3: add docs about implicit "no_hash_pointers" when using "slab_debug" (harry.yoo)
v2: https://lore.kernel.org/all/[email protected]/
v1: https://lore.kernel.org/lkml/[email protected]/--- .../admin-guide/kernel-parameters.txt | 38 ++++++++---- include/linux/sprintf.h | 2 +- lib/vsprintf.c | 61 +++++++++++++++++-- mm/slub.c | 5 +- 4 files changed, 86 insertions(+), 20 deletions(-)Documentation/admin-guide/kernel-parameters.txt +26
-12@@ -1795,6 +1795,27 @@ backtraces on all cpus. Format: 0 | 1 + hash_pointers= + [KNL,EARLY] + By default, when pointers are printed to the console + or buffers via the %p format string, that pointer is + "hashed", i.e. obscured by hashing the pointer value. + This is a security feature that hides actual kernel + addresses from unprivileged users, but it also makes + debugging the kernel more difficult since unequal + pointers can no longer be compared. The choices are: + Format: { auto | always | never } + Default: auto + + auto - Hash pointers unless slab_debug is enabled. + always - Always hash pointers (even if slab_debug is + enabled). + never - Never hash pointers. This option should only + be specified when debugging the kernel. Do + not use on production kernels. The boot + param "no_hash_pointers" is an alias for + this mode. + hashdist= [KNL,NUMA] Large hashes allocated during boot are distributed across NUMA nodes. Defaults on for 64-bit NUMA, off otherwise.@@ -4117,18 +4138,7 @@ no_hash_pointers [KNL,EARLY] - Force pointers printed to the console or buffers to be - unhashed. By default, when a pointer is printed via %p - format string, that pointer is "hashed", i.e. obscured - by hashing the pointer value. This is a security feature - that hides actual kernel addresses from unprivileged - users, but it also makes debugging the kernel more - difficult since unequal pointers can no longer be - compared. However, if this command-line option is - specified, then all normal pointers will have their true - value printed. This option should only be specified when - debugging the kernel. Please do not use on production - kernels. + Alias for "hash_pointers=never". nohibernate [HIBERNATION] Disable hibernation and resume.@@ -6478,6 +6488,10 @@ Documentation/mm/slub.rst. (slub_debug legacy name also accepted for now) + Using this option implies the "no_hash_pointers" + option which can be undone by adding the + "hash_pointers=always" option. + slab_max_order= [MM] Determines the maximum allowed order for slabs. A high setting may cause OOMs due to memoryinclude/linux/sprintf.h +1
-1@@ -22,7 +22,7 @@ __scanf(2, 0) int vsscanf(const char *, const char *, va_list);/* These are for specific cases, do not use without real need */ extern bool no_hash_pointers; -int no_hash_pointers_enable (char *str); +void hash_pointers_finalize (bool slub_debug);/* Used for Rust formatting ('%pA') */ char *rust_fmt_argument (char *buf,char *end,const void *ptr);lib/vsprintf.c +57
-4@@ -60,6 +60,20 @@bool no_hash_pointers__ro_after_init ;EXPORT_SYMBOL_GPL (no_hash_pointers); +/* +* Hashed pointers policy selected by "hash_pointers=..." boot param +* +* `auto` - Hashed pointers enabled unless disabled by slub_debug_enabled=true +* `always` - Hashed pointers enabled unconditionally +* `never` - Hashed pointers disabled unconditionally +*/ +enum hash_pointers_policy { +HASH_PTR_AUTO =0 , +HASH_PTR_ALWAYS , +HASH_PTR_NEVER +}; +static enum hash_pointers_policy hash_pointers_mode__initdata ; +noinline static unsigned long long simple_strntoull(const char *startp, char **endp, unsigned int base, size_t max_chars) {@@ -2271,12 +2285,23 @@ char *resource_or_range(const char *fmt, char *buf, char *end, void *ptr,return resource_string (buf, end, ptr, spec, fmt); } -int __init no_hash_pointers_enable (char *str) +void __init hash_pointers_finalize (bool slub_debug) { -if (no_hash_pointers) -return 0 ; +switch (hash_pointers_mode) { +case HASH_PTR_ALWAYS : + no_hash_pointers = false; +break ; +case HASH_PTR_NEVER : + no_hash_pointers = true; +break ; +case HASH_PTR_AUTO : +default : + no_hash_pointers = slub_debug; +break ; + } - no_hash_pointers = true; +if (!no_hash_pointers) +return ;pr_warn ("**********************************************************\n" );pr_warn ("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n" );@@ -2289,11 +2314,39 @@ int __init no_hash_pointers_enable(char *str)pr_warn ("** the kernel, report this immediately to your system **\n" );pr_warn ("** administrator! **\n" );pr_warn ("** **\n" ); +pr_warn ("** Use hash_pointers=always to force this mode off **\n" ); +pr_warn ("** **\n" );pr_warn ("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n" );pr_warn ("**********************************************************\n" ); +} + +static int __init hash_pointers_mode_parse (char *str) +{ +if (!str) { +pr_warn ("Hash pointers mode empty; falling back to auto.\n" ); + hash_pointers_mode =HASH_PTR_AUTO ; + }else if (strncmp (str,"auto" ,4 ) ==0 ) { +pr_info ("Hash pointers mode set to auto.\n" ); + hash_pointers_mode =HASH_PTR_AUTO ; + }else if (strncmp (str,"never" ,5 ) ==0 ) { +pr_info ("Hash pointers mode set to never.\n" ); + hash_pointers_mode =HASH_PTR_NEVER ; + }else if (strncmp (str,"always" ,6 ) ==0 ) { +pr_info ("Hash pointers mode set to always.\n" ); + hash_pointers_mode =HASH_PTR_ALWAYS ; + }else { +pr_warn ("Unknown hash_pointers mode '%s' specified; assuming auto.\n" , str); + hash_pointers_mode =HASH_PTR_AUTO ; + }return 0 ; } +early_param ("hash_pointers" , hash_pointers_mode_parse); + +static int __init no_hash_pointers_enable (char *str) +{ +return hash_pointers_mode_parse ("never" ); +}early_param ("no_hash_pointers" , no_hash_pointers_enable);/* mm/slub.c +2
-3@@ -6314,9 +6314,8 @@ void __init kmem_cache_init(void)if (debug_guardpage_minorder ()) slub_max_order =0 ; -/* Print slub debugging pointers without hashing */ -if (__slub_debug_enabled ()) -no_hash_pointers_enable (NULL ); +/* Inform pointer hashing choice about slub debugging state. */ +hash_pointers_finalize (__slub_debug_enabled ()); kmem_cache_node = &boot_kmem_cache_node; kmem_cache = &boot_kmem_cache;Signature · 1 line
2.34.1