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