]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - lib/ubsan.c
Merge remote-tracking branch 'torvalds/master' into perf/core
[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
469cbd01 166void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs)
c6d30853 167{
469cbd01 168 struct overflow_data *data = _data;
c6d30853
AR
169 char rhs_val_str[VALUE_LENGTH];
170
171 if (suppress_report(&data->location))
172 return;
173
ef065653 174 ubsan_prologue(&data->location, "division-overflow");
c6d30853
AR
175
176 val_to_string(rhs_val_str, sizeof(rhs_val_str), data->type, rhs);
177
178 if (type_is_signed(data->type) && get_signed_val(data->type, rhs) == -1)
179 pr_err("division of %s by -1 cannot be represented in type %s\n",
180 rhs_val_str, data->type->type_name);
181 else
182 pr_err("division by zero\n");
183
ce5c31db 184 ubsan_epilogue();
c6d30853
AR
185}
186EXPORT_SYMBOL(__ubsan_handle_divrem_overflow);
187
42440c1f 188static void handle_null_ptr_deref(struct type_mismatch_data_common *data)
c6d30853 189{
42440c1f 190 if (suppress_report(data->location))
c6d30853
AR
191 return;
192
ef065653 193 ubsan_prologue(data->location, "null-ptr-deref");
c6d30853
AR
194
195 pr_err("%s null pointer of type %s\n",
196 type_check_kinds[data->type_check_kind],
197 data->type->type_name);
198
ce5c31db 199 ubsan_epilogue();
c6d30853
AR
200}
201
42440c1f 202static void handle_misaligned_access(struct type_mismatch_data_common *data,
c6d30853
AR
203 unsigned long ptr)
204{
42440c1f 205 if (suppress_report(data->location))
c6d30853
AR
206 return;
207
ef065653 208 ubsan_prologue(data->location, "misaligned-access");
c6d30853
AR
209
210 pr_err("%s misaligned address %p for type %s\n",
211 type_check_kinds[data->type_check_kind],
212 (void *)ptr, data->type->type_name);
213 pr_err("which requires %ld byte alignment\n", data->alignment);
214
ce5c31db 215 ubsan_epilogue();
c6d30853
AR
216}
217
42440c1f 218static void handle_object_size_mismatch(struct type_mismatch_data_common *data,
c6d30853
AR
219 unsigned long ptr)
220{
42440c1f 221 if (suppress_report(data->location))
c6d30853
AR
222 return;
223
ef065653 224 ubsan_prologue(data->location, "object-size-mismatch");
901d805c 225 pr_err("%s address %p with insufficient space\n",
c6d30853
AR
226 type_check_kinds[data->type_check_kind],
227 (void *) ptr);
228 pr_err("for an object of type %s\n", data->type->type_name);
ce5c31db 229 ubsan_epilogue();
c6d30853
AR
230}
231
42440c1f 232static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data,
c6d30853
AR
233 unsigned long ptr)
234{
d08965a2 235 unsigned long flags = user_access_save();
c6d30853
AR
236
237 if (!ptr)
238 handle_null_ptr_deref(data);
239 else if (data->alignment && !IS_ALIGNED(ptr, data->alignment))
b8fe1120 240 handle_misaligned_access(data, ptr);
c6d30853
AR
241 else
242 handle_object_size_mismatch(data, ptr);
d08965a2
PZ
243
244 user_access_restore(flags);
c6d30853 245}
42440c1f
AR
246
247void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
f0996bc2 248 void *ptr)
42440c1f
AR
249{
250 struct type_mismatch_data_common common_data = {
251 .location = &data->location,
252 .type = data->type,
253 .alignment = data->alignment,
254 .type_check_kind = data->type_check_kind
255 };
256
f0996bc2 257 ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
42440c1f 258}
c6d30853
AR
259EXPORT_SYMBOL(__ubsan_handle_type_mismatch);
260
469cbd01 261void __ubsan_handle_type_mismatch_v1(void *_data, void *ptr)
42440c1f 262{
469cbd01 263 struct type_mismatch_data_v1 *data = _data;
42440c1f
AR
264 struct type_mismatch_data_common common_data = {
265 .location = &data->location,
266 .type = data->type,
267 .alignment = 1UL << data->log_alignment,
268 .type_check_kind = data->type_check_kind
269 };
270
f0996bc2 271 ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
42440c1f
AR
272}
273EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1);
274
469cbd01 275void __ubsan_handle_out_of_bounds(void *_data, void *index)
c6d30853 276{
469cbd01 277 struct out_of_bounds_data *data = _data;
c6d30853
AR
278 char index_str[VALUE_LENGTH];
279
280 if (suppress_report(&data->location))
281 return;
282
ef065653 283 ubsan_prologue(&data->location, "array-index-out-of-bounds");
c6d30853
AR
284
285 val_to_string(index_str, sizeof(index_str), data->index_type, index);
286 pr_err("index %s is out of range for type %s\n", index_str,
287 data->array_type->type_name);
ce5c31db 288 ubsan_epilogue();
c6d30853
AR
289}
290EXPORT_SYMBOL(__ubsan_handle_out_of_bounds);
291
469cbd01 292void __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs)
c6d30853 293{
469cbd01 294 struct shift_out_of_bounds_data *data = _data;
c6d30853
AR
295 struct type_descriptor *rhs_type = data->rhs_type;
296 struct type_descriptor *lhs_type = data->lhs_type;
297 char rhs_str[VALUE_LENGTH];
298 char lhs_str[VALUE_LENGTH];
9a50dcaf 299 unsigned long ua_flags = user_access_save();
c6d30853
AR
300
301 if (suppress_report(&data->location))
9a50dcaf 302 goto out;
c6d30853 303
ef065653 304 ubsan_prologue(&data->location, "shift-out-of-bounds");
c6d30853
AR
305
306 val_to_string(rhs_str, sizeof(rhs_str), rhs_type, rhs);
307 val_to_string(lhs_str, sizeof(lhs_str), lhs_type, lhs);
308
309 if (val_is_negative(rhs_type, rhs))
310 pr_err("shift exponent %s is negative\n", rhs_str);
311
312 else if (get_unsigned_val(rhs_type, rhs) >=
313 type_bit_width(lhs_type))
314 pr_err("shift exponent %s is too large for %u-bit type %s\n",
315 rhs_str,
316 type_bit_width(lhs_type),
317 lhs_type->type_name);
318 else if (val_is_negative(lhs_type, lhs))
319 pr_err("left shift of negative value %s\n",
320 lhs_str);
321 else
322 pr_err("left shift of %s by %s places cannot be"
323 " represented in type %s\n",
324 lhs_str, rhs_str,
325 lhs_type->type_name);
326
ce5c31db 327 ubsan_epilogue();
9a50dcaf
PZ
328out:
329 user_access_restore(ua_flags);
c6d30853
AR
330}
331EXPORT_SYMBOL(__ubsan_handle_shift_out_of_bounds);
332
333
469cbd01 334void __ubsan_handle_builtin_unreachable(void *_data)
c6d30853 335{
469cbd01 336 struct unreachable_data *data = _data;
ef065653 337 ubsan_prologue(&data->location, "unreachable");
c6d30853 338 pr_err("calling __builtin_unreachable()\n");
ce5c31db 339 ubsan_epilogue();
c6d30853
AR
340 panic("can't return from __builtin_unreachable()");
341}
342EXPORT_SYMBOL(__ubsan_handle_builtin_unreachable);
343
469cbd01 344void __ubsan_handle_load_invalid_value(void *_data, void *val)
c6d30853 345{
469cbd01 346 struct invalid_value_data *data = _data;
c6d30853
AR
347 char val_str[VALUE_LENGTH];
348
349 if (suppress_report(&data->location))
350 return;
351
ef065653 352 ubsan_prologue(&data->location, "invalid-load");
c6d30853
AR
353
354 val_to_string(val_str, sizeof(val_str), data->type, val);
355
356 pr_err("load of value %s is not a valid value for type %s\n",
357 val_str, data->type->type_name);
358
ce5c31db 359 ubsan_epilogue();
c6d30853
AR
360}
361EXPORT_SYMBOL(__ubsan_handle_load_invalid_value);
28abcc96
NC
362
363void __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr,
364 unsigned long align,
365 unsigned long offset);
366void __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr,
367 unsigned long align,
368 unsigned long offset)
369{
370 struct alignment_assumption_data *data = _data;
371 unsigned long real_ptr;
372
373 if (suppress_report(&data->location))
374 return;
375
376 ubsan_prologue(&data->location, "alignment-assumption");
377
378 if (offset)
379 pr_err("assumption of %lu byte alignment (with offset of %lu byte) for pointer of type %s failed",
380 align, offset, data->type->type_name);
381 else
382 pr_err("assumption of %lu byte alignment for pointer of type %s failed",
383 align, data->type->type_name);
384
385 real_ptr = ptr - offset;
386 pr_err("%saddress is %lu aligned, misalignment offset is %lu bytes",
387 offset ? "offset " : "", BIT(real_ptr ? __ffs(real_ptr) : 0),
388 real_ptr & (align - 1));
389
390 ubsan_epilogue();
391}
392EXPORT_SYMBOL(__ubsan_handle_alignment_assumption);