1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * This file contains generic KASAN specific error reporting code. 4 * 5 * Copyright (c) 2014 Samsung Electronics Co., Ltd. 6 * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com> 7 * 8 * Some code borrowed from https://github.com/xairy/kasan-prototype by 9 * Andrey Konovalov <andreyknvl@gmail.com> 10 */ 11 12 #include <linux/bitops.h> 13 #include <linux/ftrace.h> 14 #include <linux/init.h> 15 #include <linux/kernel.h> 16 #include <linux/mm.h> 17 #include <linux/printk.h> 18 #include <linux/sched.h> 19 #include <linux/sched/task_stack.h> 20 #include <linux/slab.h> 21 #include <linux/stackdepot.h> 22 #include <linux/stacktrace.h> 23 #include <linux/string.h> 24 #include <linux/types.h> 25 #include <linux/kasan.h> 26 #include <linux/module.h> 27 28 #include <asm/sections.h> 29 30 #include "kasan.h" 31 #include "../slab.h" 32 33 void *kasan_find_first_bad_addr(void *addr, size_t size) 34 { 35 void *p = addr; 36 37 while (p < addr + size && !(*(u8 *)kasan_mem_to_shadow(p))) 38 p += KASAN_GRANULE_SIZE; 39 return p; 40 } 41 42 static const char *get_shadow_bug_type(struct kasan_access_info *info) 43 { 44 const char *bug_type = "unknown-crash"; 45 u8 *shadow_addr; 46 47 shadow_addr = (u8 *)kasan_mem_to_shadow(info->first_bad_addr); 48 49 /* 50 * If shadow byte value is in [0, KASAN_GRANULE_SIZE) we can look 51 * at the next shadow byte to determine the type of the bad access. 52 */ 53 if (*shadow_addr > 0 && *shadow_addr <= KASAN_GRANULE_SIZE - 1) 54 shadow_addr++; 55 56 switch (*shadow_addr) { 57 case 0 ... KASAN_GRANULE_SIZE - 1: 58 /* 59 * In theory it's still possible to see these shadow values 60 * due to a data race in the kernel code. 61 */ 62 bug_type = "out-of-bounds"; 63 break; 64 case KASAN_PAGE_REDZONE: 65 case KASAN_KMALLOC_REDZONE: 66 bug_type = "slab-out-of-bounds"; 67 break; 68 case KASAN_GLOBAL_REDZONE: 69 bug_type = "global-out-of-bounds"; 70 break; 71 case KASAN_STACK_LEFT: 72 case KASAN_STACK_MID: 73 case KASAN_STACK_RIGHT: 74 case KASAN_STACK_PARTIAL: 75 bug_type = "stack-out-of-bounds"; 76 break; 77 case KASAN_FREE_PAGE: 78 case KASAN_KMALLOC_FREE: 79 case KASAN_KMALLOC_FREETRACK: 80 bug_type = "use-after-free"; 81 break; 82 case KASAN_ALLOCA_LEFT: 83 case KASAN_ALLOCA_RIGHT: 84 bug_type = "alloca-out-of-bounds"; 85 break; 86 case KASAN_VMALLOC_INVALID: 87 bug_type = "vmalloc-out-of-bounds"; 88 break; 89 } 90 91 return bug_type; 92 } 93 94 static const char *get_wild_bug_type(struct kasan_access_info *info) 95 { 96 const char *bug_type = "unknown-crash"; 97 98 if ((unsigned long)info->access_addr < PAGE_SIZE) 99 bug_type = "null-ptr-deref"; 100 else if ((unsigned long)info->access_addr < TASK_SIZE) 101 bug_type = "user-memory-access"; 102 else 103 bug_type = "wild-memory-access"; 104 105 return bug_type; 106 } 107 108 const char *kasan_get_bug_type(struct kasan_access_info *info) 109 { 110 /* 111 * If access_size is a negative number, then it has reason to be 112 * defined as out-of-bounds bug type. 113 * 114 * Casting negative numbers to size_t would indeed turn up as 115 * a large size_t and its value will be larger than ULONG_MAX/2, 116 * so that this can qualify as out-of-bounds. 117 */ 118 if (info->access_addr + info->access_size < info->access_addr) 119 return "out-of-bounds"; 120 121 if (addr_has_metadata(info->access_addr)) 122 return get_shadow_bug_type(info); 123 return get_wild_bug_type(info); 124 } 125 126 void kasan_metadata_fetch_row(char *buffer, void *row) 127 { 128 memcpy(buffer, kasan_mem_to_shadow(row), META_BYTES_PER_ROW); 129 } 130 131 #ifdef CONFIG_KASAN_STACK 132 static bool __must_check tokenize_frame_descr(const char **frame_descr, 133 char *token, size_t max_tok_len, 134 unsigned long *value) 135 { 136 const char *sep = strchr(*frame_descr, ' '); 137 138 if (sep == NULL) 139 sep = *frame_descr + strlen(*frame_descr); 140 141 if (token != NULL) { 142 const size_t tok_len = sep - *frame_descr; 143 144 if (tok_len + 1 > max_tok_len) { 145 pr_err("KASAN internal error: frame description too long: %s\n", 146 *frame_descr); 147 return false; 148 } 149 150 /* Copy token (+ 1 byte for '\0'). */ 151 strscpy(token, *frame_descr, tok_len + 1); 152 } 153 154 /* Advance frame_descr past separator. */ 155 *frame_descr = sep + 1; 156 157 if (value != NULL && kstrtoul(token, 10, value)) { 158 pr_err("KASAN internal error: not a valid number: %s\n", token); 159 return false; 160 } 161 162 return true; 163 } 164 165 static void print_decoded_frame_descr(const char *frame_descr) 166 { 167 /* 168 * We need to parse the following string: 169 * "n alloc_1 alloc_2 ... alloc_n" 170 * where alloc_i looks like 171 * "offset size len name" 172 * or "offset size len name:line". 173 */ 174 175 char token[64]; 176 unsigned long num_objects; 177 178 if (!tokenize_frame_descr(&frame_descr, token, sizeof(token), 179 &num_objects)) 180 return; 181 182 pr_err("\n"); 183 pr_err("this frame has %lu %s:\n", num_objects, 184 num_objects == 1 ? "object" : "objects"); 185 186 while (num_objects--) { 187 unsigned long offset; 188 unsigned long size; 189 190 /* access offset */ 191 if (!tokenize_frame_descr(&frame_descr, token, sizeof(token), 192 &offset)) 193 return; 194 /* access size */ 195 if (!tokenize_frame_descr(&frame_descr, token, sizeof(token), 196 &size)) 197 return; 198 /* name length (unused) */ 199 if (!tokenize_frame_descr(&frame_descr, NULL, 0, NULL)) 200 return; 201 /* object name */ 202 if (!tokenize_frame_descr(&frame_descr, token, sizeof(token), 203 NULL)) 204 return; 205 206 /* Strip line number; without filename it's not very helpful. */ 207 strreplace(token, ':', '\0'); 208 209 /* Finally, print object information. */ 210 pr_err(" [%lu, %lu) '%s'", offset, offset + size, token); 211 } 212 } 213 214 static bool __must_check get_address_stack_frame_info(const void *addr, 215 unsigned long *offset, 216 const char **frame_descr, 217 const void **frame_pc) 218 { 219 unsigned long aligned_addr; 220 unsigned long mem_ptr; 221 const u8 *shadow_bottom; 222 const u8 *shadow_ptr; 223 const unsigned long *frame; 224 225 BUILD_BUG_ON(IS_ENABLED(CONFIG_STACK_GROWSUP)); 226 227 /* 228 * NOTE: We currently only support printing frame information for 229 * accesses to the task's own stack. 230 */ 231 if (!object_is_on_stack(addr)) 232 return false; 233 234 aligned_addr = round_down((unsigned long)addr, sizeof(long)); 235 mem_ptr = round_down(aligned_addr, KASAN_GRANULE_SIZE); 236 shadow_ptr = kasan_mem_to_shadow((void *)aligned_addr); 237 shadow_bottom = kasan_mem_to_shadow(end_of_stack(current)); 238 239 while (shadow_ptr >= shadow_bottom && *shadow_ptr != KASAN_STACK_LEFT) { 240 shadow_ptr--; 241 mem_ptr -= KASAN_GRANULE_SIZE; 242 } 243 244 while (shadow_ptr >= shadow_bottom && *shadow_ptr == KASAN_STACK_LEFT) { 245 shadow_ptr--; 246 mem_ptr -= KASAN_GRANULE_SIZE; 247 } 248 249 if (shadow_ptr < shadow_bottom) 250 return false; 251 252 frame = (const unsigned long *)(mem_ptr + KASAN_GRANULE_SIZE); 253 if (frame[0] != KASAN_CURRENT_STACK_FRAME_MAGIC) { 254 pr_err("KASAN internal error: frame info validation failed; invalid marker: %lu\n", 255 frame[0]); 256 return false; 257 } 258 259 *offset = (unsigned long)addr - (unsigned long)frame; 260 *frame_descr = (const char *)frame[1]; 261 *frame_pc = (void *)frame[2]; 262 263 return true; 264 } 265 266 void kasan_print_address_stack_frame(const void *addr) 267 { 268 unsigned long offset; 269 const char *frame_descr; 270 const void *frame_pc; 271 272 if (!get_address_stack_frame_info(addr, &offset, &frame_descr, 273 &frame_pc)) 274 return; 275 276 /* 277 * get_address_stack_frame_info only returns true if the given addr is 278 * on the current task's stack. 279 */ 280 pr_err("\n"); 281 pr_err("addr %px is located in stack of task %s/%d at offset %lu in frame:\n", 282 addr, current->comm, task_pid_nr(current), offset); 283 pr_err(" %pS\n", frame_pc); 284 285 if (!frame_descr) 286 return; 287 288 print_decoded_frame_descr(frame_descr); 289 } 290 #endif /* CONFIG_KASAN_STACK */ 291 292 #define DEFINE_ASAN_REPORT_LOAD(size) \ 293 void __asan_report_load##size##_noabort(unsigned long addr) \ 294 { \ 295 kasan_report(addr, size, false, _RET_IP_); \ 296 } \ 297 EXPORT_SYMBOL(__asan_report_load##size##_noabort) 298 299 #define DEFINE_ASAN_REPORT_STORE(size) \ 300 void __asan_report_store##size##_noabort(unsigned long addr) \ 301 { \ 302 kasan_report(addr, size, true, _RET_IP_); \ 303 } \ 304 EXPORT_SYMBOL(__asan_report_store##size##_noabort) 305 306 DEFINE_ASAN_REPORT_LOAD(1); 307 DEFINE_ASAN_REPORT_LOAD(2); 308 DEFINE_ASAN_REPORT_LOAD(4); 309 DEFINE_ASAN_REPORT_LOAD(8); 310 DEFINE_ASAN_REPORT_LOAD(16); 311 DEFINE_ASAN_REPORT_STORE(1); 312 DEFINE_ASAN_REPORT_STORE(2); 313 DEFINE_ASAN_REPORT_STORE(4); 314 DEFINE_ASAN_REPORT_STORE(8); 315 DEFINE_ASAN_REPORT_STORE(16); 316 317 void __asan_report_load_n_noabort(unsigned long addr, size_t size) 318 { 319 kasan_report(addr, size, false, _RET_IP_); 320 } 321 EXPORT_SYMBOL(__asan_report_load_n_noabort); 322 323 void __asan_report_store_n_noabort(unsigned long addr, size_t size) 324 { 325 kasan_report(addr, size, true, _RET_IP_); 326 } 327 EXPORT_SYMBOL(__asan_report_store_n_noabort); 328