/ duct-tape / xnu / san / ubsan.h
ubsan.h
  1  /*
  2   * Copyright (c) 2018 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  enum {
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  struct ubsan_violation {
159  	uint8_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  };
182  
183  struct ubsan_buf {
184  	size_t  ub_logged;
185  	size_t  ub_buf_size;
186  	char    *ub_buf;
187  };
188  
189  void ubsan_log_append(struct ubsan_violation *);
190  void ubsan_format(struct ubsan_violation *, struct ubsan_buf *);
191  
192  /*
193   * UBSan ABI
194   */
195  
196  void __ubsan_handle_add_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
197  void __ubsan_handle_add_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
198  void __ubsan_handle_builtin_unreachable(struct ubsan_unreachable_desc *);
199  void __ubsan_handle_divrem_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
200  void __ubsan_handle_divrem_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
201  void __ubsan_handle_float_cast_overflow(struct ubsan_float_desc *, uint64_t);
202  void __ubsan_handle_float_cast_overflow_abort(struct ubsan_float_desc *, uint64_t);
203  void __ubsan_handle_function_type_mismatch(struct ubsan_func_type_mismatch_desc*, uint64_t);
204  void __ubsan_handle_function_type_mismatch_abort(struct ubsan_func_type_mismatch_desc *, uint64_t);
205  void __ubsan_handle_implicit_conversion(struct ubsan_implicit_conv_desc *, uint64_t, uint64_t);
206  void __ubsan_handle_implicit_conversion_abort(struct ubsan_implicit_conv_desc *, uint64_t, uint64_t);
207  void __ubsan_handle_invalid_builtin(struct ubsan_invalid_builtin *);
208  void __ubsan_handle_invalid_builtin_abort(struct ubsan_invalid_builtin *);
209  void __ubsan_handle_load_invalid_value(struct ubsan_load_invalid_desc *, uint64_t);
210  void __ubsan_handle_load_invalid_value_abort(struct ubsan_load_invalid_desc *, uint64_t);
211  void __ubsan_handle_missing_return(struct ubsan_missing_ret_desc *);
212  void __ubsan_handle_missing_return_abort(struct ubsan_missing_ret_desc *);
213  void __ubsan_handle_mul_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
214  void __ubsan_handle_mul_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
215  void __ubsan_handle_negate_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
216  void __ubsan_handle_negate_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
217  void __ubsan_handle_nonnull_arg(struct ubsan_nullability_arg_desc *);
218  void __ubsan_handle_nonnull_arg_abort(struct ubsan_nullability_arg_desc *);
219  void __ubsan_handle_nonnull_return_v1(struct ubsan_nullability_ret_desc *, uint64_t);
220  void __ubsan_handle_nonnull_return_v1_abort(struct ubsan_nullability_ret_desc *, uint64_t);
221  void __ubsan_handle_nullability_arg(struct ubsan_nullability_arg_desc *);
222  void __ubsan_handle_nullability_arg_abort(struct ubsan_nullability_arg_desc *);
223  void __ubsan_handle_nullability_return_v1(struct ubsan_nullability_ret_desc *, uint64_t);
224  void __ubsan_handle_nullability_return_v1_abort(struct ubsan_nullability_ret_desc *, uint64_t);
225  void __ubsan_handle_out_of_bounds(struct ubsan_oob_desc *, uint64_t idx);
226  void __ubsan_handle_out_of_bounds_abort(struct ubsan_oob_desc *, uint64_t idx);
227  void __ubsan_handle_pointer_overflow(struct ubsan_ptroverflow_desc *, uint64_t lhs, uint64_t rhs);
228  void __ubsan_handle_pointer_overflow_abort(struct ubsan_ptroverflow_desc *, uint64_t lhs, uint64_t rhs);
229  void __ubsan_handle_shift_out_of_bounds(struct ubsan_shift_desc *, uint64_t lhs, uint64_t rhs);
230  void __ubsan_handle_shift_out_of_bounds_abort(struct ubsan_shift_desc *, uint64_t lhs, uint64_t rhs);
231  void __ubsan_handle_sub_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
232  void __ubsan_handle_sub_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs);
233  void __ubsan_handle_type_mismatch_v1(struct ubsan_align_desc *, uint64_t val);
234  void __ubsan_handle_type_mismatch_v1_abort(struct ubsan_align_desc *, uint64_t val);
235  void __ubsan_handle_vla_bound_not_positive(struct ubsan_vla_bound_desc *, uint64_t);
236  void __ubsan_handle_vla_bound_not_positive_abort(struct ubsan_vla_bound_desc *, uint64_t);
237  
238  #endif /* _UBSAN_H_ */