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 | ||
c8c7016f | 12 | #include <kunit/test.h> |
b0845ce5 | 13 | #include <linux/bitops.h> |
4f40c6e5 | 14 | #include <linux/ftrace.h> |
b0845ce5 | 15 | #include <linux/init.h> |
0b24becc | 16 | #include <linux/kernel.h> |
c32caa26 | 17 | #include <linux/lockdep.h> |
0b24becc AR |
18 | #include <linux/mm.h> |
19 | #include <linux/printk.h> | |
20 | #include <linux/sched.h> | |
21 | #include <linux/slab.h> | |
cd11016e | 22 | #include <linux/stackdepot.h> |
0b24becc AR |
23 | #include <linux/stacktrace.h> |
24 | #include <linux/string.h> | |
25 | #include <linux/types.h> | |
26 | #include <linux/kasan.h> | |
527f215b | 27 | #include <linux/module.h> |
e8969219 | 28 | #include <linux/sched/task_stack.h> |
4fba3758 | 29 | #include <linux/uaccess.h> |
d3a61f74 | 30 | #include <trace/events/error_report.h> |
0b24becc | 31 | |
bebf56a1 AR |
32 | #include <asm/sections.h> |
33 | ||
0b24becc | 34 | #include "kasan.h" |
0316bec2 | 35 | #include "../slab.h" |
0b24becc | 36 | |
11cd3cd6 | 37 | static unsigned long kasan_flags; |
0b24becc | 38 | |
11cd3cd6 AK |
39 | #define KASAN_BIT_REPORTED 0 |
40 | #define KASAN_BIT_MULTI_SHOT 1 | |
5e82cd12 | 41 | |
c9d1af2b WL |
42 | enum kasan_arg_fault { |
43 | KASAN_ARG_FAULT_DEFAULT, | |
44 | KASAN_ARG_FAULT_REPORT, | |
45 | KASAN_ARG_FAULT_PANIC, | |
46 | }; | |
47 | ||
48 | static enum kasan_arg_fault kasan_arg_fault __ro_after_init = KASAN_ARG_FAULT_DEFAULT; | |
49 | ||
50 | /* kasan.fault=report/panic */ | |
51 | static int __init early_kasan_fault(char *arg) | |
52 | { | |
53 | if (!arg) | |
54 | return -EINVAL; | |
55 | ||
56 | if (!strcmp(arg, "report")) | |
57 | kasan_arg_fault = KASAN_ARG_FAULT_REPORT; | |
58 | else if (!strcmp(arg, "panic")) | |
59 | kasan_arg_fault = KASAN_ARG_FAULT_PANIC; | |
60 | else | |
61 | return -EINVAL; | |
62 | ||
63 | return 0; | |
64 | } | |
65 | early_param("kasan.fault", early_kasan_fault); | |
66 | ||
11cd3cd6 | 67 | static int __init kasan_set_multi_shot(char *str) |
7d418f7b | 68 | { |
11cd3cd6 AK |
69 | set_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags); |
70 | return 1; | |
7d418f7b | 71 | } |
11cd3cd6 | 72 | __setup("kasan_multi_shot", kasan_set_multi_shot); |
7d418f7b | 73 | |
865bfa28 AK |
74 | /* |
75 | * Used to suppress reports within kasan_disable/enable_current() critical | |
76 | * sections, which are used for marking accesses to slab metadata. | |
77 | */ | |
78 | static bool report_suppressed(void) | |
5e82cd12 | 79 | { |
865bfa28 AK |
80 | #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) |
81 | if (current->kasan_depth) | |
82 | return true; | |
83 | #endif | |
84 | return false; | |
85 | } | |
31c65110 | 86 | |
865bfa28 AK |
87 | /* |
88 | * Used to avoid reporting more than one KASAN bug unless kasan_multi_shot | |
89 | * is enabled. Note that KASAN tests effectively enable kasan_multi_shot | |
90 | * for their duration. | |
91 | */ | |
92 | static bool report_enabled(void) | |
93 | { | |
94 | if (test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags)) | |
95 | return true; | |
96 | return !test_and_set_bit(KASAN_BIT_REPORTED, &kasan_flags); | |
0b24becc AR |
97 | } |
98 | ||
80207910 AK |
99 | #if IS_ENABLED(CONFIG_KASAN_KUNIT_TEST) || IS_ENABLED(CONFIG_KASAN_MODULE_TEST) |
100 | ||
101 | bool kasan_save_enable_multi_shot(void) | |
102 | { | |
103 | return test_and_set_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags); | |
104 | } | |
105 | EXPORT_SYMBOL_GPL(kasan_save_enable_multi_shot); | |
106 | ||
107 | void kasan_restore_multi_shot(bool enabled) | |
108 | { | |
109 | if (!enabled) | |
110 | clear_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags); | |
111 | } | |
112 | EXPORT_SYMBOL_GPL(kasan_restore_multi_shot); | |
113 | ||
114 | #endif | |
115 | ||
c8c7016f AK |
116 | #if IS_ENABLED(CONFIG_KASAN_KUNIT_TEST) |
117 | ||
118 | /* | |
119 | * Whether the KASAN KUnit test suite is currently being executed. | |
120 | * Updated in kasan_test.c. | |
121 | */ | |
122 | bool kasan_kunit_executing; | |
123 | ||
124 | void kasan_kunit_test_suite_start(void) | |
125 | { | |
126 | WRITE_ONCE(kasan_kunit_executing, true); | |
127 | } | |
128 | EXPORT_SYMBOL_GPL(kasan_kunit_test_suite_start); | |
129 | ||
130 | void kasan_kunit_test_suite_end(void) | |
131 | { | |
132 | WRITE_ONCE(kasan_kunit_executing, false); | |
133 | } | |
134 | EXPORT_SYMBOL_GPL(kasan_kunit_test_suite_end); | |
135 | ||
136 | static bool kasan_kunit_test_suite_executing(void) | |
137 | { | |
138 | return READ_ONCE(kasan_kunit_executing); | |
139 | } | |
140 | ||
141 | #else /* CONFIG_KASAN_KUNIT_TEST */ | |
142 | ||
143 | static inline bool kasan_kunit_test_suite_executing(void) { return false; } | |
144 | ||
145 | #endif /* CONFIG_KASAN_KUNIT_TEST */ | |
146 | ||
147 | #if IS_ENABLED(CONFIG_KUNIT) | |
148 | ||
149 | static void fail_non_kasan_kunit_test(void) | |
150 | { | |
151 | struct kunit *test; | |
152 | ||
153 | if (kasan_kunit_test_suite_executing()) | |
154 | return; | |
155 | ||
156 | test = current->kunit_test; | |
157 | if (test) | |
158 | kunit_set_failure(test); | |
159 | } | |
160 | ||
161 | #else /* CONFIG_KUNIT */ | |
162 | ||
163 | static inline void fail_non_kasan_kunit_test(void) { } | |
164 | ||
165 | #endif /* CONFIG_KUNIT */ | |
166 | ||
7e088978 AR |
167 | static DEFINE_SPINLOCK(report_lock); |
168 | ||
a260d281 | 169 | static void start_report(unsigned long *flags, bool sync) |
7e088978 | 170 | { |
c8c7016f | 171 | fail_non_kasan_kunit_test(); |
0a6e8a07 AK |
172 | /* Respect the /proc/sys/kernel/traceoff_on_warning interface. */ |
173 | disable_trace_on_warning(); | |
c32caa26 AK |
174 | /* Do not allow LOCKDEP mangling KASAN reports. */ |
175 | lockdep_off(); | |
a260d281 | 176 | /* Make sure we don't end up in loop. */ |
7e088978 AR |
177 | kasan_disable_current(); |
178 | spin_lock_irqsave(&report_lock, *flags); | |
179 | pr_err("==================================================================\n"); | |
180 | } | |
181 | ||
9d7b7dd9 | 182 | static void end_report(unsigned long *flags, void *addr) |
7e088978 | 183 | { |
476b1dc2 | 184 | if (addr) |
9d7b7dd9 AK |
185 | trace_error_report_end(ERROR_DETECTOR_KASAN, |
186 | (unsigned long)addr); | |
7e088978 | 187 | pr_err("==================================================================\n"); |
7e088978 | 188 | spin_unlock_irqrestore(&report_lock, *flags); |
79cc1ba7 KC |
189 | if (!test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags)) |
190 | check_panic_on_warn("KASAN"); | |
c9d1af2b | 191 | if (kasan_arg_fault == KASAN_ARG_FAULT_PANIC) |
8028caac | 192 | panic("kasan.fault=panic set ...\n"); |
c32caa26 AK |
193 | add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE); |
194 | lockdep_on(); | |
7e088978 AR |
195 | kasan_enable_current(); |
196 | } | |
197 | ||
865bfa28 AK |
198 | static void print_error_description(struct kasan_report_info *info) |
199 | { | |
dcc57966 | 200 | pr_err("BUG: KASAN: %s in %pS\n", info->bug_type, (void *)info->ip); |
3de0de75 | 201 | |
dcc57966 AK |
202 | if (info->type != KASAN_REPORT_ACCESS) { |
203 | pr_err("Free of addr %px by task %s/%d\n", | |
204 | info->access_addr, current->comm, task_pid_nr(current)); | |
865bfa28 AK |
205 | return; |
206 | } | |
207 | ||
865bfa28 AK |
208 | if (info->access_size) |
209 | pr_err("%s of size %zu at addr %px by task %s/%d\n", | |
210 | info->is_write ? "Write" : "Read", info->access_size, | |
211 | info->access_addr, current->comm, task_pid_nr(current)); | |
212 | else | |
213 | pr_err("%s at addr %px by task %s/%d\n", | |
214 | info->is_write ? "Write" : "Read", | |
215 | info->access_addr, current->comm, task_pid_nr(current)); | |
216 | } | |
217 | ||
b6b72f49 | 218 | static void print_track(struct kasan_track *track, const char *prefix) |
7ed2f9e6 | 219 | { |
b6b72f49 | 220 | pr_err("%s by task %u:\n", prefix, track->pid); |
9ef08d26 | 221 | if (track->stack) |
505be481 | 222 | stack_depot_print(track->stack); |
9ef08d26 | 223 | else |
cd11016e | 224 | pr_err("(stack is not available)\n"); |
7ed2f9e6 AP |
225 | } |
226 | ||
559756e8 | 227 | static inline struct page *addr_to_page(const void *addr) |
db429f16 | 228 | { |
2c9fb1fd | 229 | if (virt_addr_valid(addr)) |
db429f16 AK |
230 | return virt_to_head_page(addr); |
231 | return NULL; | |
232 | } | |
233 | ||
92a38eac AK |
234 | static void describe_object_addr(const void *addr, struct kmem_cache *cache, |
235 | void *object) | |
7ed2f9e6 | 236 | { |
0c06f1f8 AK |
237 | unsigned long access_addr = (unsigned long)addr; |
238 | unsigned long object_addr = (unsigned long)object; | |
239 | const char *rel_type; | |
240 | int rel_bytes; | |
7ed2f9e6 | 241 | |
6424f6bb | 242 | pr_err("The buggy address belongs to the object at %px\n" |
0c06f1f8 AK |
243 | " which belongs to the cache %s of size %d\n", |
244 | object, cache->name, cache->object_size); | |
47b5c2a0 | 245 | |
0c06f1f8 AK |
246 | if (access_addr < object_addr) { |
247 | rel_type = "to the left"; | |
248 | rel_bytes = object_addr - access_addr; | |
249 | } else if (access_addr >= object_addr + cache->object_size) { | |
250 | rel_type = "to the right"; | |
251 | rel_bytes = access_addr - (object_addr + cache->object_size); | |
252 | } else { | |
253 | rel_type = "inside"; | |
254 | rel_bytes = access_addr - object_addr; | |
255 | } | |
256 | ||
257 | pr_err("The buggy address is located %d bytes %s of\n" | |
6424f6bb | 258 | " %d-byte region [%px, %px)\n", |
0c06f1f8 AK |
259 | rel_bytes, rel_type, cache->object_size, (void *)object_addr, |
260 | (void *)(object_addr + cache->object_size)); | |
261 | } | |
262 | ||
59e6e098 | 263 | static void describe_object_stacks(struct kasan_report_info *info) |
0c06f1f8 | 264 | { |
59e6e098 AK |
265 | if (info->alloc_track.stack) { |
266 | print_track(&info->alloc_track, "Allocated"); | |
b1938599 | 267 | pr_err("\n"); |
97593cad AK |
268 | } |
269 | ||
59e6e098 AK |
270 | if (info->free_track.stack) { |
271 | print_track(&info->free_track, "Freed"); | |
97593cad AK |
272 | pr_err("\n"); |
273 | } | |
26e760c9 | 274 | |
92a38eac | 275 | kasan_print_aux_stacks(info->cache, info->object); |
8028caac | 276 | } |
0c06f1f8 | 277 | |
59e6e098 | 278 | static void describe_object(const void *addr, struct kasan_report_info *info) |
8028caac AK |
279 | { |
280 | if (kasan_stack_collection_enabled()) | |
59e6e098 | 281 | describe_object_stacks(info); |
92a38eac | 282 | describe_object_addr(addr, info->cache, info->object); |
7ed2f9e6 | 283 | } |
7ed2f9e6 | 284 | |
11cd3cd6 AK |
285 | static inline bool kernel_or_module_addr(const void *addr) |
286 | { | |
3298cbe8 | 287 | if (is_kernel((unsigned long)addr)) |
11cd3cd6 AK |
288 | return true; |
289 | if (is_module_address((unsigned long)addr)) | |
290 | return true; | |
291 | return false; | |
292 | } | |
293 | ||
294 | static inline bool init_task_stack_addr(const void *addr) | |
295 | { | |
296 | return addr >= (void *)&init_thread_union.stack && | |
297 | (addr <= (void *)&init_thread_union.stack + | |
298 | sizeof(init_thread_union.stack)); | |
299 | } | |
300 | ||
7fae3dd0 AK |
301 | static void print_address_description(void *addr, u8 tag, |
302 | struct kasan_report_info *info) | |
0b24becc | 303 | { |
559756e8 | 304 | struct page *page = addr_to_page(addr); |
b8c73fc2 | 305 | |
336abff6 | 306 | dump_stack_lvl(KERN_ERR); |
b1938599 | 307 | pr_err("\n"); |
db429f16 | 308 | |
7fae3dd0 | 309 | if (info->cache && info->object) { |
59e6e098 | 310 | describe_object(addr, info); |
038fd2b4 | 311 | pr_err("\n"); |
b8c73fc2 AR |
312 | } |
313 | ||
430a05f9 AK |
314 | if (kernel_or_module_addr(addr) && !init_task_stack_addr(addr)) { |
315 | pr_err("The buggy address belongs to the variable:\n"); | |
316 | pr_err(" %pS\n", addr); | |
038fd2b4 | 317 | pr_err("\n"); |
430a05f9 AK |
318 | } |
319 | ||
0f9b35f3 AK |
320 | if (object_is_on_stack(addr)) { |
321 | /* | |
322 | * Currently, KASAN supports printing frame information only | |
323 | * for accesses to the task's own stack. | |
324 | */ | |
325 | kasan_print_address_stack_frame(addr); | |
326 | pr_err("\n"); | |
327 | } | |
328 | ||
c056a364 AK |
329 | if (is_vmalloc_addr(addr)) { |
330 | struct vm_struct *va = find_vm_area(addr); | |
331 | ||
332 | if (va) { | |
333 | pr_err("The buggy address belongs to the virtual mapping at\n" | |
334 | " [%px, %px) created by:\n" | |
335 | " %pS\n", | |
336 | va->addr, va->addr + va->size, va->caller); | |
038fd2b4 | 337 | pr_err("\n"); |
c056a364 | 338 | |
fbf4df06 | 339 | page = vmalloc_to_page(addr); |
c056a364 AK |
340 | } |
341 | } | |
342 | ||
430a05f9 | 343 | if (page) { |
c056a364 | 344 | pr_err("The buggy address belongs to the physical page:\n"); |
430a05f9 | 345 | dump_page(page, "kasan: bad access detected"); |
038fd2b4 | 346 | pr_err("\n"); |
bebf56a1 | 347 | } |
0b24becc AR |
348 | } |
349 | ||
96e0279d | 350 | static bool meta_row_is_guilty(const void *row, const void *addr) |
0b24becc | 351 | { |
96e0279d | 352 | return (row <= addr) && (addr < row + META_MEM_BYTES_PER_ROW); |
0b24becc AR |
353 | } |
354 | ||
96e0279d | 355 | static int meta_pointer_offset(const void *row, const void *addr) |
0b24becc | 356 | { |
96e0279d AK |
357 | /* |
358 | * Memory state around the buggy address: | |
359 | * ff00ff00ff00ff00: 00 00 00 05 fe fe fe fe fe fe fe fe fe fe fe fe | |
360 | * ... | |
361 | * | |
362 | * The length of ">ff00ff00ff00ff00: " is | |
363 | * 3 + (BITS_PER_LONG / 8) * 2 chars. | |
364 | * The length of each granule metadata is 2 bytes | |
365 | * plus 1 byte for space. | |
0b24becc | 366 | */ |
96e0279d AK |
367 | return 3 + (BITS_PER_LONG / 8) * 2 + |
368 | (addr - row) / KASAN_GRANULE_SIZE * 3 + 1; | |
0b24becc AR |
369 | } |
370 | ||
db3de8f7 | 371 | static void print_memory_metadata(const void *addr) |
0b24becc AR |
372 | { |
373 | int i; | |
96e0279d | 374 | void *row; |
0b24becc | 375 | |
96e0279d AK |
376 | row = (void *)round_down((unsigned long)addr, META_MEM_BYTES_PER_ROW) |
377 | - META_ROWS_AROUND_ADDR * META_MEM_BYTES_PER_ROW; | |
0b24becc AR |
378 | |
379 | pr_err("Memory state around the buggy address:\n"); | |
380 | ||
88b86597 | 381 | for (i = -META_ROWS_AROUND_ADDR; i <= META_ROWS_AROUND_ADDR; i++) { |
96e0279d AK |
382 | char buffer[4 + (BITS_PER_LONG / 8) * 2]; |
383 | char metadata[META_BYTES_PER_ROW]; | |
0b24becc AR |
384 | |
385 | snprintf(buffer, sizeof(buffer), | |
96e0279d AK |
386 | (i == 0) ? ">%px: " : " %px: ", row); |
387 | ||
f2377d4e AK |
388 | /* |
389 | * We should not pass a shadow pointer to generic | |
390 | * function, because generic functions may try to | |
391 | * access kasan mapping for the passed address. | |
392 | */ | |
f00748bf | 393 | kasan_metadata_fetch_row(&metadata[0], row); |
96e0279d | 394 | |
0b24becc | 395 | print_hex_dump(KERN_ERR, buffer, |
88b86597 | 396 | DUMP_PREFIX_NONE, META_BYTES_PER_ROW, 1, |
96e0279d | 397 | metadata, META_BYTES_PER_ROW, 0); |
0b24becc | 398 | |
96e0279d AK |
399 | if (meta_row_is_guilty(row, addr)) |
400 | pr_err("%*c\n", meta_pointer_offset(row, addr), '^'); | |
0b24becc | 401 | |
96e0279d | 402 | row += META_MEM_BYTES_PER_ROW; |
0b24becc AR |
403 | } |
404 | } | |
405 | ||
c965cdd6 | 406 | static void print_report(struct kasan_report_info *info) |
9d7b7dd9 | 407 | { |
a794898a AK |
408 | void *addr = kasan_reset_tag(info->access_addr); |
409 | u8 tag = get_tag(info->access_addr); | |
9d7b7dd9 AK |
410 | |
411 | print_error_description(info); | |
a794898a | 412 | if (addr_has_metadata(addr)) |
9d7b7dd9 AK |
413 | kasan_print_tags(tag, info->first_bad_addr); |
414 | pr_err("\n"); | |
415 | ||
a794898a | 416 | if (addr_has_metadata(addr)) { |
7fae3dd0 | 417 | print_address_description(addr, tag, info); |
9d7b7dd9 AK |
418 | print_memory_metadata(info->first_bad_addr); |
419 | } else { | |
420 | dump_stack_lvl(KERN_ERR); | |
421 | } | |
422 | } | |
423 | ||
015b109f AK |
424 | static void complete_report_info(struct kasan_report_info *info) |
425 | { | |
426 | void *addr = kasan_reset_tag(info->access_addr); | |
7fae3dd0 | 427 | struct slab *slab; |
015b109f AK |
428 | |
429 | if (info->type == KASAN_REPORT_ACCESS) | |
430 | info->first_bad_addr = kasan_find_first_bad_addr( | |
431 | info->access_addr, info->access_size); | |
432 | else | |
433 | info->first_bad_addr = addr; | |
7fae3dd0 AK |
434 | |
435 | slab = kasan_addr_to_slab(addr); | |
436 | if (slab) { | |
437 | info->cache = slab->slab_cache; | |
438 | info->object = nearest_obj(info->cache, slab, addr); | |
439 | } else | |
440 | info->cache = info->object = NULL; | |
59e6e098 | 441 | |
dcc57966 AK |
442 | switch (info->type) { |
443 | case KASAN_REPORT_INVALID_FREE: | |
444 | info->bug_type = "invalid-free"; | |
445 | break; | |
446 | case KASAN_REPORT_DOUBLE_FREE: | |
447 | info->bug_type = "double-free"; | |
448 | break; | |
449 | default: | |
450 | /* bug_type filled in by kasan_complete_mode_report_info. */ | |
451 | break; | |
452 | } | |
453 | ||
59e6e098 AK |
454 | /* Fill in mode-specific report info fields. */ |
455 | kasan_complete_mode_report_info(info); | |
015b109f AK |
456 | } |
457 | ||
3de0de75 | 458 | void kasan_report_invalid_free(void *ptr, unsigned long ip, enum kasan_report_type type) |
31c65110 AK |
459 | { |
460 | unsigned long flags; | |
c965cdd6 | 461 | struct kasan_report_info info; |
31c65110 | 462 | |
c068664c AK |
463 | /* |
464 | * Do not check report_suppressed(), as an invalid-free cannot be | |
465 | * caused by accessing slab metadata and thus should not be | |
466 | * suppressed by kasan_disable/enable_current() critical sections. | |
467 | */ | |
468 | if (unlikely(!report_enabled())) | |
469 | return; | |
470 | ||
31c65110 AK |
471 | start_report(&flags, true); |
472 | ||
59e6e098 | 473 | memset(&info, 0, sizeof(info)); |
3de0de75 | 474 | info.type = type; |
31c65110 | 475 | info.access_addr = ptr; |
31c65110 AK |
476 | info.access_size = 0; |
477 | info.is_write = false; | |
478 | info.ip = ip; | |
479 | ||
015b109f AK |
480 | complete_report_info(&info); |
481 | ||
31c65110 AK |
482 | print_report(&info); |
483 | ||
484 | end_report(&flags, ptr); | |
485 | } | |
486 | ||
795b760f AK |
487 | /* |
488 | * kasan_report() is the only reporting function that uses | |
489 | * user_access_save/restore(): kasan_report_invalid_free() cannot be called | |
490 | * from a UACCESS region, and kasan_report_async() is not used on x86. | |
491 | */ | |
4fba3758 AK |
492 | bool kasan_report(unsigned long addr, size_t size, bool is_write, |
493 | unsigned long ip) | |
494 | { | |
b3bb1d70 | 495 | bool ret = true; |
be8631a1 AK |
496 | void *ptr = (void *)addr; |
497 | unsigned long ua_flags = user_access_save(); | |
498 | unsigned long irq_flags; | |
c965cdd6 | 499 | struct kasan_report_info info; |
4fba3758 | 500 | |
c068664c | 501 | if (unlikely(report_suppressed()) || unlikely(!report_enabled())) { |
b3bb1d70 AK |
502 | ret = false; |
503 | goto out; | |
4fba3758 AK |
504 | } |
505 | ||
be8631a1 AK |
506 | start_report(&irq_flags, true); |
507 | ||
59e6e098 | 508 | memset(&info, 0, sizeof(info)); |
31c65110 | 509 | info.type = KASAN_REPORT_ACCESS; |
be8631a1 | 510 | info.access_addr = ptr; |
be8631a1 AK |
511 | info.access_size = size; |
512 | info.is_write = is_write; | |
513 | info.ip = ip; | |
514 | ||
015b109f AK |
515 | complete_report_info(&info); |
516 | ||
be8631a1 AK |
517 | print_report(&info); |
518 | ||
519 | end_report(&irq_flags, ptr); | |
b3bb1d70 AK |
520 | |
521 | out: | |
522 | user_access_restore(ua_flags); | |
4fba3758 AK |
523 | |
524 | return ret; | |
525 | } | |
526 | ||
bb2f967c AK |
527 | #ifdef CONFIG_KASAN_HW_TAGS |
528 | void kasan_report_async(void) | |
529 | { | |
530 | unsigned long flags; | |
531 | ||
c068664c AK |
532 | /* |
533 | * Do not check report_suppressed(), as kasan_disable/enable_current() | |
534 | * critical sections do not affect Hardware Tag-Based KASAN. | |
535 | */ | |
536 | if (unlikely(!report_enabled())) | |
537 | return; | |
538 | ||
bb2f967c AK |
539 | start_report(&flags, false); |
540 | pr_err("BUG: KASAN: invalid-access\n"); | |
541 | pr_err("Asynchronous fault: no details available\n"); | |
542 | pr_err("\n"); | |
543 | dump_stack_lvl(KERN_ERR); | |
544 | end_report(&flags, NULL); | |
545 | } | |
546 | #endif /* CONFIG_KASAN_HW_TAGS */ | |
547 | ||
2f004eea JH |
548 | #ifdef CONFIG_KASAN_INLINE |
549 | /* | |
550 | * With CONFIG_KASAN_INLINE, accesses to bogus pointers (outside the high | |
551 | * canonical half of the address space) cause out-of-bounds shadow memory reads | |
552 | * before the actual access. For addresses in the low canonical half of the | |
553 | * address space, as well as most non-canonical addresses, that out-of-bounds | |
554 | * shadow memory access lands in the non-canonical part of the address space. | |
555 | * Help the user figure out what the original bogus pointer was. | |
556 | */ | |
557 | void kasan_non_canonical_hook(unsigned long addr) | |
558 | { | |
559 | unsigned long orig_addr; | |
560 | const char *bug_type; | |
561 | ||
562 | if (addr < KASAN_SHADOW_OFFSET) | |
563 | return; | |
564 | ||
565 | orig_addr = (addr - KASAN_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT; | |
566 | /* | |
567 | * For faults near the shadow address for NULL, we can be fairly certain | |
568 | * that this is a KASAN shadow memory access. | |
569 | * For faults that correspond to shadow for low canonical addresses, we | |
570 | * can still be pretty sure - that shadow region is a fairly narrow | |
571 | * chunk of the non-canonical address space. | |
572 | * But faults that look like shadow for non-canonical addresses are a | |
573 | * really large chunk of the address space. In that case, we still | |
574 | * print the decoded address, but make it clear that this is not | |
575 | * necessarily what's actually going on. | |
576 | */ | |
577 | if (orig_addr < PAGE_SIZE) | |
578 | bug_type = "null-ptr-deref"; | |
579 | else if (orig_addr < TASK_SIZE) | |
580 | bug_type = "probably user-memory-access"; | |
581 | else | |
582 | bug_type = "maybe wild-memory-access"; | |
583 | pr_alert("KASAN: %s in range [0x%016lx-0x%016lx]\n", bug_type, | |
1f600626 | 584 | orig_addr, orig_addr + KASAN_GRANULE_SIZE - 1); |
2f004eea JH |
585 | } |
586 | #endif |