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