mm/kmsan/report.c

Source file repositories/reference/linux-study-clean/mm/kmsan/report.c

File Facts

System
Linux kernel
Corpus path
mm/kmsan/report.c
Extension
.c
Size
5942 bytes
Lines
222
Domain
Core OS
Bucket
Memory Management
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if ((nr_entries == 4) && (magic == KMSAN_ALLOCA_MAGIC_ORIGIN)) {
			descr = (char *)entries[1];
			pc1 = (void *)entries[2];
			pc2 = (void *)entries[3];
			pr_err("Local variable %s created at:\n",
			       pretty_descr(descr));
			if (pc1)
				pr_err(" %pSb\n", pc1);
			if (pc2)
				pr_err(" %pSb\n", pc2);
			break;
		}
		if ((nr_entries == 3) && (magic == KMSAN_CHAIN_MAGIC_ORIGIN)) {
			/*
			 * Origin chains deeper than KMSAN_MAX_ORIGIN_DEPTH are
			 * not stored, so the output may be incomplete.
			 */
			if (depth == KMSAN_MAX_ORIGIN_DEPTH)
				pr_err("<Zero or more stacks not recorded to save memory>\n\n");
			head = entries[1];
			origin = entries[2];
			pr_err("Uninit was stored to memory at:\n");
			chained_nr_entries =
				stack_depot_fetch(head, &chained_entries);
			kmsan_internal_unpoison_memory(
				chained_entries,
				chained_nr_entries * sizeof(*chained_entries),
				/*checked*/ false);
			skipnr = get_stack_skipnr(chained_entries,
						  chained_nr_entries);
			stack_trace_print(chained_entries + skipnr,
					  chained_nr_entries - skipnr, 0);
			pr_err("\n");
			continue;
		}
		pr_err("Uninit was created at:\n");
		if (nr_entries) {
			skipnr = get_stack_skipnr(entries, nr_entries);
			stack_trace_print(entries + skipnr, nr_entries - skipnr,
					  0);
		} else {
			pr_err("(stack is not available)\n");
		}
		break;
	}
}

void kmsan_report(depot_stack_handle_t origin, void *address, int size,
		  int off_first, int off_last, const void __user *user_addr,
		  enum kmsan_bug_reason reason)
{
	unsigned long stack_entries[KMSAN_STACK_DEPTH];
	int num_stack_entries, skipnr;
	char *bug_type = NULL;
	unsigned long ua_flags;
	bool is_uaf;

	if (!kmsan_enabled || kmsan_in_runtime())
		return;
	if (current->kmsan_ctx.depth)
		return;
	if (!origin)
		return;

	kmsan_enter_runtime();
	ua_flags = user_access_save();
	raw_spin_lock(&kmsan_report_lock);
	pr_err("=====================================================\n");
	is_uaf = kmsan_uaf_from_eb(stack_depot_get_extra_bits(origin));
	switch (reason) {
	case REASON_ANY:
		bug_type = is_uaf ? "use-after-free" : "uninit-value";
		break;
	case REASON_COPY_TO_USER:
		bug_type = is_uaf ? "kernel-infoleak-after-free" :
				    "kernel-infoleak";
		break;
	case REASON_SUBMIT_URB:
		bug_type = is_uaf ? "kernel-usb-infoleak-after-free" :
				    "kernel-usb-infoleak";
		break;
	}

	num_stack_entries =
		stack_trace_save(stack_entries, KMSAN_STACK_DEPTH, 1);
	skipnr = get_stack_skipnr(stack_entries, num_stack_entries);

	pr_err("BUG: KMSAN: %s in %pSb\n", bug_type,
	       (void *)stack_entries[skipnr]);
	stack_trace_print(stack_entries + skipnr, num_stack_entries - skipnr,

Annotation

Implementation Notes