]> git.ipfire.org Git - thirdparty/kernel/linux.git/blame - lib/ubsan.c
Merge tag 'drm-misc-fixes-2024-02-15' of git://anongit.freedesktop.org/drm/drm-misc...
[thirdparty/kernel/linux.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>
25b84002 17#include <linux/ubsan.h>
1195505f 18#include <kunit/test-bug.h>
c6d30853
AR
19
20#include "ubsan.h"
21
25b84002
KC
22#ifdef CONFIG_UBSAN_TRAP
23/*
24 * Only include matches for UBSAN checks that are actually compiled in.
25 * The mappings of struct SanitizerKind (the -fsanitize=xxx args) to
26 * enum SanitizerHandler (the traps) in Clang is in clang/lib/CodeGen/.
27 */
28const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type)
29{
30 switch (check_type) {
31#ifdef CONFIG_UBSAN_BOUNDS
32 /*
33 * SanitizerKind::ArrayBounds and SanitizerKind::LocalBounds
34 * emit SanitizerHandler::OutOfBounds.
35 */
36 case ubsan_out_of_bounds:
37 return "UBSAN: array index out of bounds";
38#endif
39#ifdef CONFIG_UBSAN_SHIFT
40 /*
41 * SanitizerKind::ShiftBase and SanitizerKind::ShiftExponent
42 * emit SanitizerHandler::ShiftOutOfBounds.
43 */
44 case ubsan_shift_out_of_bounds:
45 return "UBSAN: shift out of bounds";
46#endif
47#ifdef CONFIG_UBSAN_DIV_ZERO
48 /*
49 * SanitizerKind::IntegerDivideByZero emits
50 * SanitizerHandler::DivremOverflow.
51 */
52 case ubsan_divrem_overflow:
53 return "UBSAN: divide/remainder overflow";
54#endif
55#ifdef CONFIG_UBSAN_UNREACHABLE
56 /*
57 * SanitizerKind::Unreachable emits
58 * SanitizerHandler::BuiltinUnreachable.
59 */
60 case ubsan_builtin_unreachable:
61 return "UBSAN: unreachable code";
62#endif
63#if defined(CONFIG_UBSAN_BOOL) || defined(CONFIG_UBSAN_ENUM)
64 /*
65 * SanitizerKind::Bool and SanitizerKind::Enum emit
66 * SanitizerHandler::LoadInvalidValue.
67 */
68 case ubsan_load_invalid_value:
69 return "UBSAN: loading invalid value";
70#endif
71#ifdef CONFIG_UBSAN_ALIGNMENT
72 /*
73 * SanitizerKind::Alignment emits SanitizerHandler::TypeMismatch
74 * or SanitizerHandler::AlignmentAssumption.
75 */
76 case ubsan_alignment_assumption:
77 return "UBSAN: alignment assumption";
78 case ubsan_type_mismatch:
79 return "UBSAN: type mismatch";
80#endif
81 default:
82 return "UBSAN: unrecognized failure code";
83 }
84}
85
86#else
d3c22797 87static const char * const type_check_kinds[] = {
c6d30853
AR
88 "load of",
89 "store to",
90 "reference binding to",
91 "member access within",
92 "member call on",
93 "constructor call on",
94 "downcast of",
95 "downcast of"
96};
97
98#define REPORTED_BIT 31
99
100#if (BITS_PER_LONG == 64) && defined(__BIG_ENDIAN)
101#define COLUMN_MASK (~(1U << REPORTED_BIT))
102#define LINE_MASK (~0U)
103#else
104#define COLUMN_MASK (~0U)
105#define LINE_MASK (~(1U << REPORTED_BIT))
106#endif
107
108#define VALUE_LENGTH 40
109
110static bool was_reported(struct source_location *location)
111{
112 return test_and_set_bit(REPORTED_BIT, &location->reported);
113}
114
c6d30853
AR
115static bool suppress_report(struct source_location *loc)
116{
117 return current->in_ubsan || was_reported(loc);
118}
119
120static bool type_is_int(struct type_descriptor *type)
121{
122 return type->type_kind == type_kind_int;
123}
124
125static bool type_is_signed(struct type_descriptor *type)
126{
127 WARN_ON(!type_is_int(type));
128 return type->type_info & 1;
129}
130
131static unsigned type_bit_width(struct type_descriptor *type)
132{
133 return 1 << (type->type_info >> 1);
134}
135
136static bool is_inline_int(struct type_descriptor *type)
137{
138 unsigned inline_bits = sizeof(unsigned long)*8;
139 unsigned bits = type_bit_width(type);
140
141 WARN_ON(!type_is_int(type));
142
143 return bits <= inline_bits;
144}
145
f0996bc2 146static s_max get_signed_val(struct type_descriptor *type, void *val)
c6d30853
AR
147{
148 if (is_inline_int(type)) {
149 unsigned extra_bits = sizeof(s_max)*8 - type_bit_width(type);
f0996bc2
AR
150 unsigned long ulong_val = (unsigned long)val;
151
152 return ((s_max)ulong_val) << extra_bits >> extra_bits;
c6d30853
AR
153 }
154
155 if (type_bit_width(type) == 64)
156 return *(s64 *)val;
157
158 return *(s_max *)val;
159}
160
f0996bc2 161static bool val_is_negative(struct type_descriptor *type, void *val)
c6d30853
AR
162{
163 return type_is_signed(type) && get_signed_val(type, val) < 0;
164}
165
f0996bc2 166static u_max get_unsigned_val(struct type_descriptor *type, void *val)
c6d30853
AR
167{
168 if (is_inline_int(type))
f0996bc2 169 return (unsigned long)val;
c6d30853
AR
170
171 if (type_bit_width(type) == 64)
172 return *(u64 *)val;
173
174 return *(u_max *)val;
175}
176
177static void val_to_string(char *str, size_t size, struct type_descriptor *type,
f0996bc2 178 void *value)
c6d30853
AR
179{
180 if (type_is_int(type)) {
181 if (type_bit_width(type) == 128) {
c12d3362 182#if defined(CONFIG_ARCH_SUPPORTS_INT128)
c6d30853
AR
183 u_max val = get_unsigned_val(type, value);
184
185 scnprintf(str, size, "0x%08x%08x%08x%08x",
186 (u32)(val >> 96),
187 (u32)(val >> 64),
188 (u32)(val >> 32),
189 (u32)(val));
190#else
191 WARN_ON(1);
192#endif
193 } else if (type_is_signed(type)) {
194 scnprintf(str, size, "%lld",
195 (s64)get_signed_val(type, value));
196 } else {
197 scnprintf(str, size, "%llu",
198 (u64)get_unsigned_val(type, value));
199 }
200 }
201}
202
ef065653 203static void ubsan_prologue(struct source_location *loc, const char *reason)
c6d30853
AR
204{
205 current->in_ubsan++;
c6d30853 206
ffda6556
BPA
207 pr_warn(CUT_HERE);
208
ef065653
KC
209 pr_err("UBSAN: %s in %s:%d:%d\n", reason, loc->file_name,
210 loc->line & LINE_MASK, loc->column & COLUMN_MASK);
1195505f
UG
211
212 kunit_fail_current_test("%s in %s", reason, loc->file_name);
c6d30853
AR
213}
214
ce5c31db 215static void ubsan_epilogue(void)
c6d30853
AR
216{
217 dump_stack();
ffda6556 218 pr_warn("---[ end trace ]---\n");
ce5c31db 219
c6d30853 220 current->in_ubsan--;
1d28c8d6 221
79cc1ba7 222 check_panic_on_warn("UBSAN");
c6d30853
AR
223}
224
469cbd01 225void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs)
c6d30853 226{
469cbd01 227 struct overflow_data *data = _data;
c6d30853
AR
228 char rhs_val_str[VALUE_LENGTH];
229
230 if (suppress_report(&data->location))
231 return;
232
ef065653 233 ubsan_prologue(&data->location, "division-overflow");
c6d30853
AR
234
235 val_to_string(rhs_val_str, sizeof(rhs_val_str), data->type, rhs);
236
237 if (type_is_signed(data->type) && get_signed_val(data->type, rhs) == -1)
238 pr_err("division of %s by -1 cannot be represented in type %s\n",
239 rhs_val_str, data->type->type_name);
240 else
241 pr_err("division by zero\n");
242
ce5c31db 243 ubsan_epilogue();
c6d30853
AR
244}
245EXPORT_SYMBOL(__ubsan_handle_divrem_overflow);
246
42440c1f 247static void handle_null_ptr_deref(struct type_mismatch_data_common *data)
c6d30853 248{
42440c1f 249 if (suppress_report(data->location))
c6d30853
AR
250 return;
251
ef065653 252 ubsan_prologue(data->location, "null-ptr-deref");
c6d30853
AR
253
254 pr_err("%s null pointer of type %s\n",
255 type_check_kinds[data->type_check_kind],
256 data->type->type_name);
257
ce5c31db 258 ubsan_epilogue();
c6d30853
AR
259}
260
42440c1f 261static void handle_misaligned_access(struct type_mismatch_data_common *data,
c6d30853
AR
262 unsigned long ptr)
263{
42440c1f 264 if (suppress_report(data->location))
c6d30853
AR
265 return;
266
ef065653 267 ubsan_prologue(data->location, "misaligned-access");
c6d30853
AR
268
269 pr_err("%s misaligned address %p for type %s\n",
270 type_check_kinds[data->type_check_kind],
271 (void *)ptr, data->type->type_name);
272 pr_err("which requires %ld byte alignment\n", data->alignment);
273
ce5c31db 274 ubsan_epilogue();
c6d30853
AR
275}
276
42440c1f 277static void handle_object_size_mismatch(struct type_mismatch_data_common *data,
c6d30853
AR
278 unsigned long ptr)
279{
42440c1f 280 if (suppress_report(data->location))
c6d30853
AR
281 return;
282
ef065653 283 ubsan_prologue(data->location, "object-size-mismatch");
901d805c 284 pr_err("%s address %p with insufficient space\n",
c6d30853
AR
285 type_check_kinds[data->type_check_kind],
286 (void *) ptr);
287 pr_err("for an object of type %s\n", data->type->type_name);
ce5c31db 288 ubsan_epilogue();
c6d30853
AR
289}
290
42440c1f 291static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data,
c6d30853
AR
292 unsigned long ptr)
293{
d08965a2 294 unsigned long flags = user_access_save();
c6d30853
AR
295
296 if (!ptr)
297 handle_null_ptr_deref(data);
298 else if (data->alignment && !IS_ALIGNED(ptr, data->alignment))
b8fe1120 299 handle_misaligned_access(data, ptr);
c6d30853
AR
300 else
301 handle_object_size_mismatch(data, ptr);
d08965a2
PZ
302
303 user_access_restore(flags);
c6d30853 304}
42440c1f
AR
305
306void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
f0996bc2 307 void *ptr)
42440c1f
AR
308{
309 struct type_mismatch_data_common common_data = {
310 .location = &data->location,
311 .type = data->type,
312 .alignment = data->alignment,
313 .type_check_kind = data->type_check_kind
314 };
315
f0996bc2 316 ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
42440c1f 317}
c6d30853
AR
318EXPORT_SYMBOL(__ubsan_handle_type_mismatch);
319
469cbd01 320void __ubsan_handle_type_mismatch_v1(void *_data, void *ptr)
42440c1f 321{
469cbd01 322 struct type_mismatch_data_v1 *data = _data;
42440c1f
AR
323 struct type_mismatch_data_common common_data = {
324 .location = &data->location,
325 .type = data->type,
326 .alignment = 1UL << data->log_alignment,
327 .type_check_kind = data->type_check_kind
328 };
329
f0996bc2 330 ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
42440c1f
AR
331}
332EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1);
333
469cbd01 334void __ubsan_handle_out_of_bounds(void *_data, void *index)
c6d30853 335{
469cbd01 336 struct out_of_bounds_data *data = _data;
c6d30853
AR
337 char index_str[VALUE_LENGTH];
338
339 if (suppress_report(&data->location))
340 return;
341
ef065653 342 ubsan_prologue(&data->location, "array-index-out-of-bounds");
c6d30853
AR
343
344 val_to_string(index_str, sizeof(index_str), data->index_type, index);
345 pr_err("index %s is out of range for type %s\n", index_str,
346 data->array_type->type_name);
ce5c31db 347 ubsan_epilogue();
c6d30853
AR
348}
349EXPORT_SYMBOL(__ubsan_handle_out_of_bounds);
350
469cbd01 351void __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs)
c6d30853 352{
469cbd01 353 struct shift_out_of_bounds_data *data = _data;
c6d30853
AR
354 struct type_descriptor *rhs_type = data->rhs_type;
355 struct type_descriptor *lhs_type = data->lhs_type;
356 char rhs_str[VALUE_LENGTH];
357 char lhs_str[VALUE_LENGTH];
9a50dcaf 358 unsigned long ua_flags = user_access_save();
c6d30853
AR
359
360 if (suppress_report(&data->location))
9a50dcaf 361 goto out;
c6d30853 362
ef065653 363 ubsan_prologue(&data->location, "shift-out-of-bounds");
c6d30853
AR
364
365 val_to_string(rhs_str, sizeof(rhs_str), rhs_type, rhs);
366 val_to_string(lhs_str, sizeof(lhs_str), lhs_type, lhs);
367
368 if (val_is_negative(rhs_type, rhs))
369 pr_err("shift exponent %s is negative\n", rhs_str);
370
371 else if (get_unsigned_val(rhs_type, rhs) >=
372 type_bit_width(lhs_type))
373 pr_err("shift exponent %s is too large for %u-bit type %s\n",
374 rhs_str,
375 type_bit_width(lhs_type),
376 lhs_type->type_name);
377 else if (val_is_negative(lhs_type, lhs))
378 pr_err("left shift of negative value %s\n",
379 lhs_str);
380 else
381 pr_err("left shift of %s by %s places cannot be"
382 " represented in type %s\n",
383 lhs_str, rhs_str,
384 lhs_type->type_name);
385
ce5c31db 386 ubsan_epilogue();
9a50dcaf
PZ
387out:
388 user_access_restore(ua_flags);
c6d30853
AR
389}
390EXPORT_SYMBOL(__ubsan_handle_shift_out_of_bounds);
391
392
469cbd01 393void __ubsan_handle_builtin_unreachable(void *_data)
c6d30853 394{
469cbd01 395 struct unreachable_data *data = _data;
ef065653 396 ubsan_prologue(&data->location, "unreachable");
c6d30853 397 pr_err("calling __builtin_unreachable()\n");
ce5c31db 398 ubsan_epilogue();
c6d30853
AR
399 panic("can't return from __builtin_unreachable()");
400}
401EXPORT_SYMBOL(__ubsan_handle_builtin_unreachable);
402
469cbd01 403void __ubsan_handle_load_invalid_value(void *_data, void *val)
c6d30853 404{
469cbd01 405 struct invalid_value_data *data = _data;
c6d30853 406 char val_str[VALUE_LENGTH];
f18b0d7e 407 unsigned long ua_flags = user_access_save();
c6d30853
AR
408
409 if (suppress_report(&data->location))
f18b0d7e 410 goto out;
c6d30853 411
ef065653 412 ubsan_prologue(&data->location, "invalid-load");
c6d30853
AR
413
414 val_to_string(val_str, sizeof(val_str), data->type, val);
415
416 pr_err("load of value %s is not a valid value for type %s\n",
417 val_str, data->type->type_name);
418
ce5c31db 419 ubsan_epilogue();
f18b0d7e
PZ
420out:
421 user_access_restore(ua_flags);
c6d30853
AR
422}
423EXPORT_SYMBOL(__ubsan_handle_load_invalid_value);
28abcc96 424
28abcc96
NC
425void __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr,
426 unsigned long align,
427 unsigned long offset)
428{
429 struct alignment_assumption_data *data = _data;
430 unsigned long real_ptr;
431
432 if (suppress_report(&data->location))
433 return;
434
435 ubsan_prologue(&data->location, "alignment-assumption");
436
437 if (offset)
438 pr_err("assumption of %lu byte alignment (with offset of %lu byte) for pointer of type %s failed",
439 align, offset, data->type->type_name);
440 else
441 pr_err("assumption of %lu byte alignment for pointer of type %s failed",
442 align, data->type->type_name);
443
444 real_ptr = ptr - offset;
445 pr_err("%saddress is %lu aligned, misalignment offset is %lu bytes",
446 offset ? "offset " : "", BIT(real_ptr ? __ffs(real_ptr) : 0),
447 real_ptr & (align - 1));
448
449 ubsan_epilogue();
450}
451EXPORT_SYMBOL(__ubsan_handle_alignment_assumption);
25b84002
KC
452
453#endif /* !CONFIG_UBSAN_TRAP */