lib/ubsan.c

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

File Facts

System
Linux kernel
Corpus path
lib/ubsan.c
Extension
.c
Size
14489 bytes
Lines
562
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

if (type_bit_width(type) == 128) {
#if defined(CONFIG_ARCH_SUPPORTS_INT128)
			u_max val = get_unsigned_val(type, value);

			scnprintf(str, size, "0x%08x%08x%08x%08x",
				(u32)(val >> 96),
				(u32)(val >> 64),
				(u32)(val >> 32),
				(u32)(val));
#else
			WARN_ON(1);
#endif
		} else if (type_is_signed(type)) {
			scnprintf(str, size, "%lld",
				(s64)get_signed_val(type, value));
		} else {
			scnprintf(str, size, "%llu",
				(u64)get_unsigned_val(type, value));
		}
	}
}

static void ubsan_prologue(struct source_location *loc, const char *reason)
{
	current->in_ubsan++;

	pr_warn(CUT_HERE);

	pr_err("UBSAN: %s in %s:%d:%d\n", reason, loc->file_name,
		loc->line & LINE_MASK, loc->column & COLUMN_MASK);

	kunit_fail_current_test("%s in %s", reason, loc->file_name);
}

static void ubsan_epilogue(void)
{
	dump_stack();
	pr_warn("---[ end trace ]---\n");

	current->in_ubsan--;

	check_panic_on_warn("UBSAN");
}

static void handle_overflow(struct overflow_data *data, void *lhs,
			void *rhs, char op)
{

	struct type_descriptor *type = data->type;
	char lhs_val_str[VALUE_LENGTH];
	char rhs_val_str[VALUE_LENGTH];

	if (suppress_report(&data->location))
		return;

	ubsan_prologue(&data->location, type_is_signed(type) ?
			"signed-integer-overflow" :
			"unsigned-integer-overflow");

	val_to_string(lhs_val_str, sizeof(lhs_val_str), type, lhs);
	val_to_string(rhs_val_str, sizeof(rhs_val_str), type, rhs);
	pr_err("%s %c %s cannot be represented in type %s\n",
		lhs_val_str,
		op,
		rhs_val_str,
		type->type_name);

	ubsan_epilogue();
}

void __ubsan_handle_add_overflow(void *data,
				void *lhs, void *rhs)
{

	handle_overflow(data, lhs, rhs, '+');
}
EXPORT_SYMBOL(__ubsan_handle_add_overflow);

void __ubsan_handle_sub_overflow(void *data,
				void *lhs, void *rhs)
{
	handle_overflow(data, lhs, rhs, '-');
}
EXPORT_SYMBOL(__ubsan_handle_sub_overflow);

void __ubsan_handle_mul_overflow(void *data,
				void *lhs, void *rhs)
{
	handle_overflow(data, lhs, rhs, '*');
}

Annotation

Implementation Notes