xref: /arm-trusted-firmware/plat/common/ubsan.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2016, Linaro Limited
3*91f16700Schasinglulu  * Copyright (c) 2019, ARM Limited. All rights reserved.
4*91f16700Schasinglulu  *
5*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-2-Clause
6*91f16700Schasinglulu  */
7*91f16700Schasinglulu 
8*91f16700Schasinglulu #include <arch_helpers.h>
9*91f16700Schasinglulu #include <context.h>
10*91f16700Schasinglulu #include <common/debug.h>
11*91f16700Schasinglulu #include <plat/common/platform.h>
12*91f16700Schasinglulu 
13*91f16700Schasinglulu struct source_location {
14*91f16700Schasinglulu 	const char *file_name;
15*91f16700Schasinglulu 	uint32_t line;
16*91f16700Schasinglulu 	uint32_t column;
17*91f16700Schasinglulu };
18*91f16700Schasinglulu 
19*91f16700Schasinglulu struct type_descriptor {
20*91f16700Schasinglulu 	uint16_t type_kind;
21*91f16700Schasinglulu 	uint16_t type_info;
22*91f16700Schasinglulu 	char type_name[1];
23*91f16700Schasinglulu };
24*91f16700Schasinglulu 
25*91f16700Schasinglulu struct type_mismatch_data {
26*91f16700Schasinglulu 	struct source_location loc;
27*91f16700Schasinglulu 	struct type_descriptor *type;
28*91f16700Schasinglulu 	unsigned long alignment;
29*91f16700Schasinglulu 	unsigned char type_check_kind;
30*91f16700Schasinglulu };
31*91f16700Schasinglulu 
32*91f16700Schasinglulu struct overflow_data {
33*91f16700Schasinglulu 	struct source_location loc;
34*91f16700Schasinglulu 	struct type_descriptor *type;
35*91f16700Schasinglulu };
36*91f16700Schasinglulu 
37*91f16700Schasinglulu struct shift_out_of_bounds_data {
38*91f16700Schasinglulu 	struct source_location loc;
39*91f16700Schasinglulu 	struct type_descriptor *lhs_type;
40*91f16700Schasinglulu 	struct type_descriptor *rhs_type;
41*91f16700Schasinglulu };
42*91f16700Schasinglulu 
43*91f16700Schasinglulu struct out_of_bounds_data {
44*91f16700Schasinglulu 	struct source_location loc;
45*91f16700Schasinglulu 	struct type_descriptor *array_type;
46*91f16700Schasinglulu 	struct type_descriptor *index_type;
47*91f16700Schasinglulu };
48*91f16700Schasinglulu 
49*91f16700Schasinglulu struct unreachable_data {
50*91f16700Schasinglulu 	struct source_location loc;
51*91f16700Schasinglulu };
52*91f16700Schasinglulu 
53*91f16700Schasinglulu struct vla_bound_data {
54*91f16700Schasinglulu 	struct source_location loc;
55*91f16700Schasinglulu 	struct type_descriptor *type;
56*91f16700Schasinglulu };
57*91f16700Schasinglulu 
58*91f16700Schasinglulu struct invalid_value_data {
59*91f16700Schasinglulu 	struct source_location loc;
60*91f16700Schasinglulu 	struct type_descriptor *type;
61*91f16700Schasinglulu };
62*91f16700Schasinglulu 
63*91f16700Schasinglulu struct nonnull_arg_data {
64*91f16700Schasinglulu 	struct source_location loc;
65*91f16700Schasinglulu };
66*91f16700Schasinglulu 
67*91f16700Schasinglulu /*
68*91f16700Schasinglulu  * When compiling with -fsanitize=undefined the compiler expects functions
69*91f16700Schasinglulu  * with the following signatures. The functions are never called directly,
70*91f16700Schasinglulu  * only when undefined behavior is detected in instrumented code.
71*91f16700Schasinglulu  */
72*91f16700Schasinglulu void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data,
73*91f16700Schasinglulu 					unsigned long ptr);
74*91f16700Schasinglulu void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data,
75*91f16700Schasinglulu 					   unsigned long ptr);
76*91f16700Schasinglulu void __ubsan_handle_add_overflow_abort(struct overflow_data *data,
77*91f16700Schasinglulu 					unsigned long lhs, unsigned long rhs);
78*91f16700Schasinglulu void __ubsan_handle_sub_overflow_abort(struct overflow_data *data,
79*91f16700Schasinglulu 				       unsigned long lhs, unsigned long rhs);
80*91f16700Schasinglulu void __ubsan_handle_mul_overflow_abort(struct overflow_data *data,
81*91f16700Schasinglulu 				       unsigned long lhs, unsigned long rhs);
82*91f16700Schasinglulu void __ubsan_handle_negate_overflow_abort(struct overflow_data *data,
83*91f16700Schasinglulu 					  unsigned long old_val);
84*91f16700Schasinglulu void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data,
85*91f16700Schasinglulu 					   unsigned long old_val);
86*91f16700Schasinglulu void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data,
87*91f16700Schasinglulu 					  unsigned long lhs, unsigned long rhs);
88*91f16700Schasinglulu void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data,
89*91f16700Schasinglulu 					      unsigned long lhs, unsigned long rhs);
90*91f16700Schasinglulu void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data,
91*91f16700Schasinglulu 					unsigned long idx);
92*91f16700Schasinglulu void __ubsan_handle_unreachable_abort(struct unreachable_data *data);
93*91f16700Schasinglulu void __ubsan_handle_missing_return_abort(struct unreachable_data *data);
94*91f16700Schasinglulu void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data,
95*91f16700Schasinglulu 						 unsigned long bound);
96*91f16700Schasinglulu void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data,
97*91f16700Schasinglulu 					     unsigned long val);
98*91f16700Schasinglulu void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data
99*91f16700Schasinglulu #if __GCC_VERSION < 60000
100*91f16700Schasinglulu 				    , size_t arg_no
101*91f16700Schasinglulu #endif
102*91f16700Schasinglulu 				      );
103*91f16700Schasinglulu 
104*91f16700Schasinglulu static void print_loc(const char *func, struct source_location *loc)
105*91f16700Schasinglulu {
106*91f16700Schasinglulu 	ERROR("Undefined behavior at %s:%d col %d (%s)",
107*91f16700Schasinglulu 		loc->file_name, loc->line, loc->column, func);
108*91f16700Schasinglulu }
109*91f16700Schasinglulu 
110*91f16700Schasinglulu 
111*91f16700Schasinglulu void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data,
112*91f16700Schasinglulu 					unsigned long ptr __unused)
113*91f16700Schasinglulu {
114*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
115*91f16700Schasinglulu 	plat_panic_handler();
116*91f16700Schasinglulu }
117*91f16700Schasinglulu 
118*91f16700Schasinglulu void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data,
119*91f16700Schasinglulu 					unsigned long ptr __unused)
120*91f16700Schasinglulu {
121*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
122*91f16700Schasinglulu 	plat_panic_handler();
123*91f16700Schasinglulu }
124*91f16700Schasinglulu 
125*91f16700Schasinglulu void __ubsan_handle_add_overflow_abort(struct overflow_data *data,
126*91f16700Schasinglulu 				       unsigned long lhs __unused,
127*91f16700Schasinglulu 				       unsigned long rhs __unused)
128*91f16700Schasinglulu {
129*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
130*91f16700Schasinglulu 	plat_panic_handler();
131*91f16700Schasinglulu }
132*91f16700Schasinglulu 
133*91f16700Schasinglulu void __ubsan_handle_sub_overflow_abort(struct overflow_data *data,
134*91f16700Schasinglulu 				       unsigned long lhs __unused,
135*91f16700Schasinglulu 				       unsigned long rhs __unused)
136*91f16700Schasinglulu {
137*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
138*91f16700Schasinglulu 	plat_panic_handler();
139*91f16700Schasinglulu }
140*91f16700Schasinglulu 
141*91f16700Schasinglulu void __ubsan_handle_mul_overflow_abort(struct overflow_data *data,
142*91f16700Schasinglulu 				       unsigned long lhs __unused,
143*91f16700Schasinglulu 				       unsigned long rhs __unused)
144*91f16700Schasinglulu {
145*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
146*91f16700Schasinglulu 	plat_panic_handler();
147*91f16700Schasinglulu }
148*91f16700Schasinglulu 
149*91f16700Schasinglulu void __ubsan_handle_negate_overflow_abort(struct overflow_data *data,
150*91f16700Schasinglulu 					  unsigned long old_val __unused)
151*91f16700Schasinglulu {
152*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
153*91f16700Schasinglulu 	plat_panic_handler();
154*91f16700Schasinglulu }
155*91f16700Schasinglulu 
156*91f16700Schasinglulu void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data,
157*91f16700Schasinglulu 					  unsigned long old_val __unused)
158*91f16700Schasinglulu {
159*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
160*91f16700Schasinglulu 	plat_panic_handler();
161*91f16700Schasinglulu }
162*91f16700Schasinglulu 
163*91f16700Schasinglulu void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data,
164*91f16700Schasinglulu 					  unsigned long lhs __unused,
165*91f16700Schasinglulu 					  unsigned long rhs __unused)
166*91f16700Schasinglulu {
167*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
168*91f16700Schasinglulu 	plat_panic_handler();
169*91f16700Schasinglulu }
170*91f16700Schasinglulu 
171*91f16700Schasinglulu void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data,
172*91f16700Schasinglulu 					      unsigned long lhs __unused,
173*91f16700Schasinglulu 					      unsigned long rhs __unused)
174*91f16700Schasinglulu {
175*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
176*91f16700Schasinglulu 	plat_panic_handler();
177*91f16700Schasinglulu }
178*91f16700Schasinglulu 
179*91f16700Schasinglulu void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data,
180*91f16700Schasinglulu 					unsigned long idx __unused)
181*91f16700Schasinglulu {
182*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
183*91f16700Schasinglulu 	plat_panic_handler();
184*91f16700Schasinglulu }
185*91f16700Schasinglulu 
186*91f16700Schasinglulu void __ubsan_handle_unreachable_abort(struct unreachable_data *data)
187*91f16700Schasinglulu {
188*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
189*91f16700Schasinglulu 	plat_panic_handler();
190*91f16700Schasinglulu }
191*91f16700Schasinglulu 
192*91f16700Schasinglulu void __ubsan_handle_missing_return_abort(struct unreachable_data *data)
193*91f16700Schasinglulu {
194*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
195*91f16700Schasinglulu 	plat_panic_handler();
196*91f16700Schasinglulu }
197*91f16700Schasinglulu 
198*91f16700Schasinglulu void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data,
199*91f16700Schasinglulu 						 unsigned long bound __unused)
200*91f16700Schasinglulu {
201*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
202*91f16700Schasinglulu 	plat_panic_handler();
203*91f16700Schasinglulu }
204*91f16700Schasinglulu 
205*91f16700Schasinglulu void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data,
206*91f16700Schasinglulu 					     unsigned long val __unused)
207*91f16700Schasinglulu {
208*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
209*91f16700Schasinglulu 	plat_panic_handler();
210*91f16700Schasinglulu }
211*91f16700Schasinglulu 
212*91f16700Schasinglulu void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data
213*91f16700Schasinglulu #if __GCC_VERSION < 60000
214*91f16700Schasinglulu 				   , size_t arg_no __unused
215*91f16700Schasinglulu #endif
216*91f16700Schasinglulu 				     )
217*91f16700Schasinglulu {
218*91f16700Schasinglulu 	print_loc(__func__, &data->loc);
219*91f16700Schasinglulu 	plat_panic_handler();
220*91f16700Schasinglulu }
221