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