1ff3ed644SAleksandr Iashchenko // SPDX-License-Identifier: BSD-2-Clause
2ff3ed644SAleksandr Iashchenko /*
3ff3ed644SAleksandr Iashchenko * Copyright (c) 2016, Linaro Limited
4ff3ed644SAleksandr Iashchenko */
5ff3ed644SAleksandr Iashchenko
6*fa1190c6SAleksandr Iashchenko #include <atomic.h>
7ff3ed644SAleksandr Iashchenko #include <compiler.h>
8ff3ed644SAleksandr Iashchenko #include <string.h>
9ff3ed644SAleksandr Iashchenko #include <trace.h>
10ff3ed644SAleksandr Iashchenko #include <types_ext.h>
11*fa1190c6SAleksandr Iashchenko #include <util.h>
12ff3ed644SAleksandr Iashchenko
13ff3ed644SAleksandr Iashchenko #if defined(__KERNEL__)
14ff3ed644SAleksandr Iashchenko # include <kernel/panic.h>
15ff3ed644SAleksandr Iashchenko #elif defined(__LDELF__)
16ff3ed644SAleksandr Iashchenko # include <ldelf_syscalls.h>
17ff3ed644SAleksandr Iashchenko #else
18949b0c0cSAleksandr Iashchenko # include <utee_syscalls.h>
19ff3ed644SAleksandr Iashchenko #endif
20ff3ed644SAleksandr Iashchenko
21*fa1190c6SAleksandr Iashchenko #define UBSAN_LOC_REPORTED BIT32(31)
22*fa1190c6SAleksandr Iashchenko
23ff3ed644SAleksandr Iashchenko struct source_location {
24ff3ed644SAleksandr Iashchenko const char *file_name;
25ff3ed644SAleksandr Iashchenko uint32_t line;
26ff3ed644SAleksandr Iashchenko uint32_t column;
27ff3ed644SAleksandr Iashchenko };
28ff3ed644SAleksandr Iashchenko
ubsan_panic(void)29ff3ed644SAleksandr Iashchenko static void __noreturn ubsan_panic(void)
30ff3ed644SAleksandr Iashchenko {
31ff3ed644SAleksandr Iashchenko #if defined(__KERNEL__)
32ff3ed644SAleksandr Iashchenko panic();
33ff3ed644SAleksandr Iashchenko #elif defined(__LDELF__)
34ff3ed644SAleksandr Iashchenko _ldelf_panic(2);
35ff3ed644SAleksandr Iashchenko #else
36949b0c0cSAleksandr Iashchenko _utee_panic(TEE_ERROR_GENERIC);
37ff3ed644SAleksandr Iashchenko #endif
38ff3ed644SAleksandr Iashchenko /*
39ff3ed644SAleksandr Iashchenko * _ldelf_panic and _utee_panic are not marked as noreturn,
40ff3ed644SAleksandr Iashchenko * however they should be. To prevent "‘noreturn’ function
41ff3ed644SAleksandr Iashchenko * does return" warning the while loop is used.
42ff3ed644SAleksandr Iashchenko */
43ff3ed644SAleksandr Iashchenko while (1)
44ff3ed644SAleksandr Iashchenko ;
45ff3ed644SAleksandr Iashchenko }
46ff3ed644SAleksandr Iashchenko
was_already_reported(struct source_location * loc)47*fa1190c6SAleksandr Iashchenko static bool was_already_reported(struct source_location *loc)
48*fa1190c6SAleksandr Iashchenko {
49*fa1190c6SAleksandr Iashchenko uint32_t column = loc->column;
50*fa1190c6SAleksandr Iashchenko
51*fa1190c6SAleksandr Iashchenko if (column & UBSAN_LOC_REPORTED)
52*fa1190c6SAleksandr Iashchenko return true;
53*fa1190c6SAleksandr Iashchenko
54*fa1190c6SAleksandr Iashchenko return !atomic_cas_u32(&loc->column, &column,
55*fa1190c6SAleksandr Iashchenko column | UBSAN_LOC_REPORTED);
56*fa1190c6SAleksandr Iashchenko }
57*fa1190c6SAleksandr Iashchenko
58ff3ed644SAleksandr Iashchenko struct type_descriptor {
59ff3ed644SAleksandr Iashchenko uint16_t type_kind;
60ff3ed644SAleksandr Iashchenko uint16_t type_info;
61ff3ed644SAleksandr Iashchenko char type_name[1];
62ff3ed644SAleksandr Iashchenko };
63ff3ed644SAleksandr Iashchenko
64ff3ed644SAleksandr Iashchenko struct type_mismatch_data {
65ff3ed644SAleksandr Iashchenko struct source_location loc;
66ff3ed644SAleksandr Iashchenko struct type_descriptor *type;
67ff3ed644SAleksandr Iashchenko unsigned long alignment;
68ff3ed644SAleksandr Iashchenko unsigned char type_check_kind;
69ff3ed644SAleksandr Iashchenko };
70ff3ed644SAleksandr Iashchenko
71ff3ed644SAleksandr Iashchenko struct overflow_data {
72ff3ed644SAleksandr Iashchenko struct source_location loc;
73ff3ed644SAleksandr Iashchenko struct type_descriptor *type;
74ff3ed644SAleksandr Iashchenko };
75ff3ed644SAleksandr Iashchenko
76ff3ed644SAleksandr Iashchenko struct shift_out_of_bounds_data {
77ff3ed644SAleksandr Iashchenko struct source_location loc;
78ff3ed644SAleksandr Iashchenko struct type_descriptor *lhs_type;
79ff3ed644SAleksandr Iashchenko struct type_descriptor *rhs_type;
80ff3ed644SAleksandr Iashchenko };
81ff3ed644SAleksandr Iashchenko
82ff3ed644SAleksandr Iashchenko struct out_of_bounds_data {
83ff3ed644SAleksandr Iashchenko struct source_location loc;
84ff3ed644SAleksandr Iashchenko struct type_descriptor *array_type;
85ff3ed644SAleksandr Iashchenko struct type_descriptor *index_type;
86ff3ed644SAleksandr Iashchenko };
87ff3ed644SAleksandr Iashchenko
88ff3ed644SAleksandr Iashchenko struct unreachable_data {
89ff3ed644SAleksandr Iashchenko struct source_location loc;
90ff3ed644SAleksandr Iashchenko };
91ff3ed644SAleksandr Iashchenko
92ff3ed644SAleksandr Iashchenko struct vla_bound_data {
93ff3ed644SAleksandr Iashchenko struct source_location loc;
94ff3ed644SAleksandr Iashchenko struct type_descriptor *type;
95ff3ed644SAleksandr Iashchenko };
96ff3ed644SAleksandr Iashchenko
97ff3ed644SAleksandr Iashchenko struct invalid_value_data {
98ff3ed644SAleksandr Iashchenko struct source_location loc;
99ff3ed644SAleksandr Iashchenko struct type_descriptor *type;
100ff3ed644SAleksandr Iashchenko };
101ff3ed644SAleksandr Iashchenko
102ff3ed644SAleksandr Iashchenko struct nonnull_arg_data {
103ff3ed644SAleksandr Iashchenko struct source_location loc;
104ff3ed644SAleksandr Iashchenko };
105ff3ed644SAleksandr Iashchenko
106ff3ed644SAleksandr Iashchenko struct invalid_builtin_data {
107ff3ed644SAleksandr Iashchenko struct source_location loc;
108ff3ed644SAleksandr Iashchenko unsigned char kind;
109ff3ed644SAleksandr Iashchenko };
110ff3ed644SAleksandr Iashchenko
111ff3ed644SAleksandr Iashchenko /*
112ff3ed644SAleksandr Iashchenko * When compiling with -fsanitize=undefined the compiler expects functions
113ff3ed644SAleksandr Iashchenko * with the following signatures. The functions are never called directly,
114ff3ed644SAleksandr Iashchenko * only when undefined behavior is detected in instrumented code.
115ff3ed644SAleksandr Iashchenko */
116ff3ed644SAleksandr Iashchenko void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
117ff3ed644SAleksandr Iashchenko unsigned long ptr);
118ff3ed644SAleksandr Iashchenko void __ubsan_handle_type_mismatch_v1(void *data_, void *ptr);
119ff3ed644SAleksandr Iashchenko void __ubsan_handle_add_overflow(void *data_, void *lhs, void *rhs);
120ff3ed644SAleksandr Iashchenko void __ubsan_handle_sub_overflow(void *data_, void *lhs, void *rhs);
121ff3ed644SAleksandr Iashchenko void __ubsan_handle_mul_overflow(void *data_, void *lhs, void *rhs);
122ff3ed644SAleksandr Iashchenko void __ubsan_handle_negate_overflow(void *data_, void *old_val);
123ff3ed644SAleksandr Iashchenko void __ubsan_handle_divrem_overflow(void *data_, void *lhs, void *rhs);
124ff3ed644SAleksandr Iashchenko void __ubsan_handle_pointer_overflow(void *data_, void *lhs, void *rhs);
125ff3ed644SAleksandr Iashchenko void __ubsan_handle_shift_out_of_bounds(void *data_, void *lhs, void *rhs);
126ff3ed644SAleksandr Iashchenko void __ubsan_handle_out_of_bounds(void *data_, void *idx);
127ff3ed644SAleksandr Iashchenko void __ubsan_handle_builtin_unreachable(void *data_);
128ff3ed644SAleksandr Iashchenko void __ubsan_handle_missing_return(void *data_);
129ff3ed644SAleksandr Iashchenko void __ubsan_handle_vla_bound_not_positive(void *data_, void *bound);
130ff3ed644SAleksandr Iashchenko void __ubsan_handle_load_invalid_value(void *data_, void *val);
131ff3ed644SAleksandr Iashchenko void __ubsan_handle_nonnull_arg(void *data_
132ff3ed644SAleksandr Iashchenko #if __GCC_VERSION < 60000
133ff3ed644SAleksandr Iashchenko , size_t arg_no
134ff3ed644SAleksandr Iashchenko #endif
135ff3ed644SAleksandr Iashchenko );
136ff3ed644SAleksandr Iashchenko void __ubsan_handle_invalid_builtin(void *data_);
137ff3ed644SAleksandr Iashchenko
138ff3ed644SAleksandr Iashchenko static bool should_panic = true;
139ff3ed644SAleksandr Iashchenko
ubsan_handle_error(const char * func,struct source_location * loc,bool panic_flag)140ff3ed644SAleksandr Iashchenko static void ubsan_handle_error(const char *func, struct source_location *loc,
141ff3ed644SAleksandr Iashchenko bool panic_flag)
142ff3ed644SAleksandr Iashchenko {
143ff3ed644SAleksandr Iashchenko const char *f = func;
144ff3ed644SAleksandr Iashchenko const char func_prefix[] = "__ubsan_handle";
145ff3ed644SAleksandr Iashchenko
146*fa1190c6SAleksandr Iashchenko if (was_already_reported(loc))
147*fa1190c6SAleksandr Iashchenko return;
148*fa1190c6SAleksandr Iashchenko
149ff3ed644SAleksandr Iashchenko if (!memcmp(f, func_prefix, sizeof(func_prefix) - 1))
150ff3ed644SAleksandr Iashchenko f += sizeof(func_prefix);
151ff3ed644SAleksandr Iashchenko
152ff3ed644SAleksandr Iashchenko EMSG_RAW("Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32,
153*fa1190c6SAleksandr Iashchenko f, loc->file_name, loc->line, loc->column & ~UBSAN_LOC_REPORTED);
154ff3ed644SAleksandr Iashchenko
155ff3ed644SAleksandr Iashchenko if (panic_flag)
156ff3ed644SAleksandr Iashchenko ubsan_panic();
157ff3ed644SAleksandr Iashchenko }
158ff3ed644SAleksandr Iashchenko
__ubsan_handle_type_mismatch(struct type_mismatch_data * data,unsigned long ptr __unused)159ff3ed644SAleksandr Iashchenko void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
160ff3ed644SAleksandr Iashchenko unsigned long ptr __unused)
161ff3ed644SAleksandr Iashchenko {
162ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
163ff3ed644SAleksandr Iashchenko }
164ff3ed644SAleksandr Iashchenko
__ubsan_handle_type_mismatch_v1(void * data_,void * ptr __unused)165ff3ed644SAleksandr Iashchenko void __ubsan_handle_type_mismatch_v1(void *data_, void *ptr __unused)
166ff3ed644SAleksandr Iashchenko {
167ff3ed644SAleksandr Iashchenko struct type_mismatch_data *data = data_;
168ff3ed644SAleksandr Iashchenko
169ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
170ff3ed644SAleksandr Iashchenko }
171ff3ed644SAleksandr Iashchenko
__ubsan_handle_add_overflow(void * data_,void * lhs __unused,void * rhs __unused)172ff3ed644SAleksandr Iashchenko void __ubsan_handle_add_overflow(void *data_, void *lhs __unused,
173ff3ed644SAleksandr Iashchenko void *rhs __unused)
174ff3ed644SAleksandr Iashchenko {
175ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_;
176ff3ed644SAleksandr Iashchenko
177ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
178ff3ed644SAleksandr Iashchenko }
179ff3ed644SAleksandr Iashchenko
__ubsan_handle_sub_overflow(void * data_,void * lhs __unused,void * rhs __unused)180ff3ed644SAleksandr Iashchenko void __ubsan_handle_sub_overflow(void *data_, void *lhs __unused,
181ff3ed644SAleksandr Iashchenko void *rhs __unused)
182ff3ed644SAleksandr Iashchenko {
183ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_;
184ff3ed644SAleksandr Iashchenko
185ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
186ff3ed644SAleksandr Iashchenko }
187ff3ed644SAleksandr Iashchenko
__ubsan_handle_mul_overflow(void * data_,void * lhs __unused,void * rhs __unused)188ff3ed644SAleksandr Iashchenko void __ubsan_handle_mul_overflow(void *data_, void *lhs __unused,
189ff3ed644SAleksandr Iashchenko void *rhs __unused)
190ff3ed644SAleksandr Iashchenko {
191ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_;
192ff3ed644SAleksandr Iashchenko
193ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
194ff3ed644SAleksandr Iashchenko }
195ff3ed644SAleksandr Iashchenko
__ubsan_handle_negate_overflow(void * data_,void * old_val __unused)196ff3ed644SAleksandr Iashchenko void __ubsan_handle_negate_overflow(void *data_, void *old_val __unused)
197ff3ed644SAleksandr Iashchenko {
198ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_;
199ff3ed644SAleksandr Iashchenko
200ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
201ff3ed644SAleksandr Iashchenko }
202ff3ed644SAleksandr Iashchenko
__ubsan_handle_divrem_overflow(void * data_,void * lhs __unused,void * rhs __unused)203ff3ed644SAleksandr Iashchenko void __ubsan_handle_divrem_overflow(void *data_, void *lhs __unused,
204ff3ed644SAleksandr Iashchenko void *rhs __unused)
205ff3ed644SAleksandr Iashchenko {
206ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_;
207ff3ed644SAleksandr Iashchenko
208ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
209ff3ed644SAleksandr Iashchenko }
210ff3ed644SAleksandr Iashchenko
__ubsan_handle_pointer_overflow(void * data_,void * lhs __unused,void * rhs __unused)211ff3ed644SAleksandr Iashchenko void __ubsan_handle_pointer_overflow(void *data_, void *lhs __unused,
212ff3ed644SAleksandr Iashchenko void *rhs __unused)
213ff3ed644SAleksandr Iashchenko {
214ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_;
215ff3ed644SAleksandr Iashchenko
216ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
217ff3ed644SAleksandr Iashchenko }
218ff3ed644SAleksandr Iashchenko
__ubsan_handle_shift_out_of_bounds(void * data_,void * lhs __unused,void * rhs __unused)219ff3ed644SAleksandr Iashchenko void __ubsan_handle_shift_out_of_bounds(void *data_, void *lhs __unused,
220ff3ed644SAleksandr Iashchenko void *rhs __unused)
221ff3ed644SAleksandr Iashchenko {
222ff3ed644SAleksandr Iashchenko struct shift_out_of_bounds_data *data = data_;
223ff3ed644SAleksandr Iashchenko
224ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
225ff3ed644SAleksandr Iashchenko }
226ff3ed644SAleksandr Iashchenko
__ubsan_handle_out_of_bounds(void * data_,void * idx __unused)227ff3ed644SAleksandr Iashchenko void __ubsan_handle_out_of_bounds(void *data_, void *idx __unused)
228ff3ed644SAleksandr Iashchenko {
229ff3ed644SAleksandr Iashchenko struct out_of_bounds_data *data = data_;
230ff3ed644SAleksandr Iashchenko
231ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
232ff3ed644SAleksandr Iashchenko }
233ff3ed644SAleksandr Iashchenko
__ubsan_handle_builtin_unreachable(void * data_)234ff3ed644SAleksandr Iashchenko void __noreturn __ubsan_handle_builtin_unreachable(void *data_)
235ff3ed644SAleksandr Iashchenko {
236ff3ed644SAleksandr Iashchenko struct unreachable_data *data = data_;
237ff3ed644SAleksandr Iashchenko
238ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, false);
239ff3ed644SAleksandr Iashchenko ubsan_panic();
240ff3ed644SAleksandr Iashchenko }
241ff3ed644SAleksandr Iashchenko
__ubsan_handle_missing_return(void * data_)242ff3ed644SAleksandr Iashchenko void __noreturn __ubsan_handle_missing_return(void *data_)
243ff3ed644SAleksandr Iashchenko {
244ff3ed644SAleksandr Iashchenko struct unreachable_data *data = data_;
245ff3ed644SAleksandr Iashchenko
246ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, false);
247ff3ed644SAleksandr Iashchenko ubsan_panic();
248ff3ed644SAleksandr Iashchenko }
249ff3ed644SAleksandr Iashchenko
__ubsan_handle_vla_bound_not_positive(void * data_,void * bound __unused)250ff3ed644SAleksandr Iashchenko void __ubsan_handle_vla_bound_not_positive(void *data_, void *bound __unused)
251ff3ed644SAleksandr Iashchenko {
252ff3ed644SAleksandr Iashchenko struct vla_bound_data *data = data_;
253ff3ed644SAleksandr Iashchenko
254ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
255ff3ed644SAleksandr Iashchenko }
256ff3ed644SAleksandr Iashchenko
__ubsan_handle_load_invalid_value(void * data_,void * val __unused)257ff3ed644SAleksandr Iashchenko void __ubsan_handle_load_invalid_value(void *data_, void *val __unused)
258ff3ed644SAleksandr Iashchenko {
259ff3ed644SAleksandr Iashchenko struct invalid_value_data *data = data_;
260ff3ed644SAleksandr Iashchenko
261ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
262ff3ed644SAleksandr Iashchenko }
263ff3ed644SAleksandr Iashchenko
__ubsan_handle_nonnull_arg(void * data_,size_t arg_no __unused)264ff3ed644SAleksandr Iashchenko void __ubsan_handle_nonnull_arg(void *data_
265ff3ed644SAleksandr Iashchenko #if __GCC_VERSION < 60000
266ff3ed644SAleksandr Iashchenko , size_t arg_no __unused
267ff3ed644SAleksandr Iashchenko #endif
268ff3ed644SAleksandr Iashchenko )
269ff3ed644SAleksandr Iashchenko {
270ff3ed644SAleksandr Iashchenko struct nonnull_arg_data *data = data_;
271ff3ed644SAleksandr Iashchenko
272ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
273ff3ed644SAleksandr Iashchenko }
274ff3ed644SAleksandr Iashchenko
__ubsan_handle_invalid_builtin(void * data_)275ff3ed644SAleksandr Iashchenko void __ubsan_handle_invalid_builtin(void *data_)
276ff3ed644SAleksandr Iashchenko {
277ff3ed644SAleksandr Iashchenko struct invalid_builtin_data *data = data_;
278ff3ed644SAleksandr Iashchenko
279ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic);
280ff3ed644SAleksandr Iashchenko }
281