162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * KMSAN error reporting routines.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2019-2022 Google LLC
662306a36Sopenharmony_ci * Author: Alexander Potapenko <glider@google.com>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/console.h>
1162306a36Sopenharmony_ci#include <linux/moduleparam.h>
1262306a36Sopenharmony_ci#include <linux/stackdepot.h>
1362306a36Sopenharmony_ci#include <linux/stacktrace.h>
1462306a36Sopenharmony_ci#include <linux/uaccess.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "kmsan.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(kmsan_report_lock);
1962306a36Sopenharmony_ci#define DESCR_SIZE 128
2062306a36Sopenharmony_ci/* Protected by kmsan_report_lock */
2162306a36Sopenharmony_cistatic char report_local_descr[DESCR_SIZE];
2262306a36Sopenharmony_ciint panic_on_kmsan __read_mostly;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#ifdef MODULE_PARAM_PREFIX
2562306a36Sopenharmony_ci#undef MODULE_PARAM_PREFIX
2662306a36Sopenharmony_ci#endif
2762306a36Sopenharmony_ci#define MODULE_PARAM_PREFIX "kmsan."
2862306a36Sopenharmony_cimodule_param_named(panic, panic_on_kmsan, int, 0);
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/*
3162306a36Sopenharmony_ci * Skip internal KMSAN frames.
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_cistatic int get_stack_skipnr(const unsigned long stack_entries[],
3462306a36Sopenharmony_ci			    int num_entries)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	int len, skip;
3762306a36Sopenharmony_ci	char buf[64];
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	for (skip = 0; skip < num_entries; ++skip) {
4062306a36Sopenharmony_ci		len = scnprintf(buf, sizeof(buf), "%ps",
4162306a36Sopenharmony_ci				(void *)stack_entries[skip]);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci		/* Never show __msan_* or kmsan_* functions. */
4462306a36Sopenharmony_ci		if ((strnstr(buf, "__msan_", len) == buf) ||
4562306a36Sopenharmony_ci		    (strnstr(buf, "kmsan_", len) == buf))
4662306a36Sopenharmony_ci			continue;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci		/*
4962306a36Sopenharmony_ci		 * No match for runtime functions -- @skip entries to skip to
5062306a36Sopenharmony_ci		 * get to first frame of interest.
5162306a36Sopenharmony_ci		 */
5262306a36Sopenharmony_ci		break;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	return skip;
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/*
5962306a36Sopenharmony_ci * Currently the descriptions of locals generated by Clang look as follows:
6062306a36Sopenharmony_ci *   ----local_name@function_name
6162306a36Sopenharmony_ci * We want to print only the name of the local, as other information in that
6262306a36Sopenharmony_ci * description can be confusing.
6362306a36Sopenharmony_ci * The meaningful part of the description is copied to a global buffer to avoid
6462306a36Sopenharmony_ci * allocating memory.
6562306a36Sopenharmony_ci */
6662306a36Sopenharmony_cistatic char *pretty_descr(char *descr)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	int pos = 0, len = strlen(descr);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	for (int i = 0; i < len; i++) {
7162306a36Sopenharmony_ci		if (descr[i] == '@')
7262306a36Sopenharmony_ci			break;
7362306a36Sopenharmony_ci		if (descr[i] == '-')
7462306a36Sopenharmony_ci			continue;
7562306a36Sopenharmony_ci		report_local_descr[pos] = descr[i];
7662306a36Sopenharmony_ci		if (pos + 1 == DESCR_SIZE)
7762306a36Sopenharmony_ci			break;
7862306a36Sopenharmony_ci		pos++;
7962306a36Sopenharmony_ci	}
8062306a36Sopenharmony_ci	report_local_descr[pos] = 0;
8162306a36Sopenharmony_ci	return report_local_descr;
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_civoid kmsan_print_origin(depot_stack_handle_t origin)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	unsigned long *entries = NULL, *chained_entries = NULL;
8762306a36Sopenharmony_ci	unsigned int nr_entries, chained_nr_entries, skipnr;
8862306a36Sopenharmony_ci	void *pc1 = NULL, *pc2 = NULL;
8962306a36Sopenharmony_ci	depot_stack_handle_t head;
9062306a36Sopenharmony_ci	unsigned long magic;
9162306a36Sopenharmony_ci	char *descr = NULL;
9262306a36Sopenharmony_ci	unsigned int depth;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	if (!origin)
9562306a36Sopenharmony_ci		return;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	while (true) {
9862306a36Sopenharmony_ci		nr_entries = stack_depot_fetch(origin, &entries);
9962306a36Sopenharmony_ci		depth = kmsan_depth_from_eb(stack_depot_get_extra_bits(origin));
10062306a36Sopenharmony_ci		magic = nr_entries ? entries[0] : 0;
10162306a36Sopenharmony_ci		if ((nr_entries == 4) && (magic == KMSAN_ALLOCA_MAGIC_ORIGIN)) {
10262306a36Sopenharmony_ci			descr = (char *)entries[1];
10362306a36Sopenharmony_ci			pc1 = (void *)entries[2];
10462306a36Sopenharmony_ci			pc2 = (void *)entries[3];
10562306a36Sopenharmony_ci			pr_err("Local variable %s created at:\n",
10662306a36Sopenharmony_ci			       pretty_descr(descr));
10762306a36Sopenharmony_ci			if (pc1)
10862306a36Sopenharmony_ci				pr_err(" %pSb\n", pc1);
10962306a36Sopenharmony_ci			if (pc2)
11062306a36Sopenharmony_ci				pr_err(" %pSb\n", pc2);
11162306a36Sopenharmony_ci			break;
11262306a36Sopenharmony_ci		}
11362306a36Sopenharmony_ci		if ((nr_entries == 3) && (magic == KMSAN_CHAIN_MAGIC_ORIGIN)) {
11462306a36Sopenharmony_ci			/*
11562306a36Sopenharmony_ci			 * Origin chains deeper than KMSAN_MAX_ORIGIN_DEPTH are
11662306a36Sopenharmony_ci			 * not stored, so the output may be incomplete.
11762306a36Sopenharmony_ci			 */
11862306a36Sopenharmony_ci			if (depth == KMSAN_MAX_ORIGIN_DEPTH)
11962306a36Sopenharmony_ci				pr_err("<Zero or more stacks not recorded to save memory>\n\n");
12062306a36Sopenharmony_ci			head = entries[1];
12162306a36Sopenharmony_ci			origin = entries[2];
12262306a36Sopenharmony_ci			pr_err("Uninit was stored to memory at:\n");
12362306a36Sopenharmony_ci			chained_nr_entries =
12462306a36Sopenharmony_ci				stack_depot_fetch(head, &chained_entries);
12562306a36Sopenharmony_ci			kmsan_internal_unpoison_memory(
12662306a36Sopenharmony_ci				chained_entries,
12762306a36Sopenharmony_ci				chained_nr_entries * sizeof(*chained_entries),
12862306a36Sopenharmony_ci				/*checked*/ false);
12962306a36Sopenharmony_ci			skipnr = get_stack_skipnr(chained_entries,
13062306a36Sopenharmony_ci						  chained_nr_entries);
13162306a36Sopenharmony_ci			stack_trace_print(chained_entries + skipnr,
13262306a36Sopenharmony_ci					  chained_nr_entries - skipnr, 0);
13362306a36Sopenharmony_ci			pr_err("\n");
13462306a36Sopenharmony_ci			continue;
13562306a36Sopenharmony_ci		}
13662306a36Sopenharmony_ci		pr_err("Uninit was created at:\n");
13762306a36Sopenharmony_ci		if (nr_entries) {
13862306a36Sopenharmony_ci			skipnr = get_stack_skipnr(entries, nr_entries);
13962306a36Sopenharmony_ci			stack_trace_print(entries + skipnr, nr_entries - skipnr,
14062306a36Sopenharmony_ci					  0);
14162306a36Sopenharmony_ci		} else {
14262306a36Sopenharmony_ci			pr_err("(stack is not available)\n");
14362306a36Sopenharmony_ci		}
14462306a36Sopenharmony_ci		break;
14562306a36Sopenharmony_ci	}
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_civoid kmsan_report(depot_stack_handle_t origin, void *address, int size,
14962306a36Sopenharmony_ci		  int off_first, int off_last, const void *user_addr,
15062306a36Sopenharmony_ci		  enum kmsan_bug_reason reason)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	unsigned long stack_entries[KMSAN_STACK_DEPTH];
15362306a36Sopenharmony_ci	int num_stack_entries, skipnr;
15462306a36Sopenharmony_ci	char *bug_type = NULL;
15562306a36Sopenharmony_ci	unsigned long ua_flags;
15662306a36Sopenharmony_ci	bool is_uaf;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	if (!kmsan_enabled)
15962306a36Sopenharmony_ci		return;
16062306a36Sopenharmony_ci	if (!current->kmsan_ctx.allow_reporting)
16162306a36Sopenharmony_ci		return;
16262306a36Sopenharmony_ci	if (!origin)
16362306a36Sopenharmony_ci		return;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	current->kmsan_ctx.allow_reporting = false;
16662306a36Sopenharmony_ci	ua_flags = user_access_save();
16762306a36Sopenharmony_ci	raw_spin_lock(&kmsan_report_lock);
16862306a36Sopenharmony_ci	pr_err("=====================================================\n");
16962306a36Sopenharmony_ci	is_uaf = kmsan_uaf_from_eb(stack_depot_get_extra_bits(origin));
17062306a36Sopenharmony_ci	switch (reason) {
17162306a36Sopenharmony_ci	case REASON_ANY:
17262306a36Sopenharmony_ci		bug_type = is_uaf ? "use-after-free" : "uninit-value";
17362306a36Sopenharmony_ci		break;
17462306a36Sopenharmony_ci	case REASON_COPY_TO_USER:
17562306a36Sopenharmony_ci		bug_type = is_uaf ? "kernel-infoleak-after-free" :
17662306a36Sopenharmony_ci				    "kernel-infoleak";
17762306a36Sopenharmony_ci		break;
17862306a36Sopenharmony_ci	case REASON_SUBMIT_URB:
17962306a36Sopenharmony_ci		bug_type = is_uaf ? "kernel-usb-infoleak-after-free" :
18062306a36Sopenharmony_ci				    "kernel-usb-infoleak";
18162306a36Sopenharmony_ci		break;
18262306a36Sopenharmony_ci	}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	num_stack_entries =
18562306a36Sopenharmony_ci		stack_trace_save(stack_entries, KMSAN_STACK_DEPTH, 1);
18662306a36Sopenharmony_ci	skipnr = get_stack_skipnr(stack_entries, num_stack_entries);
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	pr_err("BUG: KMSAN: %s in %pSb\n", bug_type,
18962306a36Sopenharmony_ci	       (void *)stack_entries[skipnr]);
19062306a36Sopenharmony_ci	stack_trace_print(stack_entries + skipnr, num_stack_entries - skipnr,
19162306a36Sopenharmony_ci			  0);
19262306a36Sopenharmony_ci	pr_err("\n");
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	kmsan_print_origin(origin);
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	if (size) {
19762306a36Sopenharmony_ci		pr_err("\n");
19862306a36Sopenharmony_ci		if (off_first == off_last)
19962306a36Sopenharmony_ci			pr_err("Byte %d of %d is uninitialized\n", off_first,
20062306a36Sopenharmony_ci			       size);
20162306a36Sopenharmony_ci		else
20262306a36Sopenharmony_ci			pr_err("Bytes %d-%d of %d are uninitialized\n",
20362306a36Sopenharmony_ci			       off_first, off_last, size);
20462306a36Sopenharmony_ci	}
20562306a36Sopenharmony_ci	if (address)
20662306a36Sopenharmony_ci		pr_err("Memory access of size %d starts at %px\n", size,
20762306a36Sopenharmony_ci		       address);
20862306a36Sopenharmony_ci	if (user_addr && reason == REASON_COPY_TO_USER)
20962306a36Sopenharmony_ci		pr_err("Data copied to user address %px\n", user_addr);
21062306a36Sopenharmony_ci	pr_err("\n");
21162306a36Sopenharmony_ci	dump_stack_print_info(KERN_ERR);
21262306a36Sopenharmony_ci	pr_err("=====================================================\n");
21362306a36Sopenharmony_ci	add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
21462306a36Sopenharmony_ci	raw_spin_unlock(&kmsan_report_lock);
21562306a36Sopenharmony_ci	if (panic_on_kmsan)
21662306a36Sopenharmony_ci		panic("kmsan.panic set ...\n");
21762306a36Sopenharmony_ci	user_access_restore(ua_flags);
21862306a36Sopenharmony_ci	current->kmsan_ctx.allow_reporting = true;
21962306a36Sopenharmony_ci}
220