]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - mm/kasan/hw_tags.c
Merge tag 'amlogic-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman...
[mirror_ubuntu-jammy-kernel.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
8028caac
AK
22enum 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
29enum kasan_arg_stacktrace {
30 KASAN_ARG_STACKTRACE_DEFAULT,
31 KASAN_ARG_STACKTRACE_OFF,
32 KASAN_ARG_STACKTRACE_ON,
33};
34
35enum kasan_arg_fault {
36 KASAN_ARG_FAULT_DEFAULT,
37 KASAN_ARG_FAULT_REPORT,
38 KASAN_ARG_FAULT_PANIC,
39};
40
41static enum kasan_arg_mode kasan_arg_mode __ro_after_init;
42static enum kasan_arg_stacktrace kasan_arg_stacktrace __ro_after_init;
43static enum kasan_arg_fault kasan_arg_fault __ro_after_init;
44
45/* Whether KASAN is enabled at all. */
46DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled);
47EXPORT_SYMBOL(kasan_flag_enabled);
48
49/* Whether to collect alloc/free stack traces. */
50DEFINE_STATIC_KEY_FALSE(kasan_flag_stacktrace);
51
52/* Whether panic or disable tag checking on fault. */
53bool kasan_flag_panic __ro_after_init;
54
55/* kasan.mode=off/prod/full */
56static 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}
72early_param("kasan.mode", early_kasan_mode);
73
74/* kasan.stack=off/on */
75static 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}
89early_param("kasan.stacktrace", early_kasan_flag_stacktrace);
90
91/* kasan.fault=report/panic */
92static 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}
106early_param("kasan.fault", early_kasan_fault);
107
2e903b91
AK
108/* kasan_init_hw_tags_cpu() is called for each CPU. */
109void kasan_init_hw_tags_cpu(void)
110{
8028caac
AK
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
2e903b91
AK
120 hw_init_tags(KASAN_TAG_MAX);
121 hw_enable_tagging();
122}
123
124/* kasan_init_hw_tags() is called once on boot CPU. */
125void __init kasan_init_hw_tags(void)
126{
8028caac
AK
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
2e903b91
AK
181 pr_info("KernelAddressSanitizer initialized\n");
182}
183
2e903b91
AK
184void kasan_set_free_info(struct kmem_cache *cache,
185 void *object, u8 tag)
186{
187 struct kasan_alloc_meta *alloc_meta;
188
6476792f 189 alloc_meta = kasan_get_alloc_meta(cache, object);
97593cad
AK
190 if (alloc_meta)
191 kasan_set_track(&alloc_meta->free_track[0], GFP_NOWAIT);
2e903b91
AK
192}
193
194struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
195 void *object, u8 tag)
196{
197 struct kasan_alloc_meta *alloc_meta;
198
6476792f 199 alloc_meta = kasan_get_alloc_meta(cache, object);
97593cad
AK
200 if (!alloc_meta)
201 return NULL;
202
2e903b91
AK
203 return &alloc_meta->free_track[0];
204}