diff options
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 50 | 
1 files changed, 37 insertions, 13 deletions
| diff --git a/lib/vsprintf.c b/lib/vsprintf.c index a48aaa79d352..376de10929b3 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1651,6 +1651,17 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,  	return widen_string(buf, buf - buf_start, end, spec);  } +/* Make pointers available for printing early in the boot sequence. */ +static int debug_boot_weak_hash __ro_after_init; + +static int __init debug_boot_weak_hash_enable(char *str) +{ +	debug_boot_weak_hash = 1; +	pr_info("debug_boot_weak_hash enabled\n"); +	return 0; +} +early_param("debug_boot_weak_hash", debug_boot_weak_hash_enable); +  static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key);  static siphash_key_t ptr_key __read_mostly; @@ -1675,8 +1686,16 @@ static struct random_ready_callback random_ready = {  static int __init initialize_ptr_random(void)  { -	int ret = add_random_ready_callback(&random_ready); +	int key_size = sizeof(ptr_key); +	int ret; +	/* Use hw RNG if available. */ +	if (get_random_bytes_arch(&ptr_key, key_size) == key_size) { +		static_branch_disable(¬_filled_random_ptr_key); +		return 0; +	} + +	ret = add_random_ready_callback(&random_ready);  	if (!ret) {  		return 0;  	} else if (ret == -EALREADY) { @@ -1695,6 +1714,12 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec)  	const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)";  	unsigned long hashval; +	/* When debugging early boot use non-cryptographically secure hash. */ +	if (unlikely(debug_boot_weak_hash)) { +		hashval = hash_long((unsigned long)ptr, 32); +		return pointer_string(buf, end, (const void *)hashval, spec); +	} +  	if (static_branch_unlikely(¬_filled_random_ptr_key)) {  		spec.field_width = 2 * sizeof(ptr);  		/* string length must be less than default_width */ @@ -1808,17 +1833,15 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec)   *       p page flags (see struct page) given as pointer to unsigned long   *       g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t   *       v vma flags (VM_*) given as pointer to unsigned long - * - 'O' For a kobject based struct. Must be one of the following: - *       - 'OF[fnpPcCF]'  For a device tree object - *                        Without any optional arguments prints the full_name - *                        f device node full_name - *                        n device node name - *                        p device node phandle - *                        P device node path spec (name + @unit) - *                        F device node flags - *                        c major compatible string - *                        C full compatible string - * + * - 'OF[fnpPcCF]'  For a device tree object + *                  Without any optional arguments prints the full_name + *                  f device node full_name + *                  n device node name + *                  p device node phandle + *                  P device node path spec (name + @unit) + *                  F device node flags + *                  c major compatible string + *                  C full compatible string   * - 'x' For printing the address. Equivalent to "%lx".   *   * ** When making changes please also update: @@ -1942,6 +1965,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,  		case 'F':  			return device_node_string(buf, end, ptr, spec, fmt + 1);  		} +		break;  	case 'x':  		return pointer_string(buf, end, ptr, spec);  	} @@ -2768,7 +2792,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)  						copy = end - str;  					memcpy(str, args, copy);  					str += len; -					args += len; +					args += len + 1;  				}  			}  			if (process) |