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