xref: /xnu-10063.121.3/san/memory/ubsan.h (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1 /*
2  * Copyright (c) 2018-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #ifndef _UBSAN_H_
30 #define _UBSAN_H_
31 
32 #include <stdint.h>
33 #include <stdbool.h>
34 
35 struct san_type_desc {
36 	uint16_t type; // 0: integer, 1: float
37 	union {
38 		struct {
39 			uint16_t issigned : 1;
40 			uint16_t width    : 15;
41 		}; /* int descriptor */
42 		struct {
43 			uint16_t float_desc;
44 		}; /* float descriptor */
45 	};
46 	const char name[];
47 };
48 
49 struct san_src_loc {
50 	const char *filename;
51 	uint32_t line;
52 	uint32_t col;
53 };
54 
55 struct ubsan_overflow_desc {
56 	struct san_src_loc loc;
57 	struct san_type_desc *ty;
58 };
59 
60 struct ubsan_unreachable_desc {
61 	struct san_src_loc loc;
62 };
63 
64 struct ubsan_shift_desc {
65 	struct san_src_loc loc;
66 	struct san_type_desc *lhs_t;
67 	struct san_type_desc *rhs_t;
68 };
69 
70 struct ubsan_align_desc {
71 	struct san_src_loc loc;
72 	struct san_type_desc *ty;
73 	uint8_t align;
74 	uint8_t kind;
75 };
76 
77 struct ubsan_ptroverflow_desc {
78 	struct san_src_loc loc;
79 };
80 
81 struct ubsan_oob_desc {
82 	struct san_src_loc loc;
83 	struct san_type_desc *array_ty;
84 	struct san_type_desc *index_ty;
85 };
86 
87 struct ubsan_load_invalid_desc {
88 	struct san_src_loc loc;
89 	struct san_type_desc *type;
90 };
91 
92 struct ubsan_nullability_arg_desc {
93 	struct san_src_loc loc;
94 	struct san_src_loc attr_loc;
95 	int arg_index;
96 };
97 
98 struct ubsan_nullability_ret_desc {
99 	struct san_src_loc loc;
100 };
101 
102 struct ubsan_missing_ret_desc {
103 	struct san_src_loc loc;
104 };
105 
106 struct ubsan_float_desc {
107 	struct san_src_loc loc;
108 	struct san_type_desc *type_from;
109 	struct san_type_desc *type_to;
110 };
111 
112 struct ubsan_implicit_conv_desc {
113 	struct san_src_loc loc;
114 	struct san_type_desc *type_from;
115 	struct san_type_desc *type_to;
116 	unsigned char kind;
117 };
118 
119 struct ubsan_func_type_mismatch_desc {
120 	struct san_src_loc loc;
121 	struct san_type_desc *type;
122 };
123 
124 struct ubsan_vla_bound_desc {
125 	struct san_src_loc loc;
126 	struct san_type_desc *type;
127 };
128 
129 struct ubsan_invalid_builtin {
130 	struct san_src_loc loc;
131 	unsigned char kind;
132 };
133 
134 OS_ENUM(ubsan_violation_type, uint8_t,
135     UBSAN_OVERFLOW_add = 1,
136     UBSAN_OVERFLOW_sub,
137     UBSAN_OVERFLOW_mul,
138     UBSAN_OVERFLOW_divrem,
139     UBSAN_OVERFLOW_negate,
140     UBSAN_UNREACHABLE,
141     UBSAN_SHIFT,
142     UBSAN_ALIGN,
143     UBSAN_POINTER_OVERFLOW,
144     UBSAN_OOB,
145     UBSAN_TYPE_MISMATCH,
146     UBSAN_LOAD_INVALID_VALUE,
147     UBSAN_NULLABILITY_ARG,
148     UBSAN_NULLABILITY_RETURN,
149     UBSAN_MISSING_RETURN,
150     UBSAN_FLOAT_CAST_OVERFLOW,
151     UBSAN_IMPLICIT_CONVERSION,
152     UBSAN_FUNCTION_TYPE_MISMATCH,
153     UBSAN_VLA_BOUND_NOT_POSITIVE,
154     UBSAN_INVALID_BUILTIN,
155     UBSAN_VIOLATION_MAX
156     );
157 
158 typedef struct ubsan_violation {
159 	ubsan_violation_type_t ubsan_type;
160 	uint64_t lhs;
161 	uint64_t rhs;
162 	union {
163 		struct ubsan_overflow_desc *overflow;
164 		struct ubsan_unreachable_desc *unreachable;
165 		struct ubsan_shift_desc *shift;
166 		struct ubsan_align_desc *align;
167 		struct ubsan_ptroverflow_desc *ptroverflow;
168 		struct ubsan_oob_desc *oob;
169 		struct ubsan_load_invalid_desc *invalid;
170 		struct ubsan_nullability_arg_desc *nonnull_arg;
171 		struct ubsan_nullability_ret_desc *nonnull_ret;
172 		struct ubsan_missing_ret_desc *missing_ret;
173 		struct ubsan_float_desc *flt;
174 		struct ubsan_implicit_conv_desc *implicit;
175 		struct ubsan_func_type_mismatch_desc *func_mismatch;
176 		struct ubsan_vla_bound_desc *vla_bound;
177 		struct ubsan_invalid_builtin *invalid_builtin;
178 		const char *func;
179 	};
180 	struct san_src_loc *loc;
181 } ubsan_violation_t;
182 
183 typedef struct ubsan_buf {
184 	char    *ub_buf;
185 	size_t  ub_buf_size;
186 	size_t  ub_written;
187 	bool    ub_err;
188 } ubsan_buf_t;
189 
190 void    ubsan_log_append(ubsan_violation_t *);
191 
192 void    ubsan_json_init(ubsan_buf_t *, char *, size_t);
193 void    ubsan_json_begin(ubsan_buf_t *, size_t);
194 size_t  ubsan_json_finish(ubsan_buf_t *);
195 bool    ubsan_json_format(ubsan_violation_t *, ubsan_buf_t *);
196 
197 /*
198  * UBSan ABI
199  */
200 void __ubsan_handle_add_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
201 void __ubsan_handle_add_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
202 void __ubsan_handle_builtin_unreachable(struct ubsan_unreachable_desc *);
203 void __ubsan_handle_divrem_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
204 void __ubsan_handle_divrem_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
205 void __ubsan_handle_float_cast_overflow(struct ubsan_float_desc *, uint64_t);
206 void __ubsan_handle_float_cast_overflow_abort(struct ubsan_float_desc *, uint64_t);
207 void __ubsan_handle_function_type_mismatch(struct ubsan_func_type_mismatch_desc*, uint64_t);
208 void __ubsan_handle_function_type_mismatch_abort(struct ubsan_func_type_mismatch_desc *, uint64_t);
209 void __ubsan_handle_implicit_conversion(struct ubsan_implicit_conv_desc *, uint64_t, uint64_t);
210 void __ubsan_handle_implicit_conversion_abort(struct ubsan_implicit_conv_desc *, uint64_t, uint64_t);
211 void __ubsan_handle_invalid_builtin(struct ubsan_invalid_builtin *);
212 void __ubsan_handle_invalid_builtin_abort(struct ubsan_invalid_builtin *);
213 void __ubsan_handle_load_invalid_value(struct ubsan_load_invalid_desc *, uint64_t);
214 void __ubsan_handle_load_invalid_value_abort(struct ubsan_load_invalid_desc *, uint64_t);
215 void __ubsan_handle_missing_return(struct ubsan_missing_ret_desc *);
216 void __ubsan_handle_missing_return_abort(struct ubsan_missing_ret_desc *);
217 void __ubsan_handle_mul_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
218 void __ubsan_handle_mul_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
219 void __ubsan_handle_negate_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
220 void __ubsan_handle_negate_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
221 void __ubsan_handle_nonnull_arg(struct ubsan_nullability_arg_desc *);
222 void __ubsan_handle_nonnull_arg_abort(struct ubsan_nullability_arg_desc *);
223 void __ubsan_handle_nonnull_return_v1(struct ubsan_nullability_ret_desc *, uint64_t);
224 void __ubsan_handle_nonnull_return_v1_abort(struct ubsan_nullability_ret_desc *, uint64_t);
225 void __ubsan_handle_nullability_arg(struct ubsan_nullability_arg_desc *);
226 void __ubsan_handle_nullability_arg_abort(struct ubsan_nullability_arg_desc *);
227 void __ubsan_handle_nullability_return_v1(struct ubsan_nullability_ret_desc *, uint64_t);
228 void __ubsan_handle_nullability_return_v1_abort(struct ubsan_nullability_ret_desc *, uint64_t);
229 void __ubsan_handle_out_of_bounds(struct ubsan_oob_desc *, uint64_t idx);
230 void __ubsan_handle_out_of_bounds_abort(struct ubsan_oob_desc *, uint64_t idx);
231 void __ubsan_handle_pointer_overflow(struct ubsan_ptroverflow_desc *, uint64_t lhs, uint64_t rhs);
232 void __ubsan_handle_pointer_overflow_abort(struct ubsan_ptroverflow_desc *, uint64_t lhs, uint64_t rhs);
233 void __ubsan_handle_shift_out_of_bounds(struct ubsan_shift_desc *, uint64_t lhs, uint64_t rhs);
234 void __ubsan_handle_shift_out_of_bounds_abort(struct ubsan_shift_desc *, uint64_t lhs, uint64_t rhs);
235 void __ubsan_handle_sub_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
236 void __ubsan_handle_sub_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
237 void __ubsan_handle_type_mismatch_v1(struct ubsan_align_desc *, uint64_t val);
238 void __ubsan_handle_type_mismatch_v1_abort(struct ubsan_align_desc *, uint64_t val);
239 void __ubsan_handle_vla_bound_not_positive(struct ubsan_vla_bound_desc *, uint64_t);
240 void __ubsan_handle_vla_bound_not_positive_abort(struct ubsan_vla_bound_desc *, uint64_t);
241 
242 #endif /* _UBSAN_H_ */
243