Merge tag 'for-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pateldipen19...
[linux-block.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
AR
206
207 pr_err("========================================"
208 "========================================\n");
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();
218 pr_err("========================================"
219 "========================================\n");
ce5c31db 220
c6d30853 221 current->in_ubsan--;
1d28c8d6 222
79cc1ba7 223 check_panic_on_warn("UBSAN");
c6d30853
AR
224}
225
469cbd01 226void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs)
c6d30853 227{
469cbd01 228 struct overflow_data *data = _data;
c6d30853
AR
229 char rhs_val_str[VALUE_LENGTH];
230
231 if (suppress_report(&data->location))
232 return;
233
ef065653 234 ubsan_prologue(&data->location, "division-overflow");
c6d30853
AR
235
236 val_to_string(rhs_val_str, sizeof(rhs_val_str), data->type, rhs);
237
238 if (type_is_signed(data->type) && get_signed_val(data->type, rhs) == -1)
239 pr_err("division of %s by -1 cannot be represented in type %s\n",
240 rhs_val_str, data->type->type_name);
241 else
242 pr_err("division by zero\n");
243
ce5c31db 244 ubsan_epilogue();
c6d30853
AR
245}
246EXPORT_SYMBOL(__ubsan_handle_divrem_overflow);
247
42440c1f 248static void handle_null_ptr_deref(struct type_mismatch_data_common *data)
c6d30853 249{
42440c1f 250 if (suppress_report(data->location))
c6d30853
AR
251 return;
252
ef065653 253 ubsan_prologue(data->location, "null-ptr-deref");
c6d30853
AR
254
255 pr_err("%s null pointer of type %s\n",
256 type_check_kinds[data->type_check_kind],
257 data->type->type_name);
258
ce5c31db 259 ubsan_epilogue();
c6d30853
AR
260}
261
42440c1f 262static void handle_misaligned_access(struct type_mismatch_data_common *data,
c6d30853
AR
263 unsigned long ptr)
264{
42440c1f 265 if (suppress_report(data->location))
c6d30853
AR
266 return;
267
ef065653 268 ubsan_prologue(data->location, "misaligned-access");
c6d30853
AR
269
270 pr_err("%s misaligned address %p for type %s\n",
271 type_check_kinds[data->type_check_kind],
272 (void *)ptr, data->type->type_name);
273 pr_err("which requires %ld byte alignment\n", data->alignment);
274
ce5c31db 275 ubsan_epilogue();
c6d30853
AR
276}
277
42440c1f 278static void handle_object_size_mismatch(struct type_mismatch_data_common *data,
c6d30853
AR
279 unsigned long ptr)
280{
42440c1f 281 if (suppress_report(data->location))
c6d30853
AR
282 return;
283
ef065653 284 ubsan_prologue(data->location, "object-size-mismatch");
901d805c 285 pr_err("%s address %p with insufficient space\n",
c6d30853
AR
286 type_check_kinds[data->type_check_kind],
287 (void *) ptr);
288 pr_err("for an object of type %s\n", data->type->type_name);
ce5c31db 289 ubsan_epilogue();
c6d30853
AR
290}
291
42440c1f 292static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data,
c6d30853
AR
293 unsigned long ptr)
294{
d08965a2 295 unsigned long flags = user_access_save();
c6d30853
AR
296
297 if (!ptr)
298 handle_null_ptr_deref(data);
299 else if (data->alignment && !IS_ALIGNED(ptr, data->alignment))
b8fe1120 300 handle_misaligned_access(data, ptr);
c6d30853
AR
301 else
302 handle_object_size_mismatch(data, ptr);
d08965a2
PZ
303
304 user_access_restore(flags);
c6d30853 305}
42440c1f
AR
306
307void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
f0996bc2 308 void *ptr)
42440c1f
AR
309{
310 struct type_mismatch_data_common common_data = {
311 .location = &data->location,
312 .type = data->type,
313 .alignment = data->alignment,
314 .type_check_kind = data->type_check_kind
315 };
316
f0996bc2 317 ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
42440c1f 318}
c6d30853
AR
319EXPORT_SYMBOL(__ubsan_handle_type_mismatch);
320
469cbd01 321void __ubsan_handle_type_mismatch_v1(void *_data, void *ptr)
42440c1f 322{
469cbd01 323 struct type_mismatch_data_v1 *data = _data;
42440c1f
AR
324 struct type_mismatch_data_common common_data = {
325 .location = &data->location,
326 .type = data->type,
327 .alignment = 1UL << data->log_alignment,
328 .type_check_kind = data->type_check_kind
329 };
330
f0996bc2 331 ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
42440c1f
AR
332}
333EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1);
334
469cbd01 335void __ubsan_handle_out_of_bounds(void *_data, void *index)
c6d30853 336{
469cbd01 337 struct out_of_bounds_data *data = _data;
c6d30853
AR
338 char index_str[VALUE_LENGTH];
339
340 if (suppress_report(&data->location))
341 return;
342
ef065653 343 ubsan_prologue(&data->location, "array-index-out-of-bounds");
c6d30853
AR
344
345 val_to_string(index_str, sizeof(index_str), data->index_type, index);
346 pr_err("index %s is out of range for type %s\n", index_str,
347 data->array_type->type_name);
ce5c31db 348 ubsan_epilogue();
c6d30853
AR
349}
350EXPORT_SYMBOL(__ubsan_handle_out_of_bounds);
351
469cbd01 352void __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs)
c6d30853 353{
469cbd01 354 struct shift_out_of_bounds_data *data = _data;
c6d30853
AR
355 struct type_descriptor *rhs_type = data->rhs_type;
356 struct type_descriptor *lhs_type = data->lhs_type;
357 char rhs_str[VALUE_LENGTH];
358 char lhs_str[VALUE_LENGTH];
9a50dcaf 359 unsigned long ua_flags = user_access_save();
c6d30853
AR
360
361 if (suppress_report(&data->location))
9a50dcaf 362 goto out;
c6d30853 363
ef065653 364 ubsan_prologue(&data->location, "shift-out-of-bounds");
c6d30853
AR
365
366 val_to_string(rhs_str, sizeof(rhs_str), rhs_type, rhs);
367 val_to_string(lhs_str, sizeof(lhs_str), lhs_type, lhs);
368
369 if (val_is_negative(rhs_type, rhs))
370 pr_err("shift exponent %s is negative\n", rhs_str);
371
372 else if (get_unsigned_val(rhs_type, rhs) >=
373 type_bit_width(lhs_type))
374 pr_err("shift exponent %s is too large for %u-bit type %s\n",
375 rhs_str,
376 type_bit_width(lhs_type),
377 lhs_type->type_name);
378 else if (val_is_negative(lhs_type, lhs))
379 pr_err("left shift of negative value %s\n",
380 lhs_str);
381 else
382 pr_err("left shift of %s by %s places cannot be"
383 " represented in type %s\n",
384 lhs_str, rhs_str,
385 lhs_type->type_name);
386
ce5c31db 387 ubsan_epilogue();
9a50dcaf
PZ
388out:
389 user_access_restore(ua_flags);
c6d30853
AR
390}
391EXPORT_SYMBOL(__ubsan_handle_shift_out_of_bounds);
392
393
469cbd01 394void __ubsan_handle_builtin_unreachable(void *_data)
c6d30853 395{
469cbd01 396 struct unreachable_data *data = _data;
ef065653 397 ubsan_prologue(&data->location, "unreachable");
c6d30853 398 pr_err("calling __builtin_unreachable()\n");
ce5c31db 399 ubsan_epilogue();
c6d30853
AR
400 panic("can't return from __builtin_unreachable()");
401}
402EXPORT_SYMBOL(__ubsan_handle_builtin_unreachable);
403
469cbd01 404void __ubsan_handle_load_invalid_value(void *_data, void *val)
c6d30853 405{
469cbd01 406 struct invalid_value_data *data = _data;
c6d30853 407 char val_str[VALUE_LENGTH];
f18b0d7e 408 unsigned long ua_flags = user_access_save();
c6d30853
AR
409
410 if (suppress_report(&data->location))
f18b0d7e 411 goto out;
c6d30853 412
ef065653 413 ubsan_prologue(&data->location, "invalid-load");
c6d30853
AR
414
415 val_to_string(val_str, sizeof(val_str), data->type, val);
416
417 pr_err("load of value %s is not a valid value for type %s\n",
418 val_str, data->type->type_name);
419
ce5c31db 420 ubsan_epilogue();
f18b0d7e
PZ
421out:
422 user_access_restore(ua_flags);
c6d30853
AR
423}
424EXPORT_SYMBOL(__ubsan_handle_load_invalid_value);
28abcc96
NC
425
426void __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr,
427 unsigned long align,
428 unsigned long offset);
429void __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr,
430 unsigned long align,
431 unsigned long offset)
432{
433 struct alignment_assumption_data *data = _data;
434 unsigned long real_ptr;
435
436 if (suppress_report(&data->location))
437 return;
438
439 ubsan_prologue(&data->location, "alignment-assumption");
440
441 if (offset)
442 pr_err("assumption of %lu byte alignment (with offset of %lu byte) for pointer of type %s failed",
443 align, offset, data->type->type_name);
444 else
445 pr_err("assumption of %lu byte alignment for pointer of type %s failed",
446 align, data->type->type_name);
447
448 real_ptr = ptr - offset;
449 pr_err("%saddress is %lu aligned, misalignment offset is %lu bytes",
450 offset ? "offset " : "", BIT(real_ptr ? __ffs(real_ptr) : 0),
451 real_ptr & (align - 1));
452
453 ubsan_epilogue();
454}
455EXPORT_SYMBOL(__ubsan_handle_alignment_assumption);
25b84002
KC
456
457#endif /* !CONFIG_UBSAN_TRAP */