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_alloc_pages(struct page *page, unsigned int order, gfp_t flags) 220 { 221 /* 222 * This condition should match the one in post_alloc_hook() in 223 * page_alloc.c. 224 */ 225 bool init = !want_init_on_free() && want_init_on_alloc(flags); 226 227 if (flags & __GFP_SKIP_KASAN_POISON) 228 SetPageSkipKASanPoison(page); 229 230 if (flags & __GFP_ZEROTAGS) { 231 int i; 232 233 for (i = 0; i != 1 << order; ++i) 234 tag_clear_highpage(page + i); 235 } else { 236 kasan_unpoison_pages(page, order, init); 237 } 238 } 239 240 void kasan_free_pages(struct page *page, unsigned int order) 241 { 242 /* 243 * This condition should match the one in free_pages_prepare() in 244 * page_alloc.c. 245 */ 246 bool init = want_init_on_free(); 247 248 kasan_poison_pages(page, order, init); 249 } 250 251 #if IS_ENABLED(CONFIG_KASAN_KUNIT_TEST) 252 253 void kasan_set_tagging_report_once(bool state) 254 { 255 hw_set_tagging_report_once(state); 256 } 257 EXPORT_SYMBOL_GPL(kasan_set_tagging_report_once); 258 259 void kasan_enable_tagging_sync(void) 260 { 261 hw_enable_tagging_sync(); 262 } 263 EXPORT_SYMBOL_GPL(kasan_enable_tagging_sync); 264 265 void kasan_force_async_fault(void) 266 { 267 hw_force_async_tag_fault(); 268 } 269 EXPORT_SYMBOL_GPL(kasan_force_async_fault); 270 271 #endif 272