Merge tag 'xfs-5.12-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[linux-block.git] / mm / kasan / hw_tags.c
CommitLineData
2e903b91
AK
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
8028caac 11#include <linux/init.h>
2e903b91
AK
12#include <linux/kasan.h>
13#include <linux/kernel.h>
14#include <linux/memory.h>
15#include <linux/mm.h>
8028caac 16#include <linux/static_key.h>
2e903b91
AK
17#include <linux/string.h>
18#include <linux/types.h>
19
20#include "kasan.h"
21
76bc99e8
AK
22enum kasan_arg {
23 KASAN_ARG_DEFAULT,
24 KASAN_ARG_OFF,
25 KASAN_ARG_ON,
8028caac
AK
26};
27
28enum kasan_arg_stacktrace {
29 KASAN_ARG_STACKTRACE_DEFAULT,
30 KASAN_ARG_STACKTRACE_OFF,
31 KASAN_ARG_STACKTRACE_ON,
32};
33
34enum kasan_arg_fault {
35 KASAN_ARG_FAULT_DEFAULT,
36 KASAN_ARG_FAULT_REPORT,
37 KASAN_ARG_FAULT_PANIC,
38};
39
76bc99e8 40static enum kasan_arg kasan_arg __ro_after_init;
8028caac
AK
41static enum kasan_arg_stacktrace kasan_arg_stacktrace __ro_after_init;
42static enum kasan_arg_fault kasan_arg_fault __ro_after_init;
43
44/* Whether KASAN is enabled at all. */
45DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled);
46EXPORT_SYMBOL(kasan_flag_enabled);
47
48/* Whether to collect alloc/free stack traces. */
49DEFINE_STATIC_KEY_FALSE(kasan_flag_stacktrace);
50
7169487b 51/* Whether to panic or print a report and disable tag checking on fault. */
8028caac
AK
52bool kasan_flag_panic __ro_after_init;
53
76bc99e8
AK
54/* kasan=off/on */
55static int __init early_kasan_flag(char *arg)
8028caac
AK
56{
57 if (!arg)
58 return -EINVAL;
59
60 if (!strcmp(arg, "off"))
76bc99e8
AK
61 kasan_arg = KASAN_ARG_OFF;
62 else if (!strcmp(arg, "on"))
63 kasan_arg = KASAN_ARG_ON;
8028caac
AK
64 else
65 return -EINVAL;
66
67 return 0;
68}
76bc99e8 69early_param("kasan", early_kasan_flag);
8028caac 70
76bc99e8 71/* kasan.stacktrace=off/on */
8028caac
AK
72static int __init early_kasan_flag_stacktrace(char *arg)
73{
74 if (!arg)
75 return -EINVAL;
76
77 if (!strcmp(arg, "off"))
78 kasan_arg_stacktrace = KASAN_ARG_STACKTRACE_OFF;
79 else if (!strcmp(arg, "on"))
80 kasan_arg_stacktrace = KASAN_ARG_STACKTRACE_ON;
81 else
82 return -EINVAL;
83
84 return 0;
85}
86early_param("kasan.stacktrace", early_kasan_flag_stacktrace);
87
88/* kasan.fault=report/panic */
89static int __init early_kasan_fault(char *arg)
90{
91 if (!arg)
92 return -EINVAL;
93
94 if (!strcmp(arg, "report"))
95 kasan_arg_fault = KASAN_ARG_FAULT_REPORT;
96 else if (!strcmp(arg, "panic"))
97 kasan_arg_fault = KASAN_ARG_FAULT_PANIC;
98 else
99 return -EINVAL;
100
101 return 0;
102}
103early_param("kasan.fault", early_kasan_fault);
104
2e903b91
AK
105/* kasan_init_hw_tags_cpu() is called for each CPU. */
106void kasan_init_hw_tags_cpu(void)
107{
8028caac
AK
108 /*
109 * There's no need to check that the hardware is MTE-capable here,
110 * as this function is only called for MTE-capable hardware.
111 */
112
76bc99e8
AK
113 /* If KASAN is disabled via command line, don't initialize it. */
114 if (kasan_arg == KASAN_ARG_OFF)
8028caac
AK
115 return;
116
2e903b91
AK
117 hw_init_tags(KASAN_TAG_MAX);
118 hw_enable_tagging();
119}
120
121/* kasan_init_hw_tags() is called once on boot CPU. */
122void __init kasan_init_hw_tags(void)
123{
76bc99e8 124 /* If hardware doesn't support MTE, don't initialize KASAN. */
8028caac
AK
125 if (!system_supports_mte())
126 return;
127
76bc99e8
AK
128 /* If KASAN is disabled via command line, don't initialize it. */
129 if (kasan_arg == KASAN_ARG_OFF)
8028caac 130 return;
8028caac 131
76bc99e8
AK
132 /* Enable KASAN. */
133 static_branch_enable(&kasan_flag_enabled);
8028caac
AK
134
135 switch (kasan_arg_stacktrace) {
136 case KASAN_ARG_STACKTRACE_DEFAULT:
1cc4cdb5
AK
137 /* Default to enabling stack trace collection. */
138 static_branch_enable(&kasan_flag_stacktrace);
8028caac
AK
139 break;
140 case KASAN_ARG_STACKTRACE_OFF:
76bc99e8 141 /* Do nothing, kasan_flag_stacktrace keeps its default value. */
8028caac
AK
142 break;
143 case KASAN_ARG_STACKTRACE_ON:
144 static_branch_enable(&kasan_flag_stacktrace);
145 break;
146 }
147
148 switch (kasan_arg_fault) {
149 case KASAN_ARG_FAULT_DEFAULT:
76bc99e8
AK
150 /*
151 * Default to no panic on report.
152 * Do nothing, kasan_flag_panic keeps its default value.
153 */
8028caac
AK
154 break;
155 case KASAN_ARG_FAULT_REPORT:
76bc99e8 156 /* Do nothing, kasan_flag_panic keeps its default value. */
8028caac
AK
157 break;
158 case KASAN_ARG_FAULT_PANIC:
76bc99e8 159 /* Enable panic on report. */
8028caac
AK
160 kasan_flag_panic = true;
161 break;
162 }
163
2e903b91
AK
164 pr_info("KernelAddressSanitizer initialized\n");
165}
166
2e903b91
AK
167void kasan_set_free_info(struct kmem_cache *cache,
168 void *object, u8 tag)
169{
170 struct kasan_alloc_meta *alloc_meta;
171
6476792f 172 alloc_meta = kasan_get_alloc_meta(cache, object);
97593cad
AK
173 if (alloc_meta)
174 kasan_set_track(&alloc_meta->free_track[0], GFP_NOWAIT);
2e903b91
AK
175}
176
177struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
178 void *object, u8 tag)
179{
180 struct kasan_alloc_meta *alloc_meta;
181
6476792f 182 alloc_meta = kasan_get_alloc_meta(cache, object);
97593cad
AK
183 if (!alloc_meta)
184 return NULL;
185
2e903b91
AK
186 return &alloc_meta->free_track[0];
187}
f05842cf
AK
188
189#if IS_ENABLED(CONFIG_KASAN_KUNIT_TEST)
190
191void kasan_set_tagging_report_once(bool state)
192{
193 hw_set_tagging_report_once(state);
194}
195EXPORT_SYMBOL_GPL(kasan_set_tagging_report_once);
196
197void kasan_enable_tagging(void)
198{
199 hw_enable_tagging();
200}
201EXPORT_SYMBOL_GPL(kasan_enable_tagging);
202
203#endif