brintos

brintos / linux-shallow public Read only

0
0
Text · 5.8 KiB · 94a3303 Raw
222 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * KMSAN error reporting routines.4 *5 * Copyright (C) 2019-2022 Google LLC6 * Author: Alexander Potapenko <glider@google.com>7 *8 */9 10#include <linux/console.h>11#include <linux/kmsan.h>12#include <linux/moduleparam.h>13#include <linux/stackdepot.h>14#include <linux/stacktrace.h>15#include <linux/uaccess.h>16 17#include "kmsan.h"18 19static DEFINE_RAW_SPINLOCK(kmsan_report_lock);20#define DESCR_SIZE 12821/* Protected by kmsan_report_lock */22static char report_local_descr[DESCR_SIZE];23int panic_on_kmsan __read_mostly;24EXPORT_SYMBOL_GPL(panic_on_kmsan);25 26#ifdef MODULE_PARAM_PREFIX27#undef MODULE_PARAM_PREFIX28#endif29#define MODULE_PARAM_PREFIX "kmsan."30module_param_named(panic, panic_on_kmsan, int, 0);31 32/*33 * Skip internal KMSAN frames.34 */35static int get_stack_skipnr(const unsigned long stack_entries[],36			    int num_entries)37{38	int len, skip;39	char buf[64];40 41	for (skip = 0; skip < num_entries; ++skip) {42		len = scnprintf(buf, sizeof(buf), "%ps",43				(void *)stack_entries[skip]);44 45		/* Never show __msan_* or kmsan_* functions. */46		if ((strnstr(buf, "__msan_", len) == buf) ||47		    (strnstr(buf, "kmsan_", len) == buf))48			continue;49 50		/*51		 * No match for runtime functions -- @skip entries to skip to52		 * get to first frame of interest.53		 */54		break;55	}56 57	return skip;58}59 60/*61 * Currently the descriptions of locals generated by Clang look as follows:62 *   ----local_name@function_name63 * We want to print only the name of the local, as other information in that64 * description can be confusing.65 * The meaningful part of the description is copied to a global buffer to avoid66 * allocating memory.67 */68static char *pretty_descr(char *descr)69{70	int pos = 0, len = strlen(descr);71 72	for (int i = 0; i < len; i++) {73		if (descr[i] == '@')74			break;75		if (descr[i] == '-')76			continue;77		report_local_descr[pos] = descr[i];78		if (pos + 1 == DESCR_SIZE)79			break;80		pos++;81	}82	report_local_descr[pos] = 0;83	return report_local_descr;84}85 86void kmsan_print_origin(depot_stack_handle_t origin)87{88	unsigned long *entries = NULL, *chained_entries = NULL;89	unsigned int nr_entries, chained_nr_entries, skipnr;90	void *pc1 = NULL, *pc2 = NULL;91	depot_stack_handle_t head;92	unsigned long magic;93	char *descr = NULL;94	unsigned int depth;95 96	if (!origin)97		return;98 99	while (true) {100		nr_entries = stack_depot_fetch(origin, &entries);101		depth = kmsan_depth_from_eb(stack_depot_get_extra_bits(origin));102		magic = nr_entries ? entries[0] : 0;103		if ((nr_entries == 4) && (magic == KMSAN_ALLOCA_MAGIC_ORIGIN)) {104			descr = (char *)entries[1];105			pc1 = (void *)entries[2];106			pc2 = (void *)entries[3];107			pr_err("Local variable %s created at:\n",108			       pretty_descr(descr));109			if (pc1)110				pr_err(" %pSb\n", pc1);111			if (pc2)112				pr_err(" %pSb\n", pc2);113			break;114		}115		if ((nr_entries == 3) && (magic == KMSAN_CHAIN_MAGIC_ORIGIN)) {116			/*117			 * Origin chains deeper than KMSAN_MAX_ORIGIN_DEPTH are118			 * not stored, so the output may be incomplete.119			 */120			if (depth == KMSAN_MAX_ORIGIN_DEPTH)121				pr_err("<Zero or more stacks not recorded to save memory>\n\n");122			head = entries[1];123			origin = entries[2];124			pr_err("Uninit was stored to memory at:\n");125			chained_nr_entries =126				stack_depot_fetch(head, &chained_entries);127			kmsan_internal_unpoison_memory(128				chained_entries,129				chained_nr_entries * sizeof(*chained_entries),130				/*checked*/ false);131			skipnr = get_stack_skipnr(chained_entries,132						  chained_nr_entries);133			stack_trace_print(chained_entries + skipnr,134					  chained_nr_entries - skipnr, 0);135			pr_err("\n");136			continue;137		}138		pr_err("Uninit was created at:\n");139		if (nr_entries) {140			skipnr = get_stack_skipnr(entries, nr_entries);141			stack_trace_print(entries + skipnr, nr_entries - skipnr,142					  0);143		} else {144			pr_err("(stack is not available)\n");145		}146		break;147	}148}149 150void kmsan_report(depot_stack_handle_t origin, void *address, int size,151		  int off_first, int off_last, const void __user *user_addr,152		  enum kmsan_bug_reason reason)153{154	unsigned long stack_entries[KMSAN_STACK_DEPTH];155	int num_stack_entries, skipnr;156	char *bug_type = NULL;157	unsigned long ua_flags;158	bool is_uaf;159 160	if (!kmsan_enabled)161		return;162	if (current->kmsan_ctx.depth)163		return;164	if (!origin)165		return;166 167	kmsan_disable_current();168	ua_flags = user_access_save();169	raw_spin_lock(&kmsan_report_lock);170	pr_err("=====================================================\n");171	is_uaf = kmsan_uaf_from_eb(stack_depot_get_extra_bits(origin));172	switch (reason) {173	case REASON_ANY:174		bug_type = is_uaf ? "use-after-free" : "uninit-value";175		break;176	case REASON_COPY_TO_USER:177		bug_type = is_uaf ? "kernel-infoleak-after-free" :178				    "kernel-infoleak";179		break;180	case REASON_SUBMIT_URB:181		bug_type = is_uaf ? "kernel-usb-infoleak-after-free" :182				    "kernel-usb-infoleak";183		break;184	}185 186	num_stack_entries =187		stack_trace_save(stack_entries, KMSAN_STACK_DEPTH, 1);188	skipnr = get_stack_skipnr(stack_entries, num_stack_entries);189 190	pr_err("BUG: KMSAN: %s in %pSb\n", bug_type,191	       (void *)stack_entries[skipnr]);192	stack_trace_print(stack_entries + skipnr, num_stack_entries - skipnr,193			  0);194	pr_err("\n");195 196	kmsan_print_origin(origin);197 198	if (size) {199		pr_err("\n");200		if (off_first == off_last)201			pr_err("Byte %d of %d is uninitialized\n", off_first,202			       size);203		else204			pr_err("Bytes %d-%d of %d are uninitialized\n",205			       off_first, off_last, size);206	}207	if (address)208		pr_err("Memory access of size %d starts at %px\n", size,209		       address);210	if (user_addr && reason == REASON_COPY_TO_USER)211		pr_err("Data copied to user address %px\n", user_addr);212	pr_err("\n");213	dump_stack_print_info(KERN_ERR);214	pr_err("=====================================================\n");215	add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);216	raw_spin_unlock(&kmsan_report_lock);217	if (panic_on_kmsan)218		panic("kmsan.panic set ...\n");219	user_access_restore(ua_flags);220	kmsan_enable_current();221}222