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_mode { 23 KASAN_ARG_MODE_DEFAULT, 24 KASAN_ARG_MODE_OFF, 25 KASAN_ARG_MODE_PROD, 26 KASAN_ARG_MODE_FULL, 27 }; 28 29 enum kasan_arg_stacktrace { 30 KASAN_ARG_STACKTRACE_DEFAULT, 31 KASAN_ARG_STACKTRACE_OFF, 32 KASAN_ARG_STACKTRACE_ON, 33 }; 34 35 enum kasan_arg_fault { 36 KASAN_ARG_FAULT_DEFAULT, 37 KASAN_ARG_FAULT_REPORT, 38 KASAN_ARG_FAULT_PANIC, 39 }; 40 41 static enum kasan_arg_mode kasan_arg_mode __ro_after_init; 42 static enum kasan_arg_stacktrace kasan_arg_stacktrace __ro_after_init; 43 static enum kasan_arg_fault kasan_arg_fault __ro_after_init; 44 45 /* Whether KASAN is enabled at all. */ 46 DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled); 47 EXPORT_SYMBOL(kasan_flag_enabled); 48 49 /* Whether to collect alloc/free stack traces. */ 50 DEFINE_STATIC_KEY_FALSE(kasan_flag_stacktrace); 51 52 /* Whether panic or disable tag checking on fault. */ 53 bool kasan_flag_panic __ro_after_init; 54 55 /* kasan.mode=off/prod/full */ 56 static int __init early_kasan_mode(char *arg) 57 { 58 if (!arg) 59 return -EINVAL; 60 61 if (!strcmp(arg, "off")) 62 kasan_arg_mode = KASAN_ARG_MODE_OFF; 63 else if (!strcmp(arg, "prod")) 64 kasan_arg_mode = KASAN_ARG_MODE_PROD; 65 else if (!strcmp(arg, "full")) 66 kasan_arg_mode = KASAN_ARG_MODE_FULL; 67 else 68 return -EINVAL; 69 70 return 0; 71 } 72 early_param("kasan.mode", early_kasan_mode); 73 74 /* kasan.stack=off/on */ 75 static int __init early_kasan_flag_stacktrace(char *arg) 76 { 77 if (!arg) 78 return -EINVAL; 79 80 if (!strcmp(arg, "off")) 81 kasan_arg_stacktrace = KASAN_ARG_STACKTRACE_OFF; 82 else if (!strcmp(arg, "on")) 83 kasan_arg_stacktrace = KASAN_ARG_STACKTRACE_ON; 84 else 85 return -EINVAL; 86 87 return 0; 88 } 89 early_param("kasan.stacktrace", early_kasan_flag_stacktrace); 90 91 /* kasan.fault=report/panic */ 92 static int __init early_kasan_fault(char *arg) 93 { 94 if (!arg) 95 return -EINVAL; 96 97 if (!strcmp(arg, "report")) 98 kasan_arg_fault = KASAN_ARG_FAULT_REPORT; 99 else if (!strcmp(arg, "panic")) 100 kasan_arg_fault = KASAN_ARG_FAULT_PANIC; 101 else 102 return -EINVAL; 103 104 return 0; 105 } 106 early_param("kasan.fault", early_kasan_fault); 107 108 /* kasan_init_hw_tags_cpu() is called for each CPU. */ 109 void kasan_init_hw_tags_cpu(void) 110 { 111 /* 112 * There's no need to check that the hardware is MTE-capable here, 113 * as this function is only called for MTE-capable hardware. 114 */ 115 116 /* If KASAN is disabled, do nothing. */ 117 if (kasan_arg_mode == KASAN_ARG_MODE_OFF) 118 return; 119 120 hw_init_tags(KASAN_TAG_MAX); 121 hw_enable_tagging(); 122 } 123 124 /* kasan_init_hw_tags() is called once on boot CPU. */ 125 void __init kasan_init_hw_tags(void) 126 { 127 /* If hardware doesn't support MTE, do nothing. */ 128 if (!system_supports_mte()) 129 return; 130 131 /* Choose KASAN mode if kasan boot parameter is not provided. */ 132 if (kasan_arg_mode == KASAN_ARG_MODE_DEFAULT) { 133 if (IS_ENABLED(CONFIG_DEBUG_KERNEL)) 134 kasan_arg_mode = KASAN_ARG_MODE_FULL; 135 else 136 kasan_arg_mode = KASAN_ARG_MODE_PROD; 137 } 138 139 /* Preset parameter values based on the mode. */ 140 switch (kasan_arg_mode) { 141 case KASAN_ARG_MODE_DEFAULT: 142 /* Shouldn't happen as per the check above. */ 143 WARN_ON(1); 144 return; 145 case KASAN_ARG_MODE_OFF: 146 /* If KASAN is disabled, do nothing. */ 147 return; 148 case KASAN_ARG_MODE_PROD: 149 static_branch_enable(&kasan_flag_enabled); 150 break; 151 case KASAN_ARG_MODE_FULL: 152 static_branch_enable(&kasan_flag_enabled); 153 static_branch_enable(&kasan_flag_stacktrace); 154 break; 155 } 156 157 /* Now, optionally override the presets. */ 158 159 switch (kasan_arg_stacktrace) { 160 case KASAN_ARG_STACKTRACE_DEFAULT: 161 break; 162 case KASAN_ARG_STACKTRACE_OFF: 163 static_branch_disable(&kasan_flag_stacktrace); 164 break; 165 case KASAN_ARG_STACKTRACE_ON: 166 static_branch_enable(&kasan_flag_stacktrace); 167 break; 168 } 169 170 switch (kasan_arg_fault) { 171 case KASAN_ARG_FAULT_DEFAULT: 172 break; 173 case KASAN_ARG_FAULT_REPORT: 174 kasan_flag_panic = false; 175 break; 176 case KASAN_ARG_FAULT_PANIC: 177 kasan_flag_panic = true; 178 break; 179 } 180 181 pr_info("KernelAddressSanitizer initialized\n"); 182 } 183 184 void kasan_set_free_info(struct kmem_cache *cache, 185 void *object, u8 tag) 186 { 187 struct kasan_alloc_meta *alloc_meta; 188 189 alloc_meta = kasan_get_alloc_meta(cache, object); 190 if (alloc_meta) 191 kasan_set_track(&alloc_meta->free_track[0], GFP_NOWAIT); 192 } 193 194 struct kasan_track *kasan_get_free_track(struct kmem_cache *cache, 195 void *object, u8 tag) 196 { 197 struct kasan_alloc_meta *alloc_meta; 198 199 alloc_meta = kasan_get_alloc_meta(cache, object); 200 if (!alloc_meta) 201 return NULL; 202 203 return &alloc_meta->free_track[0]; 204 } 205