lib/vsprintf: no_hash_pointers prints all addresses as unhashed

If the no_hash_pointers command line parameter is set, then
printk("%p") will print pointers as unhashed, which is useful for
debugging purposes.  This change applies to any function that uses
vsprintf, such as print_hex_dump() and seq_buf_printf().

A large warning message is displayed if this option is enabled.
Unhashed pointers expose kernel addresses, which can be a security
risk.

Also update test_printf to skip the hashed pointer tests if the
command-line option is set.

Signed-off-by: Timur Tabi <timur@kernel.org>
Acked-by: Petr Mladek <pmladek@suse.com>
Acked-by: Randy Dunlap <rdunlap@infradead.org>
Acked-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Marco Elver <elver@google.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20210214161348.369023-4-timur@kernel.org
This commit is contained in:
Timur Tabi 2021-02-14 10:13:48 -06:00 committed by Petr Mladek
parent d9d4de2309
commit 5ead723a20
3 changed files with 57 additions and 2 deletions

View File

@ -3281,6 +3281,21 @@
in certain environments such as networked servers or in certain environments such as networked servers or
real-time systems. real-time systems.
no_hash_pointers
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. Pointers printed via %pK may still be
hashed. This option should only be specified when
debugging the kernel. Please do not use on production
kernels.
nohibernate [HIBERNATION] Disable hibernation and resume. nohibernate [HIBERNATION] Disable hibernation and resume.
nohz= [KNL] Boottime enable/disable dynamic ticks nohz= [KNL] Boottime enable/disable dynamic ticks

View File

@ -35,6 +35,8 @@ KSTM_MODULE_GLOBALS();
static char *test_buffer __initdata; static char *test_buffer __initdata;
static char *alloced_buffer __initdata; static char *alloced_buffer __initdata;
extern bool no_hash_pointers;
static int __printf(4, 0) __init static int __printf(4, 0) __init
do_test(int bufsize, const char *expect, int elen, do_test(int bufsize, const char *expect, int elen,
const char *fmt, va_list ap) const char *fmt, va_list ap)
@ -301,6 +303,12 @@ plain(void)
{ {
int err; int err;
if (no_hash_pointers) {
pr_warn("skipping plain 'p' tests");
skipped_tests += 2;
return;
}
err = plain_hash(); err = plain_hash();
if (err) { if (err) {
pr_warn("plain 'p' does not appear to be hashed\n"); pr_warn("plain 'p' does not appear to be hashed\n");

View File

@ -2090,6 +2090,32 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
return widen_string(buf, buf - buf_start, end, spec); return widen_string(buf, buf - buf_start, end, spec);
} }
/* Disable pointer hashing if requested */
bool no_hash_pointers __ro_after_init;
EXPORT_SYMBOL_GPL(no_hash_pointers);
static int __init no_hash_pointers_enable(char *str)
{
no_hash_pointers = true;
pr_warn("**********************************************************\n");
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
pr_warn("** **\n");
pr_warn("** This system shows unhashed kernel memory addresses **\n");
pr_warn("** via the console, logs, and other interfaces. This **\n");
pr_warn("** might reduce the security of your system. **\n");
pr_warn("** **\n");
pr_warn("** If you see this message and you are not debugging **\n");
pr_warn("** the kernel, report this immediately to your system **\n");
pr_warn("** administrator! **\n");
pr_warn("** **\n");
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
pr_warn("**********************************************************\n");
return 0;
}
early_param("no_hash_pointers", no_hash_pointers_enable);
/* /*
* Show a '%p' thing. A kernel extension is that the '%p' is followed * Show a '%p' thing. A kernel extension is that the '%p' is followed
* by an extra set of alphanumeric characters that are extended format * by an extra set of alphanumeric characters that are extended format
@ -2297,8 +2323,14 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
} }
} }
/* default is to _not_ leak addresses, hash before printing */ /*
return ptr_to_id(buf, end, ptr, spec); * default is to _not_ leak addresses, so hash before printing,
* unless no_hash_pointers is specified on the command line.
*/
if (unlikely(no_hash_pointers))
return pointer_string(buf, end, ptr, spec);
else
return ptr_to_id(buf, end, ptr, spec);
} }
/* /*