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