| 1 |
|
| 2 | #ifndef _LIB_UBSAN_H
|
| 3 | #define _LIB_UBSAN_H
|
| 4 |
|
| 5 | |
| 6 | * ABI defined by Clang's UBSAN enum SanitizerHandler:
|
| 7 | * https://github.com/llvm/llvm-project/blob/release/16.x/clang/lib/CodeGen/CodeGenFunction.h#L113
|
| 8 |
|
| 9 | enum ubsan_checks {
|
| 10 | ubsan_add_overflow,
|
| 11 | ubsan_builtin_unreachable,
|
| 12 | ubsan_cfi_check_fail,
|
| 13 | ubsan_divrem_overflow,
|
| 14 | ubsan_dynamic_type_cache_miss,
|
| 15 | ubsan_float_cast_overflow,
|
| 16 | ubsan_function_type_mismatch,
|
| 17 | ubsan_implicit_conversion,
|
| 18 | ubsan_invalid_builtin,
|
| 19 | ubsan_invalid_objc_cast,
|
| 20 | ubsan_load_invalid_value,
|
| 21 | ubsan_missing_return,
|
| 22 | ubsan_mul_overflow,
|
| 23 | ubsan_negate_overflow,
|
| 24 | ubsan_nullability_arg,
|
| 25 | ubsan_nullability_return,
|
| 26 | ubsan_nonnull_arg,
|
| 27 | ubsan_nonnull_return,
|
| 28 | ubsan_out_of_bounds,
|
| 29 | ubsan_pointer_overflow,
|
| 30 | ubsan_shift_out_of_bounds,
|
| 31 | ubsan_sub_overflow,
|
| 32 | ubsan_type_mismatch,
|
| 33 | ubsan_alignment_assumption,
|
| 34 | ubsan_vla_bound_not_positive,
|
| 35 | };
|
| 36 |
|
| 37 | enum {
|
| 38 | type_kind_int = 0,
|
| 39 | type_kind_float = 1,
|
| 40 | type_unknown = 0xffff
|
| 41 | };
|
| 42 |
|
| 43 | struct type_descriptor {
|
| 44 | u16 type_kind;
|
| 45 | u16 type_info;
|
| 46 | char type_name[];
|
| 47 | };
|
| 48 |
|
| 49 | struct source_location {
|
| 50 | const char *file_name;
|
| 51 | union {
|
| 52 | unsigned long reported;
|
| 53 | struct {
|
| 54 | u32 line;
|
| 55 | u32 column;
|
| 56 | };
|
| 57 | };
|
| 58 | };
|
| 59 |
|
| 60 | struct overflow_data {
|
| 61 | struct source_location location;
|
| 62 | struct type_descriptor *type;
|
| 63 | };
|
| 64 |
|
| 65 | struct implicit_conversion_data {
|
| 66 | struct source_location location;
|
| 67 | struct type_descriptor *from_type;
|
| 68 | struct type_descriptor *to_type;
|
| 69 | unsigned char type_check_kind;
|
| 70 | };
|
| 71 |
|
| 72 | struct type_mismatch_data {
|
| 73 | struct source_location location;
|
| 74 | struct type_descriptor *type;
|
| 75 | unsigned long alignment;
|
| 76 | unsigned char type_check_kind;
|
| 77 | };
|
| 78 |
|
| 79 | struct type_mismatch_data_v1 {
|
| 80 | struct source_location location;
|
| 81 | struct type_descriptor *type;
|
| 82 | unsigned char log_alignment;
|
| 83 | unsigned char type_check_kind;
|
| 84 | };
|
| 85 |
|
| 86 | struct type_mismatch_data_common {
|
| 87 | struct source_location *location;
|
| 88 | struct type_descriptor *type;
|
| 89 | unsigned long alignment;
|
| 90 | unsigned char type_check_kind;
|
| 91 | };
|
| 92 |
|
| 93 | struct nonnull_arg_data {
|
| 94 | struct source_location location;
|
| 95 | struct source_location attr_location;
|
| 96 | int arg_index;
|
| 97 | };
|
| 98 |
|
| 99 | struct out_of_bounds_data {
|
| 100 | struct source_location location;
|
| 101 | struct type_descriptor *array_type;
|
| 102 | struct type_descriptor *index_type;
|
| 103 | };
|
| 104 |
|
| 105 | struct shift_out_of_bounds_data {
|
| 106 | struct source_location location;
|
| 107 | struct type_descriptor *lhs_type;
|
| 108 | struct type_descriptor *rhs_type;
|
| 109 | };
|
| 110 |
|
| 111 | struct unreachable_data {
|
| 112 | struct source_location location;
|
| 113 | };
|
| 114 |
|
| 115 | struct invalid_value_data {
|
| 116 | struct source_location location;
|
| 117 | struct type_descriptor *type;
|
| 118 | };
|
| 119 |
|
| 120 | struct alignment_assumption_data {
|
| 121 | struct source_location location;
|
| 122 | struct source_location assumption_location;
|
| 123 | struct type_descriptor *type;
|
| 124 | };
|
| 125 |
|
| 126 | #if defined(CONFIG_ARCH_SUPPORTS_INT128)
|
| 127 | typedef __int128 s_max;
|
| 128 | typedef unsigned __int128 u_max;
|
| 129 | #else
|
| 130 | typedef s64 s_max;
|
| 131 | typedef u64 u_max;
|
| 132 | #endif
|
| 133 |
|
| 134 | |
| 135 | * When generating Runtime Calls, Clang doesn't respect the -mregparm=3
|
| 136 | * option used on i386: https://github.com/llvm/llvm-project/issues/89670
|
| 137 | * Fix this for earlier Clang versions by forcing the calling convention
|
| 138 | * to use non-register arguments.
|
| 139 |
|
| 140 | #if defined(CONFIG_X86_32) && \
|
| 141 | defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 190000
|
| 142 | # define ubsan_linkage asmlinkage
|
| 143 | #else
|
| 144 | # define ubsan_linkage
|
| 145 | #endif
|
| 146 |
|
| 147 | void ubsan_linkage __ubsan_handle_add_overflow(void *data, void *lhs, void *rhs);
|
| 148 | void ubsan_linkage __ubsan_handle_sub_overflow(void *data, void *lhs, void *rhs);
|
| 149 | void ubsan_linkage __ubsan_handle_mul_overflow(void *data, void *lhs, void *rhs);
|
| 150 | void ubsan_linkage __ubsan_handle_negate_overflow(void *_data, void *old_val);
|
| 151 | void ubsan_linkage __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs);
|
| 152 | void ubsan_linkage __ubsan_handle_implicit_conversion(void *_data, void *lhs, void *rhs);
|
| 153 | void ubsan_linkage __ubsan_handle_type_mismatch(struct type_mismatch_data *data, void *ptr);
|
| 154 | void ubsan_linkage __ubsan_handle_type_mismatch_v1(void *_data, void *ptr);
|
| 155 | void ubsan_linkage __ubsan_handle_out_of_bounds(void *_data, void *index);
|
| 156 | void ubsan_linkage __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs);
|
| 157 | void ubsan_linkage __ubsan_handle_builtin_unreachable(void *_data);
|
| 158 | void ubsan_linkage __ubsan_handle_load_invalid_value(void *_data, void *val);
|
| 159 | void ubsan_linkage __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr,
|
| 160 | unsigned long align,
|
| 161 | unsigned long offset);
|
| 162 |
|
| 163 | #endif
|