forked from mirrors/linux
		
	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:
		
							parent
							
								
									d9d4de2309
								
							
						
					
					
						commit
						5ead723a20
					
				
					 3 changed files with 57 additions and 2 deletions
				
			
		| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,7 +2323,13 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* default is to _not_ leak addresses, hash before printing */
 | 
						/*
 | 
				
			||||||
 | 
						 * 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);
 | 
							return ptr_to_id(buf, end, ptr, spec);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue