]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - lib/ubsan.c
x86/speculation/mmio: Enable CPU Fill buffer clearing on idle
[mirror_ubuntu-jammy-kernel.git] / lib / ubsan.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
c6d30853
AR
2/*
3 * UBSAN error reporting functions
4 *
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
6 * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
c6d30853
AR
7 */
8
9#include <linux/bitops.h>
10#include <linux/bug.h>
11#include <linux/ctype.h>
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/sched.h>
d08965a2 16#include <linux/uaccess.h>
1195505f 17#include <kunit/test-bug.h>
c6d30853
AR
18
19#include "ubsan.h"
20
d3c22797 21static const char * const type_check_kinds[] = {
c6d30853
AR
22 "load of",
23 "store to",
24 "reference binding to",
25 "member access within",
26 "member call on",
27 "constructor call on",
28 "downcast of",
29 "downcast of"
30};
31
32#define REPORTED_BIT 31
33
34#if (BITS_PER_LONG == 64) && defined(__BIG_ENDIAN)
35#define COLUMN_MASK (~(1U << REPORTED_BIT))
36#define LINE_MASK (~0U)
37#else
38#define COLUMN_MASK (~0U)
39#define LINE_MASK (~(1U << REPORTED_BIT))
40#endif
41
42#define VALUE_LENGTH 40
43
44static bool was_reported(struct source_location *location)
45{
46 return test_and_set_bit(REPORTED_BIT, &location->reported);
47}
48
c6d30853
AR
49static bool suppress_report(struct source_location *loc)
50{
51 return current->in_ubsan || was_reported(loc);
52}
53
54static bool type_is_int(struct type_descriptor *type)
55{
56 return type->type_kind == type_kind_int;
57}
58
59static bool type_is_signed(struct type_descriptor *type)
60{
61 WARN_ON(!type_is_int(type));
62 return type->type_info & 1;
63}
64
65static unsigned type_bit_width(struct type_descriptor *type)
66{
67 return 1 << (type->type_info >> 1);
68}
69
70static bool is_inline_int(struct type_descriptor *type)
71{
72 unsigned inline_bits = sizeof(unsigned long)*8;
73 unsigned bits = type_bit_width(type);
74
75 WARN_ON(!type_is_int(type));
76
77 return bits <= inline_bits;
78}
79
f0996bc2 80static s_max get_signed_val(struct type_descriptor *type, void *val)
c6d30853
AR
81{
82 if (is_inline_int(type)) {
83 unsigned extra_bits = sizeof(s_max)*8 - type_bit_width(type);
f0996bc2
AR
84 unsigned long ulong_val = (unsigned long)val;
85
86 return ((s_max)ulong_val) << extra_bits >> extra_bits;
c6d30853
AR
87 }
88
89 if (type_bit_width(type) == 64)
90 return *(s64 *)val;
91
92 return *(s_max *)val;
93}
94
f0996bc2 95static bool val_is_negative(struct type_descriptor *type, void *val)
c6d30853
AR
96{
97 return type_is_signed(type) && get_signed_val(type, val) < 0;
98}
99
f0996bc2 100static u_max get_unsigned_val(struct type_descriptor *type, void *val)
c6d30853
AR
101{
102 if (is_inline_int(type))
f0996bc2 103 return (unsigned long)val;
c6d30853
AR
104
105 if (type_bit_width(type) == 64)
106 return *(u64 *)val;
107
108 return *(u_max *)val;
109}
110
111static void val_to_string(char *str, size_t size, struct type_descriptor *type,
f0996bc2 112 void *value)
c6d30853
AR
113{
114 if (type_is_int(type)) {
115 if (type_bit_width(type) == 128) {
c12d3362 116#if defined(CONFIG_ARCH_SUPPORTS_INT128)
c6d30853
AR
117 u_max val = get_unsigned_val(type, value);
118
119 scnprintf(str, size, "0x%08x%08x%08x%08x",
120 (u32)(val >> 96),
121 (u32)(val >> 64),
122 (u32)(val >> 32),
123 (u32)(val));
124#else
125 WARN_ON(1);
126#endif
127 } else if (type_is_signed(type)) {
128 scnprintf(str, size, "%lld",
129 (s64)get_signed_val(type, value));
130 } else {
131 scnprintf(str, size, "%llu",
132 (u64)get_unsigned_val(type, value));
133 }
134 }
135}
136
ef065653 137static void ubsan_prologue(struct source_location *loc, const char *reason)
c6d30853
AR
138{
139 current->in_ubsan++;
c6d30853
AR
140
141 pr_err("========================================"
142 "========================================\n");
ef065653
KC
143 pr_err("UBSAN: %s in %s:%d:%d\n", reason, loc->file_name,
144 loc->line & LINE_MASK, loc->column & COLUMN_MASK);
1195505f
UG
145
146 kunit_fail_current_test("%s in %s", reason, loc->file_name);
c6d30853
AR
147}
148
ce5c31db 149static void ubsan_epilogue(void)
c6d30853
AR
150{
151 dump_stack();
152 pr_err("========================================"
153 "========================================\n");
ce5c31db 154
c6d30853 155 current->in_ubsan--;
1d28c8d6
KC
156
157 if (panic_on_warn) {
158 /*
159 * This thread may hit another WARN() in the panic path.
160 * Resetting this prevents additional WARN() from panicking the
161 * system on this thread. Other threads are blocked by the
162 * panic_mutex in panic().
163 */
164 panic_on_warn = 0;
165 panic("panic_on_warn set ...\n");
166 }
c6d30853
AR
167}
168
469cbd01 169void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs)
c6d30853 170{
469cbd01 171 struct overflow_data *data = _data;
c6d30853
AR
172 char rhs_val_str[VALUE_LENGTH];
173
174 if (suppress_report(&data->location))
175 return;
176
ef065653 177 ubsan_prologue(&data->location, "division-overflow");
c6d30853
AR
178
179 val_to_string(rhs_val_str, sizeof(rhs_val_str), data->type, rhs);
180
181 if (type_is_signed(data->type) && get_signed_val(data->type, rhs) == -1)
182 pr_err("division of %s by -1 cannot be represented in type %s\n",
183 rhs_val_str, data->type->type_name);
184 else
185 pr_err("division by zero\n");
186
ce5c31db 187 ubsan_epilogue();
c6d30853
AR
188}
189EXPORT_SYMBOL(__ubsan_handle_divrem_overflow);
190
42440c1f 191static void handle_null_ptr_deref(struct type_mismatch_data_common *data)
c6d30853 192{
42440c1f 193 if (suppress_report(data->location))
c6d30853
AR
194 return;
195
ef065653 196 ubsan_prologue(data->location, "null-ptr-deref");
c6d30853
AR
197
198 pr_err("%s null pointer of type %s\n",
199 type_check_kinds[data->type_check_kind],
200 data->type->type_name);
201
ce5c31db 202 ubsan_epilogue();
c6d30853
AR
203}
204
42440c1f 205static void handle_misaligned_access(struct type_mismatch_data_common *data,
c6d30853
AR
206 unsigned long ptr)
207{
42440c1f 208 if (suppress_report(data->location))
c6d30853
AR
209 return;
210
ef065653 211 ubsan_prologue(data->location, "misaligned-access");
c6d30853
AR
212
213 pr_err("%s misaligned address %p for type %s\n",
214 type_check_kinds[data->type_check_kind],
215 (void *)ptr, data->type->type_name);
216 pr_err("which requires %ld byte alignment\n", data->alignment);
217
ce5c31db 218 ubsan_epilogue();
c6d30853
AR
219}
220
42440c1f 221static void handle_object_size_mismatch(struct type_mismatch_data_common *data,
c6d30853
AR
222 unsigned long ptr)
223{
42440c1f 224 if (suppress_report(data->location))
c6d30853
AR
225 return;
226
ef065653 227 ubsan_prologue(data->location, "object-size-mismatch");
901d805c 228 pr_err("%s address %p with insufficient space\n",
c6d30853
AR
229 type_check_kinds[data->type_check_kind],
230 (void *) ptr);
231 pr_err("for an object of type %s\n", data->type->type_name);
ce5c31db 232 ubsan_epilogue();
c6d30853
AR
233}
234
42440c1f 235static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data,
c6d30853
AR
236 unsigned long ptr)
237{
d08965a2 238 unsigned long flags = user_access_save();
c6d30853
AR
239
240 if (!ptr)
241 handle_null_ptr_deref(data);
242 else if (data->alignment && !IS_ALIGNED(ptr, data->alignment))
b8fe1120 243 handle_misaligned_access(data, ptr);
c6d30853
AR
244 else
245 handle_object_size_mismatch(data, ptr);
d08965a2
PZ
246
247 user_access_restore(flags);
c6d30853 248}
42440c1f
AR
249
250void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
f0996bc2 251 void *ptr)
42440c1f
AR
252{
253 struct type_mismatch_data_common common_data = {
254 .location = &data->location,
255 .type = data->type,
256 .alignment = data->alignment,
257 .type_check_kind = data->type_check_kind
258 };
259
f0996bc2 260 ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
42440c1f 261}
c6d30853
AR
262EXPORT_SYMBOL(__ubsan_handle_type_mismatch);
263
469cbd01 264void __ubsan_handle_type_mismatch_v1(void *_data, void *ptr)
42440c1f 265{
469cbd01 266 struct type_mismatch_data_v1 *data = _data;
42440c1f
AR
267 struct type_mismatch_data_common common_data = {
268 .location = &data->location,
269 .type = data->type,
270 .alignment = 1UL << data->log_alignment,
271 .type_check_kind = data->type_check_kind
272 };
273
f0996bc2 274 ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
42440c1f
AR
275}
276EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1);
277
469cbd01 278void __ubsan_handle_out_of_bounds(void *_data, void *index)
c6d30853 279{
469cbd01 280 struct out_of_bounds_data *data = _data;
c6d30853
AR
281 char index_str[VALUE_LENGTH];
282
283 if (suppress_report(&data->location))
284 return;
285
ef065653 286 ubsan_prologue(&data->location, "array-index-out-of-bounds");
c6d30853
AR
287
288 val_to_string(index_str, sizeof(index_str), data->index_type, index);
289 pr_err("index %s is out of range for type %s\n", index_str,
290 data->array_type->type_name);
ce5c31db 291 ubsan_epilogue();
c6d30853
AR
292}
293EXPORT_SYMBOL(__ubsan_handle_out_of_bounds);
294
469cbd01 295void __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs)
c6d30853 296{
469cbd01 297 struct shift_out_of_bounds_data *data = _data;
c6d30853
AR
298 struct type_descriptor *rhs_type = data->rhs_type;
299 struct type_descriptor *lhs_type = data->lhs_type;
300 char rhs_str[VALUE_LENGTH];
301 char lhs_str[VALUE_LENGTH];
9a50dcaf 302 unsigned long ua_flags = user_access_save();
c6d30853
AR
303
304 if (suppress_report(&data->location))
9a50dcaf 305 goto out;
c6d30853 306
ef065653 307 ubsan_prologue(&data->location, "shift-out-of-bounds");
c6d30853
AR
308
309 val_to_string(rhs_str, sizeof(rhs_str), rhs_type, rhs);
310 val_to_string(lhs_str, sizeof(lhs_str), lhs_type, lhs);
311
312 if (val_is_negative(rhs_type, rhs))
313 pr_err("shift exponent %s is negative\n", rhs_str);
314
315 else if (get_unsigned_val(rhs_type, rhs) >=
316 type_bit_width(lhs_type))
317 pr_err("shift exponent %s is too large for %u-bit type %s\n",
318 rhs_str,
319 type_bit_width(lhs_type),
320 lhs_type->type_name);
321 else if (val_is_negative(lhs_type, lhs))
322 pr_err("left shift of negative value %s\n",
323 lhs_str);
324 else
325 pr_err("left shift of %s by %s places cannot be"
326 " represented in type %s\n",
327 lhs_str, rhs_str,
328 lhs_type->type_name);
329
ce5c31db 330 ubsan_epilogue();
9a50dcaf
PZ
331out:
332 user_access_restore(ua_flags);
c6d30853
AR
333}
334EXPORT_SYMBOL(__ubsan_handle_shift_out_of_bounds);
335
336
469cbd01 337void __ubsan_handle_builtin_unreachable(void *_data)
c6d30853 338{
469cbd01 339 struct unreachable_data *data = _data;
ef065653 340 ubsan_prologue(&data->location, "unreachable");
c6d30853 341 pr_err("calling __builtin_unreachable()\n");
ce5c31db 342 ubsan_epilogue();
c6d30853
AR
343 panic("can't return from __builtin_unreachable()");
344}
345EXPORT_SYMBOL(__ubsan_handle_builtin_unreachable);
346
469cbd01 347void __ubsan_handle_load_invalid_value(void *_data, void *val)
c6d30853 348{
469cbd01 349 struct invalid_value_data *data = _data;
c6d30853
AR
350 char val_str[VALUE_LENGTH];
351
352 if (suppress_report(&data->location))
353 return;
354
ef065653 355 ubsan_prologue(&data->location, "invalid-load");
c6d30853
AR
356
357 val_to_string(val_str, sizeof(val_str), data->type, val);
358
359 pr_err("load of value %s is not a valid value for type %s\n",
360 val_str, data->type->type_name);
361
ce5c31db 362 ubsan_epilogue();
c6d30853
AR
363}
364EXPORT_SYMBOL(__ubsan_handle_load_invalid_value);
28abcc96
NC
365
366void __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr,
367 unsigned long align,
368 unsigned long offset);
369void __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr,
370 unsigned long align,
371 unsigned long offset)
372{
373 struct alignment_assumption_data *data = _data;
374 unsigned long real_ptr;
375
376 if (suppress_report(&data->location))
377 return;
378
379 ubsan_prologue(&data->location, "alignment-assumption");
380
381 if (offset)
382 pr_err("assumption of %lu byte alignment (with offset of %lu byte) for pointer of type %s failed",
383 align, offset, data->type->type_name);
384 else
385 pr_err("assumption of %lu byte alignment for pointer of type %s failed",
386 align, data->type->type_name);
387
388 real_ptr = ptr - offset;
389 pr_err("%saddress is %lu aligned, misalignment offset is %lu bytes",
390 offset ? "offset " : "", BIT(real_ptr ? __ffs(real_ptr) : 0),
391 real_ptr & (align - 1));
392
393 ubsan_epilogue();
394}
395EXPORT_SYMBOL(__ubsan_handle_alignment_assumption);