lib/vsprintf.c

Source file repositories/reference/linux-study-clean/lib/vsprintf.c

File Facts

System
Linux kernel
Corpus path
lib/vsprintf.c
Extension
.c
Size
92345 bytes
Lines
3747
Domain
Kernel Services
Bucket
lib
Inferred role
Kernel Services: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

subsys_initcall(vsprintf_init_hashval)

/* Maps a pointer to a 32 bit unique identifier. */
static inline int __ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
{
	unsigned long hashval;

	if (!READ_ONCE(filled_random_ptr_key))
		return -EBUSY;

	/* Pairs with smp_wmb() after writing ptr_key. */
	smp_rmb();

#ifdef CONFIG_64BIT
	hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key);
	/*
	 * Mask off the first 32 bits, this makes explicit that we have
	 * modified the address (and 32 bits is plenty for a unique ID).
	 */
	hashval = hashval & 0xffffffff;
#else
	hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key);
#endif
	*hashval_out = hashval;
	return 0;
}

int ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
{
	return __ptr_to_hashval(ptr, hashval_out);
}

static char *ptr_to_id(char *buf, char *end, const void *ptr,
		       struct printf_spec spec)
{
	const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)";
	unsigned long hashval;
	int ret;

	/*
	 * Print the real pointer value for NULL and error pointers,
	 * as they are not actual addresses.
	 */
	if (IS_ERR_OR_NULL(ptr))
		return pointer_string(buf, end, ptr, spec);

	/* 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);
	}

	ret = __ptr_to_hashval(ptr, &hashval);
	if (ret) {
		spec.field_width = 2 * sizeof(ptr);
		/* string length must be less than default_width */
		return error_string(buf, end, str, spec);
	}

	return pointer_string(buf, end, (const void *)hashval, spec);
}

static char *default_pointer(char *buf, char *end, const void *ptr,
			     struct printf_spec 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);

	return ptr_to_id(buf, end, ptr, spec);
}

int kptr_restrict __read_mostly;
EXPORT_SYMBOL_FOR_MODULES(kptr_restrict, "printf_kunit");

static noinline_for_stack
char *restricted_pointer(char *buf, char *end, const void *ptr,
			 struct printf_spec spec)
{
	switch (kptr_restrict) {
	case 0:
		/* Handle as %p, hash and do _not_ leak addresses. */
		return default_pointer(buf, end, ptr, spec);
	case 1: {
		const struct cred *cred;

		/*

Annotation

Implementation Notes