1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * This file contains core hardware tag-based KASAN code. 4 * 5 * Copyright (c) 2020 Google, Inc. 6 * Author: Andrey Konovalov <andreyknvl@google.com> 7 */ 8 9 #define pr_fmt(fmt) "kasan: " fmt 10 11 #include <linux/init.h> 12 #include <linux/kasan.h> 13 #include <linux/kernel.h> 14 #include <linux/memory.h> 15 #include <linux/mm.h> 16 #include <linux/static_key.h> 17 #include <linux/string.h> 18 #include <linux/types.h> 19 20 #include "kasan.h" 21 22 enum kasan_arg { 23 KASAN_ARG_DEFAULT, 24 KASAN_ARG_OFF, 25 KASAN_ARG_ON, 26 }; 27 28 enum kasan_arg_mode { 29 KASAN_ARG_MODE_DEFAULT, 30 KASAN_ARG_MODE_SYNC, 31 KASAN_ARG_MODE_ASYNC, 32 }; 33 34 enum kasan_arg_stacktrace { 35 KASAN_ARG_STACKTRACE_DEFAULT, 36 KASAN_ARG_STACKTRACE_OFF, 37 KASAN_ARG_STACKTRACE_ON, 38 }; 39 40 enum kasan_arg_fault { 41 KASAN_ARG_FAULT_DEFAULT, 42 KASAN_ARG_FAULT_REPORT, 43 KASAN_ARG_FAULT_PANIC, 44 }; 45 46 static enum kasan_arg kasan_arg __ro_after_init; 47 static enum kasan_arg_mode kasan_arg_mode __ro_after_init; 48 static enum kasan_arg_stacktrace kasan_arg_stacktrace __ro_after_init; 49 static enum kasan_arg_fault kasan_arg_fault __ro_after_init; 50 51 /* Whether KASAN is enabled at all. */ 52 DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled); 53 EXPORT_SYMBOL(kasan_flag_enabled); 54 55 /* Whether the asynchronous mode is enabled. */ 56 bool kasan_flag_async __ro_after_init; 57 EXPORT_SYMBOL_GPL(kasan_flag_async); 58 59 /* Whether to collect alloc/free stack traces. */ 60 DEFINE_STATIC_KEY_FALSE(kasan_flag_stacktrace); 61 62 /* Whether to panic or print a report and disable tag checking on fault. */ 63 bool kasan_flag_panic __ro_after_init; 64 65 /* kasan=off/on */ 66 static int __init early_kasan_flag(char *arg) 67 { 68 if (!arg) 69 return -EINVAL; 70 71 if (!strcmp(arg, "off")) 72 kasan_arg = KASAN_ARG_OFF; 73 else if (!strcmp(arg, "on")) 74 kasan_arg = KASAN_ARG_ON; 75 else 76 return -EINVAL; 77 78 return 0; 79 } 80 early_param("kasan", early_kasan_flag); 81 82 /* kasan.mode=sync/async */ 83 static int __init early_kasan_mode(char *arg) 84 { 85 if (!arg) 86 return -EINVAL; 87 88 if (!strcmp(arg, "sync")) 89 kasan_arg_mode = KASAN_ARG_MODE_SYNC; 90 else if (!strcmp(arg, "async")) 91 kasan_arg_mode = KASAN_ARG_MODE_ASYNC; 92 else 93 return -EINVAL; 94 95 return 0; 96 } 97 early_param("kasan.mode", early_kasan_mode); 98 99 /* kasan.stacktrace=off/on */ 100 static int __init early_kasan_flag_stacktrace(char *arg) 101 { 102 if (!arg) 103 return -EINVAL; 104 105 if (!strcmp(arg, "off")) 106 kasan_arg_stacktrace = KASAN_ARG_STACKTRACE_OFF; 107 else if (!strcmp(arg, "on")) 108 kasan_arg_stacktrace = KASAN_ARG_STACKTRACE_ON; 109 else 110 return -EINVAL; 111 112 return 0; 113 } 114 early_param("kasan.stacktrace", early_kasan_flag_stacktrace); 115 116 /* kasan.fault=report/panic */ 117 static int __init early_kasan_fault(char *arg) 118 { 119 if (!arg) 120 return -EINVAL; 121 122 if (!strcmp(arg, "report")) 123 kasan_arg_fault = KASAN_ARG_FAULT_REPORT; 124 else if (!strcmp(arg, "panic")) 125 kasan_arg_fault = KASAN_ARG_FAULT_PANIC; 126 else 127 return -EINVAL; 128 129 return 0; 130 } 131 early_param("kasan.fault", early_kasan_fault); 132 133 /* kasan_init_hw_tags_cpu() is called for each CPU. */ 134 void kasan_init_hw_tags_cpu(void) 135 { 136 /* 137 * There's no need to check that the hardware is MTE-capable here, 138 * as this function is only called for MTE-capable hardware. 139 */ 140 141 /* If KASAN is disabled via command line, don't initialize it. */ 142 if (kasan_arg == KASAN_ARG_OFF) 143 return; 144 145 hw_init_tags(KASAN_TAG_MAX); 146 147 /* 148 * Enable async mode only when explicitly requested through 149 * the command line. 150 */ 151 if (kasan_arg_mode == KASAN_ARG_MODE_ASYNC) 152 hw_enable_tagging_async(); 153 else 154 hw_enable_tagging_sync(); 155 } 156 157 /* kasan_init_hw_tags() is called once on boot CPU. */ 158 void __init kasan_init_hw_tags(void) 159 { 160 /* If hardware doesn't support MTE, don't initialize KASAN. */ 161 if (!system_supports_mte()) 162 return; 163 164 /* If KASAN is disabled via command line, don't initialize it. */ 165 if (kasan_arg == KASAN_ARG_OFF) 166 return; 167 168 /* Enable KASAN. */ 169 static_branch_enable(&kasan_flag_enabled); 170 171 switch (kasan_arg_mode) { 172 case KASAN_ARG_MODE_DEFAULT: 173 /* 174 * Default to sync mode. 175 * Do nothing, kasan_flag_async keeps its default value. 176 */ 177 break; 178 case KASAN_ARG_MODE_SYNC: 179 /* Do nothing, kasan_flag_async keeps its default value. */ 180 break; 181 case KASAN_ARG_MODE_ASYNC: 182 /* Async mode enabled. */ 183 kasan_flag_async = true; 184 break; 185 } 186 187 switch (kasan_arg_stacktrace) { 188 case KASAN_ARG_STACKTRACE_DEFAULT: 189 /* Default to enabling stack trace collection. */ 190 static_branch_enable(&kasan_flag_stacktrace); 191 break; 192 case KASAN_ARG_STACKTRACE_OFF: 193 /* Do nothing, kasan_flag_stacktrace keeps its default value. */ 194 break; 195 case KASAN_ARG_STACKTRACE_ON: 196 static_branch_enable(&kasan_flag_stacktrace); 197 break; 198 } 199 200 switch (kasan_arg_fault) { 201 case KASAN_ARG_FAULT_DEFAULT: 202 /* 203 * Default to no panic on report. 204 * Do nothing, kasan_flag_panic keeps its default value. 205 */ 206 break; 207 case KASAN_ARG_FAULT_REPORT: 208 /* Do nothing, kasan_flag_panic keeps its default value. */ 209 break; 210 case KASAN_ARG_FAULT_PANIC: 211 /* Enable panic on report. */ 212 kasan_flag_panic = true; 213 break; 214 } 215 216 pr_info("KernelAddressSanitizer initialized\n"); 217 } 218 219 void kasan_set_free_info(struct kmem_cache *cache, 220 void *object, u8 tag) 221 { 222 struct kasan_alloc_meta *alloc_meta; 223 224 alloc_meta = kasan_get_alloc_meta(cache, object); 225 if (alloc_meta) 226 kasan_set_track(&alloc_meta->free_track[0], GFP_NOWAIT); 227 } 228 229 struct kasan_track *kasan_get_free_track(struct kmem_cache *cache, 230 void *object, u8 tag) 231 { 232 struct kasan_alloc_meta *alloc_meta; 233 234 alloc_meta = kasan_get_alloc_meta(cache, object); 235 if (!alloc_meta) 236 return NULL; 237 238 return &alloc_meta->free_track[0]; 239 } 240 241 #if IS_ENABLED(CONFIG_KASAN_KUNIT_TEST) 242 243 void kasan_set_tagging_report_once(bool state) 244 { 245 hw_set_tagging_report_once(state); 246 } 247 EXPORT_SYMBOL_GPL(kasan_set_tagging_report_once); 248 249 void kasan_enable_tagging_sync(void) 250 { 251 hw_enable_tagging_sync(); 252 } 253 EXPORT_SYMBOL_GPL(kasan_enable_tagging_sync); 254 255 void kasan_force_async_fault(void) 256 { 257 hw_force_async_tag_fault(); 258 } 259 EXPORT_SYMBOL_GPL(kasan_force_async_fault); 260 261 #endif 262