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