Branch data Line data Source code
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 : : * This program is free software; you can redistribute it and/or modify 12 : : * it under the terms of the GNU General Public License version 2 as 13 : : * published by the Free Software Foundation. 14 : : * 15 : : */ 16 : : 17 : : #include <linux/bitops.h> 18 : : #include <linux/ftrace.h> 19 : : #include <linux/init.h> 20 : : #include <linux/kernel.h> 21 : : #include <linux/mm.h> 22 : : #include <linux/printk.h> 23 : : #include <linux/sched.h> 24 : : #include <linux/slab.h> 25 : : #include <linux/stackdepot.h> 26 : : #include <linux/stacktrace.h> 27 : : #include <linux/string.h> 28 : : #include <linux/types.h> 29 : : #include <linux/kasan.h> 30 : : #include <linux/module.h> 31 : : 32 : : #include <asm/sections.h> 33 : : 34 : : #include "kasan.h" 35 : : #include "../slab.h" 36 : : 37 : 0 : void *find_first_bad_addr(void *addr, size_t size) 38 : : { 39 : 0 : void *p = addr; 40 : : 41 [ # # # # ]: 0 : while (p < addr + size && !(*(u8 *)kasan_mem_to_shadow(p))) 42 : 0 : p += KASAN_SHADOW_SCALE_SIZE; 43 : 0 : return p; 44 : : } 45 : : 46 : : static const char *get_shadow_bug_type(struct kasan_access_info *info) 47 : : { 48 : : const char *bug_type = "unknown-crash"; 49 : : u8 *shadow_addr; 50 : : 51 : : shadow_addr = (u8 *)kasan_mem_to_shadow(info->first_bad_addr); 52 : : 53 : : /* 54 : : * If shadow byte value is in [0, KASAN_SHADOW_SCALE_SIZE) we can look 55 : : * at the next shadow byte to determine the type of the bad access. 56 : : */ 57 : : if (*shadow_addr > 0 && *shadow_addr <= KASAN_SHADOW_SCALE_SIZE - 1) 58 : : shadow_addr++; 59 : : 60 : : switch (*shadow_addr) { 61 : : case 0 ... KASAN_SHADOW_SCALE_SIZE - 1: 62 : : /* 63 : : * In theory it's still possible to see these shadow values 64 : : * due to a data race in the kernel code. 65 : : */ 66 : : bug_type = "out-of-bounds"; 67 : : break; 68 : : case KASAN_PAGE_REDZONE: 69 : : case KASAN_KMALLOC_REDZONE: 70 : : bug_type = "slab-out-of-bounds"; 71 : : break; 72 : : case KASAN_GLOBAL_REDZONE: 73 : : bug_type = "global-out-of-bounds"; 74 : : break; 75 : : case KASAN_STACK_LEFT: 76 : : case KASAN_STACK_MID: 77 : : case KASAN_STACK_RIGHT: 78 : : case KASAN_STACK_PARTIAL: 79 : : bug_type = "stack-out-of-bounds"; 80 : : break; 81 : : case KASAN_FREE_PAGE: 82 : : case KASAN_KMALLOC_FREE: 83 : : bug_type = "use-after-free"; 84 : : break; 85 : : case KASAN_ALLOCA_LEFT: 86 : : case KASAN_ALLOCA_RIGHT: 87 : : bug_type = "alloca-out-of-bounds"; 88 : : break; 89 : : case KASAN_VMALLOC_INVALID: 90 : : bug_type = "vmalloc-out-of-bounds"; 91 : : break; 92 : : } 93 : : 94 : : return bug_type; 95 : : } 96 : : 97 : : static const char *get_wild_bug_type(struct kasan_access_info *info) 98 : : { 99 : : const char *bug_type = "unknown-crash"; 100 : : 101 : : if ((unsigned long)info->access_addr < PAGE_SIZE) 102 : : bug_type = "null-ptr-deref"; 103 : : else if ((unsigned long)info->access_addr < TASK_SIZE) 104 : : bug_type = "user-memory-access"; 105 : : else 106 : : bug_type = "wild-memory-access"; 107 : : 108 : : return bug_type; 109 : : } 110 : : 111 : 0 : const char *get_bug_type(struct kasan_access_info *info) 112 : : { 113 [ # # ]: 0 : if (addr_has_shadow(info->access_addr)) 114 : 0 : return get_shadow_bug_type(info); 115 : 0 : return get_wild_bug_type(info); 116 : : } 117 : : 118 : : #define DEFINE_ASAN_REPORT_LOAD(size) \ 119 : : void __asan_report_load##size##_noabort(unsigned long addr) \ 120 : : { \ 121 : : kasan_report(addr, size, false, _RET_IP_); \ 122 : : } \ 123 : : EXPORT_SYMBOL(__asan_report_load##size##_noabort) 124 : : 125 : : #define DEFINE_ASAN_REPORT_STORE(size) \ 126 : : void __asan_report_store##size##_noabort(unsigned long addr) \ 127 : : { \ 128 : : kasan_report(addr, size, true, _RET_IP_); \ 129 : : } \ 130 : : EXPORT_SYMBOL(__asan_report_store##size##_noabort) 131 : : 132 : 2418 : DEFINE_ASAN_REPORT_LOAD(1); 133 : 0 : DEFINE_ASAN_REPORT_LOAD(2); 134 : 2794038 : DEFINE_ASAN_REPORT_LOAD(4); 135 : 13182 : DEFINE_ASAN_REPORT_LOAD(8); 136 : 0 : DEFINE_ASAN_REPORT_LOAD(16); 137 : 0 : DEFINE_ASAN_REPORT_STORE(1); 138 : 61776 : DEFINE_ASAN_REPORT_STORE(2); 139 : 958776 : DEFINE_ASAN_REPORT_STORE(4); 140 : 3912558 : DEFINE_ASAN_REPORT_STORE(8); 141 : 0 : DEFINE_ASAN_REPORT_STORE(16); 142 : : 143 : 1456650 : void __asan_report_load_n_noabort(unsigned long addr, size_t size) 144 : : { 145 : 1456650 : kasan_report(addr, size, false, _RET_IP_); 146 : 1456650 : } 147 : : EXPORT_SYMBOL(__asan_report_load_n_noabort); 148 : : 149 : 1014 : void __asan_report_store_n_noabort(unsigned long addr, size_t size) 150 : : { 151 : 1014 : kasan_report(addr, size, true, _RET_IP_); 152 : 1014 : } 153 : : EXPORT_SYMBOL(__asan_report_store_n_noabort);