Commit | Line | Data |
---|---|---|
e886bf9d | 1 | // SPDX-License-Identifier: GPL-2.0 |
0b24becc | 2 | /* |
59fd51b2 | 3 | * This file contains common KASAN error reporting code. |
0b24becc AR |
4 | * |
5 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | |
2baf9e89 | 6 | * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com> |
0b24becc | 7 | * |
5d0926ef | 8 | * Some code borrowed from https://github.com/xairy/kasan-prototype by |
5f21f3a8 | 9 | * Andrey Konovalov <andreyknvl@gmail.com> |
0b24becc AR |
10 | */ |
11 | ||
b0845ce5 | 12 | #include <linux/bitops.h> |
4f40c6e5 | 13 | #include <linux/ftrace.h> |
b0845ce5 | 14 | #include <linux/init.h> |
0b24becc AR |
15 | #include <linux/kernel.h> |
16 | #include <linux/mm.h> | |
17 | #include <linux/printk.h> | |
18 | #include <linux/sched.h> | |
19 | #include <linux/slab.h> | |
cd11016e | 20 | #include <linux/stackdepot.h> |
0b24becc AR |
21 | #include <linux/stacktrace.h> |
22 | #include <linux/string.h> | |
23 | #include <linux/types.h> | |
24 | #include <linux/kasan.h> | |
527f215b | 25 | #include <linux/module.h> |
e8969219 | 26 | #include <linux/sched/task_stack.h> |
4fba3758 | 27 | #include <linux/uaccess.h> |
0b24becc | 28 | |
bebf56a1 AR |
29 | #include <asm/sections.h> |
30 | ||
83c4e7a0 PA |
31 | #include <kunit/test.h> |
32 | ||
0b24becc | 33 | #include "kasan.h" |
0316bec2 | 34 | #include "../slab.h" |
0b24becc AR |
35 | |
36 | /* Shadow layout customization. */ | |
37 | #define SHADOW_BYTES_PER_BLOCK 1 | |
38 | #define SHADOW_BLOCKS_PER_ROW 16 | |
39 | #define SHADOW_BYTES_PER_ROW (SHADOW_BLOCKS_PER_ROW * SHADOW_BYTES_PER_BLOCK) | |
40 | #define SHADOW_ROWS_AROUND_ADDR 2 | |
41 | ||
11cd3cd6 | 42 | static unsigned long kasan_flags; |
0b24becc | 43 | |
11cd3cd6 AK |
44 | #define KASAN_BIT_REPORTED 0 |
45 | #define KASAN_BIT_MULTI_SHOT 1 | |
5e82cd12 | 46 | |
11cd3cd6 | 47 | bool kasan_save_enable_multi_shot(void) |
0b24becc | 48 | { |
11cd3cd6 | 49 | return test_and_set_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags); |
5e82cd12 | 50 | } |
11cd3cd6 | 51 | EXPORT_SYMBOL_GPL(kasan_save_enable_multi_shot); |
5e82cd12 | 52 | |
11cd3cd6 | 53 | void kasan_restore_multi_shot(bool enabled) |
5e82cd12 | 54 | { |
11cd3cd6 AK |
55 | if (!enabled) |
56 | clear_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags); | |
5e82cd12 | 57 | } |
11cd3cd6 | 58 | EXPORT_SYMBOL_GPL(kasan_restore_multi_shot); |
5e82cd12 | 59 | |
11cd3cd6 | 60 | static int __init kasan_set_multi_shot(char *str) |
7d418f7b | 61 | { |
11cd3cd6 AK |
62 | set_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags); |
63 | return 1; | |
7d418f7b | 64 | } |
11cd3cd6 | 65 | __setup("kasan_multi_shot", kasan_set_multi_shot); |
7d418f7b | 66 | |
121e8f81 | 67 | static void print_error_description(struct kasan_access_info *info) |
5e82cd12 | 68 | { |
7f0a84c2 | 69 | pr_err("BUG: KASAN: %s in %pS\n", |
121e8f81 | 70 | get_bug_type(info), (void *)info->ip); |
6424f6bb | 71 | pr_err("%s of size %zu at addr %px by task %s/%d\n", |
7d418f7b | 72 | info->is_write ? "Write" : "Read", info->access_size, |
7f0a84c2 | 73 | info->access_addr, current->comm, task_pid_nr(current)); |
0b24becc AR |
74 | } |
75 | ||
7e088978 AR |
76 | static DEFINE_SPINLOCK(report_lock); |
77 | ||
11cd3cd6 | 78 | static void start_report(unsigned long *flags) |
7e088978 AR |
79 | { |
80 | /* | |
81 | * Make sure we don't end up in loop. | |
82 | */ | |
83 | kasan_disable_current(); | |
84 | spin_lock_irqsave(&report_lock, *flags); | |
85 | pr_err("==================================================================\n"); | |
86 | } | |
87 | ||
11cd3cd6 | 88 | static void end_report(unsigned long *flags) |
7e088978 AR |
89 | { |
90 | pr_err("==================================================================\n"); | |
91 | add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE); | |
92 | spin_unlock_irqrestore(&report_lock, *flags); | |
be4f1ae9 | 93 | if (panic_on_warn && !test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags)) { |
1d2252fa KC |
94 | /* |
95 | * This thread may hit another WARN() in the panic path. | |
96 | * Resetting this prevents additional WARN() from panicking the | |
97 | * system on this thread. Other threads are blocked by the | |
98 | * panic_mutex in panic(). | |
99 | */ | |
100 | panic_on_warn = 0; | |
5c5c1f36 | 101 | panic("panic_on_warn set ...\n"); |
1d2252fa | 102 | } |
7e088978 AR |
103 | kasan_enable_current(); |
104 | } | |
105 | ||
26e760c9 WW |
106 | static void print_stack(depot_stack_handle_t stack) |
107 | { | |
108 | unsigned long *entries; | |
109 | unsigned int nr_entries; | |
110 | ||
111 | nr_entries = stack_depot_fetch(stack, &entries); | |
112 | stack_trace_print(entries, nr_entries, 0); | |
113 | } | |
114 | ||
b6b72f49 | 115 | static void print_track(struct kasan_track *track, const char *prefix) |
7ed2f9e6 | 116 | { |
b6b72f49 | 117 | pr_err("%s by task %u:\n", prefix, track->pid); |
cd11016e | 118 | if (track->stack) { |
26e760c9 | 119 | print_stack(track->stack); |
cd11016e AP |
120 | } else { |
121 | pr_err("(stack is not available)\n"); | |
122 | } | |
7ed2f9e6 AP |
123 | } |
124 | ||
ae8f06b3 | 125 | struct page *kasan_addr_to_page(const void *addr) |
db429f16 AK |
126 | { |
127 | if ((addr >= (void *)PAGE_OFFSET) && | |
128 | (addr < high_memory)) | |
129 | return virt_to_head_page(addr); | |
130 | return NULL; | |
131 | } | |
132 | ||
0c06f1f8 AK |
133 | static void describe_object_addr(struct kmem_cache *cache, void *object, |
134 | const void *addr) | |
7ed2f9e6 | 135 | { |
0c06f1f8 AK |
136 | unsigned long access_addr = (unsigned long)addr; |
137 | unsigned long object_addr = (unsigned long)object; | |
138 | const char *rel_type; | |
139 | int rel_bytes; | |
7ed2f9e6 | 140 | |
6424f6bb | 141 | pr_err("The buggy address belongs to the object at %px\n" |
0c06f1f8 AK |
142 | " which belongs to the cache %s of size %d\n", |
143 | object, cache->name, cache->object_size); | |
47b5c2a0 | 144 | |
0c06f1f8 | 145 | if (!addr) |
7ed2f9e6 | 146 | return; |
b3cbd9bf | 147 | |
0c06f1f8 AK |
148 | if (access_addr < object_addr) { |
149 | rel_type = "to the left"; | |
150 | rel_bytes = object_addr - access_addr; | |
151 | } else if (access_addr >= object_addr + cache->object_size) { | |
152 | rel_type = "to the right"; | |
153 | rel_bytes = access_addr - (object_addr + cache->object_size); | |
154 | } else { | |
155 | rel_type = "inside"; | |
156 | rel_bytes = access_addr - object_addr; | |
157 | } | |
158 | ||
159 | pr_err("The buggy address is located %d bytes %s of\n" | |
6424f6bb | 160 | " %d-byte region [%px, %px)\n", |
0c06f1f8 AK |
161 | rel_bytes, rel_type, cache->object_size, (void *)object_addr, |
162 | (void *)(object_addr + cache->object_size)); | |
163 | } | |
164 | ||
165 | static void describe_object(struct kmem_cache *cache, void *object, | |
ae8f06b3 | 166 | const void *addr, u8 tag) |
0c06f1f8 AK |
167 | { |
168 | struct kasan_alloc_meta *alloc_info = get_alloc_info(cache, object); | |
169 | ||
170 | if (cache->flags & SLAB_KASAN) { | |
ae8f06b3 WW |
171 | struct kasan_track *free_track; |
172 | ||
0c06f1f8 | 173 | print_track(&alloc_info->alloc_track, "Allocated"); |
b1938599 | 174 | pr_err("\n"); |
ae8f06b3 | 175 | free_track = kasan_get_free_track(cache, object, tag); |
e4b7818b WW |
176 | if (free_track) { |
177 | print_track(free_track, "Freed"); | |
178 | pr_err("\n"); | |
179 | } | |
26e760c9 WW |
180 | |
181 | #ifdef CONFIG_KASAN_GENERIC | |
182 | if (alloc_info->aux_stack[0]) { | |
ef133461 | 183 | pr_err("Last potentially related work creation:\n"); |
26e760c9 WW |
184 | print_stack(alloc_info->aux_stack[0]); |
185 | pr_err("\n"); | |
186 | } | |
187 | if (alloc_info->aux_stack[1]) { | |
ef133461 | 188 | pr_err("Second to last potentially related work creation:\n"); |
26e760c9 WW |
189 | print_stack(alloc_info->aux_stack[1]); |
190 | pr_err("\n"); | |
191 | } | |
192 | #endif | |
0c06f1f8 AK |
193 | } |
194 | ||
195 | describe_object_addr(cache, object, addr); | |
7ed2f9e6 | 196 | } |
7ed2f9e6 | 197 | |
11cd3cd6 AK |
198 | static inline bool kernel_or_module_addr(const void *addr) |
199 | { | |
200 | if (addr >= (void *)_stext && addr < (void *)_end) | |
201 | return true; | |
202 | if (is_module_address((unsigned long)addr)) | |
203 | return true; | |
204 | return false; | |
205 | } | |
206 | ||
207 | static inline bool init_task_stack_addr(const void *addr) | |
208 | { | |
209 | return addr >= (void *)&init_thread_union.stack && | |
210 | (addr <= (void *)&init_thread_union.stack + | |
211 | sizeof(init_thread_union.stack)); | |
212 | } | |
213 | ||
ae8f06b3 | 214 | static void print_address_description(void *addr, u8 tag) |
0b24becc | 215 | { |
ae8f06b3 | 216 | struct page *page = kasan_addr_to_page(addr); |
b8c73fc2 | 217 | |
db429f16 | 218 | dump_stack(); |
b1938599 | 219 | pr_err("\n"); |
db429f16 AK |
220 | |
221 | if (page && PageSlab(page)) { | |
222 | struct kmem_cache *cache = page->slab_cache; | |
0c06f1f8 | 223 | void *object = nearest_obj(cache, page, addr); |
db429f16 | 224 | |
ae8f06b3 | 225 | describe_object(cache, object, addr, tag); |
b8c73fc2 AR |
226 | } |
227 | ||
430a05f9 AK |
228 | if (kernel_or_module_addr(addr) && !init_task_stack_addr(addr)) { |
229 | pr_err("The buggy address belongs to the variable:\n"); | |
230 | pr_err(" %pS\n", addr); | |
231 | } | |
232 | ||
233 | if (page) { | |
234 | pr_err("The buggy address belongs to the page:\n"); | |
235 | dump_page(page, "kasan: bad access detected"); | |
bebf56a1 | 236 | } |
e8969219 ME |
237 | |
238 | print_address_stack_frame(addr); | |
0b24becc AR |
239 | } |
240 | ||
241 | static bool row_is_guilty(const void *row, const void *guilty) | |
242 | { | |
243 | return (row <= guilty) && (guilty < row + SHADOW_BYTES_PER_ROW); | |
244 | } | |
245 | ||
246 | static int shadow_pointer_offset(const void *row, const void *shadow) | |
247 | { | |
248 | /* The length of ">ff00ff00ff00ff00: " is | |
249 | * 3 + (BITS_PER_LONG/8)*2 chars. | |
250 | */ | |
251 | return 3 + (BITS_PER_LONG/8)*2 + (shadow - row)*2 + | |
252 | (shadow - row) / SHADOW_BYTES_PER_BLOCK + 1; | |
253 | } | |
254 | ||
255 | static void print_shadow_for_address(const void *addr) | |
256 | { | |
257 | int i; | |
258 | const void *shadow = kasan_mem_to_shadow(addr); | |
259 | const void *shadow_row; | |
260 | ||
261 | shadow_row = (void *)round_down((unsigned long)shadow, | |
262 | SHADOW_BYTES_PER_ROW) | |
263 | - SHADOW_ROWS_AROUND_ADDR * SHADOW_BYTES_PER_ROW; | |
264 | ||
265 | pr_err("Memory state around the buggy address:\n"); | |
266 | ||
267 | for (i = -SHADOW_ROWS_AROUND_ADDR; i <= SHADOW_ROWS_AROUND_ADDR; i++) { | |
268 | const void *kaddr = kasan_shadow_to_mem(shadow_row); | |
269 | char buffer[4 + (BITS_PER_LONG/8)*2]; | |
f2377d4e | 270 | char shadow_buf[SHADOW_BYTES_PER_ROW]; |
0b24becc AR |
271 | |
272 | snprintf(buffer, sizeof(buffer), | |
6424f6bb | 273 | (i == 0) ? ">%px: " : " %px: ", kaddr); |
f2377d4e AK |
274 | /* |
275 | * We should not pass a shadow pointer to generic | |
276 | * function, because generic functions may try to | |
277 | * access kasan mapping for the passed address. | |
278 | */ | |
f2377d4e | 279 | memcpy(shadow_buf, shadow_row, SHADOW_BYTES_PER_ROW); |
0b24becc AR |
280 | print_hex_dump(KERN_ERR, buffer, |
281 | DUMP_PREFIX_NONE, SHADOW_BYTES_PER_ROW, 1, | |
f2377d4e | 282 | shadow_buf, SHADOW_BYTES_PER_ROW, 0); |
0b24becc AR |
283 | |
284 | if (row_is_guilty(shadow_row, shadow)) | |
285 | pr_err("%*c\n", | |
286 | shadow_pointer_offset(shadow_row, shadow), | |
287 | '^'); | |
288 | ||
289 | shadow_row += SHADOW_BYTES_PER_ROW; | |
290 | } | |
291 | } | |
292 | ||
4fba3758 | 293 | static bool report_enabled(void) |
11cd3cd6 | 294 | { |
d73b4936 | 295 | #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) |
11cd3cd6 AK |
296 | if (current->kasan_depth) |
297 | return false; | |
d73b4936 | 298 | #endif |
11cd3cd6 AK |
299 | if (test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags)) |
300 | return true; | |
301 | return !test_and_set_bit(KASAN_BIT_REPORTED, &kasan_flags); | |
302 | } | |
303 | ||
83c4e7a0 PA |
304 | #if IS_ENABLED(CONFIG_KUNIT) |
305 | static void kasan_update_kunit_status(struct kunit *cur_test) | |
306 | { | |
307 | struct kunit_resource *resource; | |
308 | struct kunit_kasan_expectation *kasan_data; | |
309 | ||
310 | resource = kunit_find_named_resource(cur_test, "kasan_data"); | |
311 | ||
312 | if (!resource) { | |
313 | kunit_set_failure(cur_test); | |
314 | return; | |
315 | } | |
316 | ||
317 | kasan_data = (struct kunit_kasan_expectation *)resource->data; | |
318 | kasan_data->report_found = true; | |
319 | kunit_put_resource(resource); | |
320 | } | |
321 | #endif /* IS_ENABLED(CONFIG_KUNIT) */ | |
322 | ||
ee3ce779 | 323 | void kasan_report_invalid_free(void *object, unsigned long ip) |
5ab6d91a AK |
324 | { |
325 | unsigned long flags; | |
ae8f06b3 | 326 | u8 tag = get_tag(object); |
5ab6d91a | 327 | |
ae8f06b3 | 328 | object = reset_tag(object); |
83c4e7a0 PA |
329 | |
330 | #if IS_ENABLED(CONFIG_KUNIT) | |
331 | if (current->kunit_test) | |
332 | kasan_update_kunit_status(current->kunit_test); | |
333 | #endif /* IS_ENABLED(CONFIG_KUNIT) */ | |
334 | ||
11cd3cd6 | 335 | start_report(&flags); |
ee3ce779 | 336 | pr_err("BUG: KASAN: double-free or invalid-free in %pS\n", (void *)ip); |
ae8f06b3 | 337 | print_tags(tag, object); |
b1938599 | 338 | pr_err("\n"); |
ae8f06b3 | 339 | print_address_description(object, tag); |
b1938599 | 340 | pr_err("\n"); |
5ab6d91a | 341 | print_shadow_for_address(object); |
11cd3cd6 | 342 | end_report(&flags); |
5ab6d91a AK |
343 | } |
344 | ||
4fba3758 AK |
345 | static void __kasan_report(unsigned long addr, size_t size, bool is_write, |
346 | unsigned long ip) | |
0b24becc AR |
347 | { |
348 | struct kasan_access_info info; | |
121e8f81 AK |
349 | void *tagged_addr; |
350 | void *untagged_addr; | |
351 | unsigned long flags; | |
0b24becc | 352 | |
83c4e7a0 PA |
353 | #if IS_ENABLED(CONFIG_KUNIT) |
354 | if (current->kunit_test) | |
355 | kasan_update_kunit_status(current->kunit_test); | |
356 | #endif /* IS_ENABLED(CONFIG_KUNIT) */ | |
357 | ||
4f40c6e5 PZ |
358 | disable_trace_on_warning(); |
359 | ||
121e8f81 AK |
360 | tagged_addr = (void *)addr; |
361 | untagged_addr = reset_tag(tagged_addr); | |
362 | ||
363 | info.access_addr = tagged_addr; | |
364 | if (addr_has_shadow(untagged_addr)) | |
365 | info.first_bad_addr = find_first_bad_addr(tagged_addr, size); | |
366 | else | |
367 | info.first_bad_addr = untagged_addr; | |
0b24becc AR |
368 | info.access_size = size; |
369 | info.is_write = is_write; | |
370 | info.ip = ip; | |
e9121076 | 371 | |
121e8f81 AK |
372 | start_report(&flags); |
373 | ||
374 | print_error_description(&info); | |
375 | if (addr_has_shadow(untagged_addr)) | |
376 | print_tags(get_tag(tagged_addr), info.first_bad_addr); | |
377 | pr_err("\n"); | |
378 | ||
379 | if (addr_has_shadow(untagged_addr)) { | |
ae8f06b3 | 380 | print_address_description(untagged_addr, get_tag(tagged_addr)); |
121e8f81 AK |
381 | pr_err("\n"); |
382 | print_shadow_for_address(info.first_bad_addr); | |
383 | } else { | |
384 | dump_stack(); | |
385 | } | |
386 | ||
387 | end_report(&flags); | |
0b24becc | 388 | } |
2f004eea | 389 | |
4fba3758 AK |
390 | bool kasan_report(unsigned long addr, size_t size, bool is_write, |
391 | unsigned long ip) | |
392 | { | |
393 | unsigned long flags = user_access_save(); | |
394 | bool ret = false; | |
395 | ||
396 | if (likely(report_enabled())) { | |
397 | __kasan_report(addr, size, is_write, ip); | |
398 | ret = true; | |
399 | } | |
400 | ||
401 | user_access_restore(flags); | |
402 | ||
403 | return ret; | |
404 | } | |
405 | ||
2f004eea JH |
406 | #ifdef CONFIG_KASAN_INLINE |
407 | /* | |
408 | * With CONFIG_KASAN_INLINE, accesses to bogus pointers (outside the high | |
409 | * canonical half of the address space) cause out-of-bounds shadow memory reads | |
410 | * before the actual access. For addresses in the low canonical half of the | |
411 | * address space, as well as most non-canonical addresses, that out-of-bounds | |
412 | * shadow memory access lands in the non-canonical part of the address space. | |
413 | * Help the user figure out what the original bogus pointer was. | |
414 | */ | |
415 | void kasan_non_canonical_hook(unsigned long addr) | |
416 | { | |
417 | unsigned long orig_addr; | |
418 | const char *bug_type; | |
419 | ||
420 | if (addr < KASAN_SHADOW_OFFSET) | |
421 | return; | |
422 | ||
423 | orig_addr = (addr - KASAN_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT; | |
424 | /* | |
425 | * For faults near the shadow address for NULL, we can be fairly certain | |
426 | * that this is a KASAN shadow memory access. | |
427 | * For faults that correspond to shadow for low canonical addresses, we | |
428 | * can still be pretty sure - that shadow region is a fairly narrow | |
429 | * chunk of the non-canonical address space. | |
430 | * But faults that look like shadow for non-canonical addresses are a | |
431 | * really large chunk of the address space. In that case, we still | |
432 | * print the decoded address, but make it clear that this is not | |
433 | * necessarily what's actually going on. | |
434 | */ | |
435 | if (orig_addr < PAGE_SIZE) | |
436 | bug_type = "null-ptr-deref"; | |
437 | else if (orig_addr < TASK_SIZE) | |
438 | bug_type = "probably user-memory-access"; | |
439 | else | |
440 | bug_type = "maybe wild-memory-access"; | |
441 | pr_alert("KASAN: %s in range [0x%016lx-0x%016lx]\n", bug_type, | |
1f600626 | 442 | orig_addr, orig_addr + KASAN_GRANULE_SIZE - 1); |
2f004eea JH |
443 | } |
444 | #endif |