coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
ubsan.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: ISC */
2 /* ubsan/ubsan.c
3  * Undefined behavior sanitizer runtime support.
4  *
5  * Adapted from:
6  * https://gitlab.com/sortix/sortix/raw/master/libc/ubsan/ubsan.c
7  */
8 
9 #include <stdint.h>
10 #include <console/console.h>
11 
13  const char *filename;
16 };
17 
21  char type_name[];
22 };
23 
25 
26 /*
27 * Keep the compiler happy -- it wants prototypes but nobody
28 * except the compiler should be touching these functions.
29 */
30 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
31 
32 static void __noreturn ubsan_abort(const struct ubsan_source_location *location,
33  const char *violation) {
34  static const struct ubsan_source_location unknown_location = {
35  "<unknown file>",
36  0,
37  0,
38  };
39 
40  if (!location || !location->filename)
41  location = &unknown_location;
42  printk(BIOS_ERR, "%s %s:%lu:%lu\n", violation, location->filename,
43  (unsigned long int)location->line,
44  (unsigned long int)location->column);
45  die("ubsan: unrecoverable error.\n");
46 }
47 
48 #define ABORT_VARIANT(name, params, call) \
49  __noreturn void __ubsan_handle_##name##_abort params; \
50  __noreturn void __ubsan_handle_##name##_abort params { \
51  __ubsan_handle_##name call; \
52  __builtin_unreachable(); \
53  }
54 
55 #define ABORT_VARIANT_VP(name) \
56  ABORT_VARIANT(name, (void *a), (a))
57 #define ABORT_VARIANT_VP_VP(name) \
58  ABORT_VARIANT(name, (void *a, void *b), (a, b))
59 #define ABORT_VARIANT_VP_IP(name) \
60  ABORT_VARIANT(name, (void *a, intptr_t b), (a, b))
61 #define ABORT_VARIANT_VP_VP_VP(name) \
62  ABORT_VARIANT(name, (void *a, void *b, void *c), (a, b, c))
63 
68  unsigned char type_check_kind;
69 };
70 
71 void __ubsan_handle_type_mismatch_v1(void *data_raw, void *pointer_raw)
72 {
73  const struct ubsan_type_mismatch_data *data =
74  (struct ubsan_type_mismatch_data *)data_raw;
75  ubsan_value_handle_t pointer = (ubsan_value_handle_t)pointer_raw;
76  const char *violation = "type mismatch";
77  if (!pointer)
78  violation = "null pointer access";
79  else if (data->alignment && (pointer & (data->alignment - 1)))
80  violation = "unaligned access";
81  ubsan_abort(&data->location, violation);
82 }
83 
84 ABORT_VARIANT_VP_VP(type_mismatch_v1);
85 
89 };
90 
91 void __ubsan_handle_add_overflow(void *data_raw, void *lhs_raw,
92  void *rhs_raw)
93 {
94  const struct ubsan_overflow_data *data
95  = (struct ubsan_overflow_data *)data_raw;
98  (void)lhs;
99  (void)rhs;
100  ubsan_abort(&data->location, "addition overflow");
101 }
102 
104 
105 void __ubsan_handle_sub_overflow(void *data_raw, void *lhs_raw,
106  void *rhs_raw)
107 {
108  const struct ubsan_overflow_data *data
109  = (struct ubsan_overflow_data *)data_raw;
112  (void)lhs;
113  (void)rhs;
114  ubsan_abort(&data->location, "subtraction overflow");
115 }
116 
118 
119 void __ubsan_handle_mul_overflow(void *data_raw, void *lhs_raw,
120  void *rhs_raw)
121 {
122  const struct ubsan_overflow_data *data
123  = (struct ubsan_overflow_data *)data_raw;
126  (void)lhs;
127  (void)rhs;
128  ubsan_abort(&data->location, "multiplication overflow");
129 }
130 
132 
133 void __ubsan_handle_negate_overflow(void *data_raw, void *old_value_raw)
134 {
135  const struct ubsan_overflow_data *data
136  = (struct ubsan_overflow_data *)data_raw;
137  ubsan_value_handle_t old_value
138  = (ubsan_value_handle_t)old_value_raw;
139  (void) old_value;
140  ubsan_abort(&data->location, "negation overflow");
141 }
142 
143 ABORT_VARIANT_VP_VP(negate_overflow);
144 
145 void __ubsan_handle_divrem_overflow(void *data_raw, void *lhs_raw,
146  void *rhs_raw)
147 {
148  const struct ubsan_overflow_data *data
149  = (struct ubsan_overflow_data *)data_raw;
152  (void)lhs;
153  (void)rhs;
154  ubsan_abort(&data->location, "division remainder overflow");
155 }
156 
157 ABORT_VARIANT_VP_VP_VP(divrem_overflow);
158 
161 };
162 
163 void __ubsan_handle_pointer_overflow(void *data_raw, void *base_raw, void *result_raw)
164 {
165  const struct ubsan_pointer_overflow_data *data =
166  (struct ubsan_pointer_overflow_data *)data_raw;
169  (void)base;
170  (void)result;
171  ubsan_abort(&data->location, "pointer overflow");
172 }
173 
174 ABORT_VARIANT_VP_VP_VP(pointer_overflow);
175 
180 };
181 
182 void __ubsan_handle_shift_out_of_bounds(void *data_raw, void *lhs_raw,
183  void *rhs_raw)
184 {
185  const struct ubsan_shift_out_of_bounds_data *data =
186  (struct ubsan_shift_out_of_bounds_data *)data_raw;
189  (void)lhs;
190  (void)rhs;
191  ubsan_abort(&data->location, "shift out of bounds");
192 }
193 
194 ABORT_VARIANT_VP_VP_VP(shift_out_of_bounds);
195 
200 };
201 
202 void __ubsan_handle_out_of_bounds(void *data_raw, void *index_raw)
203 {
204  const struct ubsan_out_of_bounds_data *data =
205  (struct ubsan_out_of_bounds_data *)data_raw;
206  ubsan_value_handle_t index = (ubsan_value_handle_t)index_raw;
207  (void)index;
208  ubsan_abort(&data->location, "out of bounds");
209 }
210 
211 ABORT_VARIANT_VP_VP(out_of_bounds);
212 
215 };
216 
218 {
219  struct ubsan_unreachable_data *data =
220  (struct ubsan_unreachable_data *)data_raw;
221  ubsan_abort(&data->location, "reached unreachable");
222 }
223 
225 {
226  const struct ubsan_unreachable_data *data =
227  (struct ubsan_unreachable_data *)data_raw;
228  ubsan_abort(&data->location, "missing return");
229 }
230 
234 };
235 
236 void __ubsan_handle_vla_bound_not_positive(void *data_raw, void *bound_raw)
237 {
238  const struct ubsan_vla_bound_data *data
239  = (struct ubsan_vla_bound_data *)data_raw;
240  ubsan_value_handle_t bound = (ubsan_value_handle_t)bound_raw;
241  (void)bound;
242  ubsan_abort(&data->location, "negative variable array length");
243 }
244 
245 ABORT_VARIANT_VP_VP(vla_bound_not_positive);
246 
251 };
252 
253 void __ubsan_handle_float_cast_overflow(void *data_raw, void *from_raw)
254 {
255  struct ubsan_float_cast_overflow_data *data =
256  (struct ubsan_float_cast_overflow_data *)data_raw;
258  (void) from;
259  ubsan_abort(&data->location, "float cast overflow");
260 }
261 
262 ABORT_VARIANT_VP_VP(float_cast_overflow);
263 
267 };
268 
269 void __ubsan_handle_load_invalid_value(void *data_raw, void *value_raw)
270 {
271  const struct ubsan_invalid_value_data *data =
272  (struct ubsan_invalid_value_data *)data_raw;
274  (void)value;
275  ubsan_abort(&data->location, "invalid value load");
276 }
277 
278 ABORT_VARIANT_VP_VP(load_invalid_value);
279 
283 };
284 
285 void __ubsan_handle_function_type_mismatch(void *data_raw, void *value_raw)
286 {
287  const struct ubsan_function_type_mismatch_data *data =
288  (struct ubsan_function_type_mismatch_data *)data_raw;
290  (void)value;
291  ubsan_abort(&data->location, "function type mismatch");
292 }
293 
294 ABORT_VARIANT_VP_VP(function_type_mismatch);
295 
299 };
300 
301 void __ubsan_handle_nonnull_return(void *data_raw)
302 {
303  const struct ubsan_nonnull_return_data *data =
304  (struct ubsan_nonnull_return_data *)data_raw;
305  ubsan_abort(&data->location, "null return");
306 }
307 
308 ABORT_VARIANT_VP(nonnull_return);
309 
313 };
314 
315 /*
316 * TODO: GCC's libubsan does not have the second parameter, but its builtin
317 * somehow has it and conflict if we don't match it.
318 */
319 void __ubsan_handle_nonnull_arg(void *data_raw, intptr_t index_raw)
320 {
321  const struct ubsan_nonnull_arg_data *data =
322  (struct ubsan_nonnull_arg_data *)data_raw;
323  ubsan_value_handle_t index = (ubsan_value_handle_t)index_raw;
324  (void)index;
325  ubsan_abort(&data->location, "null argument");
326 }
327 
328 ABORT_VARIANT_VP_IP(nonnull_arg);
329 
333 };
334 
335 void __ubsan_handle_cfi_bad_icall(void *data_raw, void *value_raw)
336 {
337  static const char *abort_text
338  = "cfi: integrity failure during indirect call.";
339  const struct ubsan_cfi_bad_icall_data *data =
340  (struct ubsan_cfi_bad_icall_data *)data_raw;
342  (void)value;
343  ubsan_abort(&data->location, abort_text);
344 }
345 
346 ABORT_VARIANT_VP_VP(cfi_bad_icall);
pte_t value
Definition: mmu.c:91
#define printk(level,...)
Definition: stdlib.h:16
#define __noreturn
Definition: compiler.h:31
void __noreturn die(const char *fmt,...)
Definition: die.c:17
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
result
Definition: mrc_cache.c:35
uintptr_t base
Definition: uart.c:17
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
signed long intptr_t
Definition: stdint.h:20
unsigned long uintptr_t
Definition: stdint.h:21
struct ubsan_type_descriptor * type
Definition: ubsan.c:332
struct ubsan_source_location location
Definition: ubsan.c:331
struct ubsan_type_descriptor * from_type
Definition: ubsan.c:249
struct ubsan_type_descriptor * to_type
Definition: ubsan.c:250
struct ubsan_source_location location
Definition: ubsan.c:248
struct ubsan_source_location location
Definition: ubsan.c:281
struct ubsan_type_descriptor * type
Definition: ubsan.c:282
struct ubsan_source_location location
Definition: ubsan.c:265
struct ubsan_type_descriptor * type
Definition: ubsan.c:266
struct ubsan_source_location location
Definition: ubsan.c:311
struct ubsan_source_location attr_location
Definition: ubsan.c:312
struct ubsan_source_location attr_location
Definition: ubsan.c:298
struct ubsan_source_location location
Definition: ubsan.c:297
struct ubsan_type_descriptor * index_type
Definition: ubsan.c:199
struct ubsan_source_location location
Definition: ubsan.c:197
struct ubsan_type_descriptor * array_type
Definition: ubsan.c:198
struct ubsan_type_descriptor * type
Definition: ubsan.c:88
struct ubsan_source_location location
Definition: ubsan.c:87
struct ubsan_source_location location
Definition: ubsan.c:160
struct ubsan_source_location location
Definition: ubsan.c:177
struct ubsan_type_descriptor * rhs_type
Definition: ubsan.c:179
struct ubsan_type_descriptor * lhs_type
Definition: ubsan.c:178
const char * filename
Definition: ubsan.c:13
uint32_t line
Definition: ubsan.c:14
uint32_t column
Definition: ubsan.c:15
uint16_t type_info
Definition: ubsan.c:20
uint16_t type_kind
Definition: ubsan.c:19
char type_name[]
Definition: ubsan.c:21
unsigned char type_check_kind
Definition: ubsan.c:68
struct ubsan_type_descriptor * type
Definition: ubsan.c:66
uintptr_t alignment
Definition: ubsan.c:67
struct ubsan_source_location location
Definition: ubsan.c:65
struct ubsan_source_location location
Definition: ubsan.c:214
struct ubsan_type_descriptor * type
Definition: ubsan.c:233
struct ubsan_source_location location
Definition: ubsan.c:232
void __ubsan_handle_float_cast_overflow(void *data_raw, void *from_raw)
Definition: ubsan.c:253
void __ubsan_handle_pointer_overflow(void *data_raw, void *base_raw, void *result_raw)
Definition: ubsan.c:163
void __ubsan_handle_mul_overflow(void *data_raw, void *lhs_raw, void *rhs_raw)
Definition: ubsan.c:119
void __ubsan_handle_shift_out_of_bounds(void *data_raw, void *lhs_raw, void *rhs_raw)
Definition: ubsan.c:182
void __ubsan_handle_add_overflow(void *data_raw, void *lhs_raw, void *rhs_raw)
Definition: ubsan.c:91
void __ubsan_handle_sub_overflow(void *data_raw, void *lhs_raw, void *rhs_raw)
Definition: ubsan.c:105
#define ABORT_VARIANT_VP_VP_VP(name)
Definition: ubsan.c:61
void __ubsan_handle_nonnull_return(void *data_raw)
Definition: ubsan.c:301
#define ABORT_VARIANT_VP(name)
Definition: ubsan.c:55
void __noreturn __ubsan_handle_missing_return(void *data_raw)
Definition: ubsan.c:224
void __ubsan_handle_type_mismatch_v1(void *data_raw, void *pointer_raw)
Definition: ubsan.c:71
void __ubsan_handle_negate_overflow(void *data_raw, void *old_value_raw)
Definition: ubsan.c:133
void __ubsan_handle_cfi_bad_icall(void *data_raw, void *value_raw)
Definition: ubsan.c:335
#define ABORT_VARIANT_VP_VP(name)
Definition: ubsan.c:57
void __ubsan_handle_divrem_overflow(void *data_raw, void *lhs_raw, void *rhs_raw)
Definition: ubsan.c:145
uintptr_t ubsan_value_handle_t
Definition: ubsan.c:24
#define ABORT_VARIANT_VP_IP(name)
Definition: ubsan.c:59
void __ubsan_handle_out_of_bounds(void *data_raw, void *index_raw)
Definition: ubsan.c:202
void __ubsan_handle_nonnull_arg(void *data_raw, intptr_t index_raw)
Definition: ubsan.c:319
static void __noreturn ubsan_abort(const struct ubsan_source_location *location, const char *violation)
Definition: ubsan.c:32
void __ubsan_handle_vla_bound_not_positive(void *data_raw, void *bound_raw)
Definition: ubsan.c:236
void __noreturn __ubsan_handle_builtin_unreachable(void *data_raw)
Definition: ubsan.c:217
void __ubsan_handle_function_type_mismatch(void *data_raw, void *value_raw)
Definition: ubsan.c:285
void __ubsan_handle_load_invalid_value(void *data_raw, void *value_raw)
Definition: ubsan.c:269
typedef void(X86APIP X86EMU_intrFuncs)(int num)