1*ff3ed644SAleksandr Iashchenko // SPDX-License-Identifier: BSD-2-Clause 2*ff3ed644SAleksandr Iashchenko /* 3*ff3ed644SAleksandr Iashchenko * Copyright (c) 2016, Linaro Limited 4*ff3ed644SAleksandr Iashchenko */ 5*ff3ed644SAleksandr Iashchenko 6*ff3ed644SAleksandr Iashchenko #include <compiler.h> 7*ff3ed644SAleksandr Iashchenko #include <string.h> 8*ff3ed644SAleksandr Iashchenko #include <trace.h> 9*ff3ed644SAleksandr Iashchenko #include <types_ext.h> 10*ff3ed644SAleksandr Iashchenko 11*ff3ed644SAleksandr Iashchenko #if defined(__KERNEL__) 12*ff3ed644SAleksandr Iashchenko # include <kernel/panic.h> 13*ff3ed644SAleksandr Iashchenko #elif defined(__LDELF__) 14*ff3ed644SAleksandr Iashchenko # include <ldelf_syscalls.h> 15*ff3ed644SAleksandr Iashchenko #else 16*ff3ed644SAleksandr Iashchenko # error "Unexpected build for ubsan" 17*ff3ed644SAleksandr Iashchenko #endif 18*ff3ed644SAleksandr Iashchenko 19*ff3ed644SAleksandr Iashchenko struct source_location { 20*ff3ed644SAleksandr Iashchenko const char *file_name; 21*ff3ed644SAleksandr Iashchenko uint32_t line; 22*ff3ed644SAleksandr Iashchenko uint32_t column; 23*ff3ed644SAleksandr Iashchenko }; 24*ff3ed644SAleksandr Iashchenko 25*ff3ed644SAleksandr Iashchenko static void __noreturn ubsan_panic(void) 26*ff3ed644SAleksandr Iashchenko { 27*ff3ed644SAleksandr Iashchenko #if defined(__KERNEL__) 28*ff3ed644SAleksandr Iashchenko panic(); 29*ff3ed644SAleksandr Iashchenko #elif defined(__LDELF__) 30*ff3ed644SAleksandr Iashchenko _ldelf_panic(2); 31*ff3ed644SAleksandr Iashchenko #else 32*ff3ed644SAleksandr Iashchenko # error "Unexpected build for ubsan" 33*ff3ed644SAleksandr Iashchenko #endif 34*ff3ed644SAleksandr Iashchenko /* 35*ff3ed644SAleksandr Iashchenko * _ldelf_panic and _utee_panic are not marked as noreturn, 36*ff3ed644SAleksandr Iashchenko * however they should be. To prevent "‘noreturn’ function 37*ff3ed644SAleksandr Iashchenko * does return" warning the while loop is used. 38*ff3ed644SAleksandr Iashchenko */ 39*ff3ed644SAleksandr Iashchenko while (1) 40*ff3ed644SAleksandr Iashchenko ; 41*ff3ed644SAleksandr Iashchenko } 42*ff3ed644SAleksandr Iashchenko 43*ff3ed644SAleksandr Iashchenko struct type_descriptor { 44*ff3ed644SAleksandr Iashchenko uint16_t type_kind; 45*ff3ed644SAleksandr Iashchenko uint16_t type_info; 46*ff3ed644SAleksandr Iashchenko char type_name[1]; 47*ff3ed644SAleksandr Iashchenko }; 48*ff3ed644SAleksandr Iashchenko 49*ff3ed644SAleksandr Iashchenko struct type_mismatch_data { 50*ff3ed644SAleksandr Iashchenko struct source_location loc; 51*ff3ed644SAleksandr Iashchenko struct type_descriptor *type; 52*ff3ed644SAleksandr Iashchenko unsigned long alignment; 53*ff3ed644SAleksandr Iashchenko unsigned char type_check_kind; 54*ff3ed644SAleksandr Iashchenko }; 55*ff3ed644SAleksandr Iashchenko 56*ff3ed644SAleksandr Iashchenko struct overflow_data { 57*ff3ed644SAleksandr Iashchenko struct source_location loc; 58*ff3ed644SAleksandr Iashchenko struct type_descriptor *type; 59*ff3ed644SAleksandr Iashchenko }; 60*ff3ed644SAleksandr Iashchenko 61*ff3ed644SAleksandr Iashchenko struct shift_out_of_bounds_data { 62*ff3ed644SAleksandr Iashchenko struct source_location loc; 63*ff3ed644SAleksandr Iashchenko struct type_descriptor *lhs_type; 64*ff3ed644SAleksandr Iashchenko struct type_descriptor *rhs_type; 65*ff3ed644SAleksandr Iashchenko }; 66*ff3ed644SAleksandr Iashchenko 67*ff3ed644SAleksandr Iashchenko struct out_of_bounds_data { 68*ff3ed644SAleksandr Iashchenko struct source_location loc; 69*ff3ed644SAleksandr Iashchenko struct type_descriptor *array_type; 70*ff3ed644SAleksandr Iashchenko struct type_descriptor *index_type; 71*ff3ed644SAleksandr Iashchenko }; 72*ff3ed644SAleksandr Iashchenko 73*ff3ed644SAleksandr Iashchenko struct unreachable_data { 74*ff3ed644SAleksandr Iashchenko struct source_location loc; 75*ff3ed644SAleksandr Iashchenko }; 76*ff3ed644SAleksandr Iashchenko 77*ff3ed644SAleksandr Iashchenko struct vla_bound_data { 78*ff3ed644SAleksandr Iashchenko struct source_location loc; 79*ff3ed644SAleksandr Iashchenko struct type_descriptor *type; 80*ff3ed644SAleksandr Iashchenko }; 81*ff3ed644SAleksandr Iashchenko 82*ff3ed644SAleksandr Iashchenko struct invalid_value_data { 83*ff3ed644SAleksandr Iashchenko struct source_location loc; 84*ff3ed644SAleksandr Iashchenko struct type_descriptor *type; 85*ff3ed644SAleksandr Iashchenko }; 86*ff3ed644SAleksandr Iashchenko 87*ff3ed644SAleksandr Iashchenko struct nonnull_arg_data { 88*ff3ed644SAleksandr Iashchenko struct source_location loc; 89*ff3ed644SAleksandr Iashchenko }; 90*ff3ed644SAleksandr Iashchenko 91*ff3ed644SAleksandr Iashchenko struct invalid_builtin_data { 92*ff3ed644SAleksandr Iashchenko struct source_location loc; 93*ff3ed644SAleksandr Iashchenko unsigned char kind; 94*ff3ed644SAleksandr Iashchenko }; 95*ff3ed644SAleksandr Iashchenko 96*ff3ed644SAleksandr Iashchenko /* 97*ff3ed644SAleksandr Iashchenko * When compiling with -fsanitize=undefined the compiler expects functions 98*ff3ed644SAleksandr Iashchenko * with the following signatures. The functions are never called directly, 99*ff3ed644SAleksandr Iashchenko * only when undefined behavior is detected in instrumented code. 100*ff3ed644SAleksandr Iashchenko */ 101*ff3ed644SAleksandr Iashchenko void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, 102*ff3ed644SAleksandr Iashchenko unsigned long ptr); 103*ff3ed644SAleksandr Iashchenko void __ubsan_handle_type_mismatch_v1(void *data_, void *ptr); 104*ff3ed644SAleksandr Iashchenko void __ubsan_handle_add_overflow(void *data_, void *lhs, void *rhs); 105*ff3ed644SAleksandr Iashchenko void __ubsan_handle_sub_overflow(void *data_, void *lhs, void *rhs); 106*ff3ed644SAleksandr Iashchenko void __ubsan_handle_mul_overflow(void *data_, void *lhs, void *rhs); 107*ff3ed644SAleksandr Iashchenko void __ubsan_handle_negate_overflow(void *data_, void *old_val); 108*ff3ed644SAleksandr Iashchenko void __ubsan_handle_divrem_overflow(void *data_, void *lhs, void *rhs); 109*ff3ed644SAleksandr Iashchenko void __ubsan_handle_pointer_overflow(void *data_, void *lhs, void *rhs); 110*ff3ed644SAleksandr Iashchenko void __ubsan_handle_shift_out_of_bounds(void *data_, void *lhs, void *rhs); 111*ff3ed644SAleksandr Iashchenko void __ubsan_handle_out_of_bounds(void *data_, void *idx); 112*ff3ed644SAleksandr Iashchenko void __ubsan_handle_builtin_unreachable(void *data_); 113*ff3ed644SAleksandr Iashchenko void __ubsan_handle_missing_return(void *data_); 114*ff3ed644SAleksandr Iashchenko void __ubsan_handle_vla_bound_not_positive(void *data_, void *bound); 115*ff3ed644SAleksandr Iashchenko void __ubsan_handle_load_invalid_value(void *data_, void *val); 116*ff3ed644SAleksandr Iashchenko void __ubsan_handle_nonnull_arg(void *data_ 117*ff3ed644SAleksandr Iashchenko #if __GCC_VERSION < 60000 118*ff3ed644SAleksandr Iashchenko , size_t arg_no 119*ff3ed644SAleksandr Iashchenko #endif 120*ff3ed644SAleksandr Iashchenko ); 121*ff3ed644SAleksandr Iashchenko void __ubsan_handle_invalid_builtin(void *data_); 122*ff3ed644SAleksandr Iashchenko 123*ff3ed644SAleksandr Iashchenko static bool should_panic = true; 124*ff3ed644SAleksandr Iashchenko 125*ff3ed644SAleksandr Iashchenko static void ubsan_handle_error(const char *func, struct source_location *loc, 126*ff3ed644SAleksandr Iashchenko bool panic_flag) 127*ff3ed644SAleksandr Iashchenko { 128*ff3ed644SAleksandr Iashchenko const char *f = func; 129*ff3ed644SAleksandr Iashchenko const char func_prefix[] = "__ubsan_handle"; 130*ff3ed644SAleksandr Iashchenko 131*ff3ed644SAleksandr Iashchenko if (!memcmp(f, func_prefix, sizeof(func_prefix) - 1)) 132*ff3ed644SAleksandr Iashchenko f += sizeof(func_prefix); 133*ff3ed644SAleksandr Iashchenko 134*ff3ed644SAleksandr Iashchenko EMSG_RAW("Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32, 135*ff3ed644SAleksandr Iashchenko f, loc->file_name, loc->line, loc->column); 136*ff3ed644SAleksandr Iashchenko 137*ff3ed644SAleksandr Iashchenko if (panic_flag) 138*ff3ed644SAleksandr Iashchenko ubsan_panic(); 139*ff3ed644SAleksandr Iashchenko } 140*ff3ed644SAleksandr Iashchenko 141*ff3ed644SAleksandr Iashchenko void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, 142*ff3ed644SAleksandr Iashchenko unsigned long ptr __unused) 143*ff3ed644SAleksandr Iashchenko { 144*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 145*ff3ed644SAleksandr Iashchenko } 146*ff3ed644SAleksandr Iashchenko 147*ff3ed644SAleksandr Iashchenko void __ubsan_handle_type_mismatch_v1(void *data_, void *ptr __unused) 148*ff3ed644SAleksandr Iashchenko { 149*ff3ed644SAleksandr Iashchenko struct type_mismatch_data *data = data_; 150*ff3ed644SAleksandr Iashchenko 151*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 152*ff3ed644SAleksandr Iashchenko } 153*ff3ed644SAleksandr Iashchenko 154*ff3ed644SAleksandr Iashchenko void __ubsan_handle_add_overflow(void *data_, void *lhs __unused, 155*ff3ed644SAleksandr Iashchenko void *rhs __unused) 156*ff3ed644SAleksandr Iashchenko { 157*ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_; 158*ff3ed644SAleksandr Iashchenko 159*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 160*ff3ed644SAleksandr Iashchenko } 161*ff3ed644SAleksandr Iashchenko 162*ff3ed644SAleksandr Iashchenko void __ubsan_handle_sub_overflow(void *data_, void *lhs __unused, 163*ff3ed644SAleksandr Iashchenko void *rhs __unused) 164*ff3ed644SAleksandr Iashchenko { 165*ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_; 166*ff3ed644SAleksandr Iashchenko 167*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 168*ff3ed644SAleksandr Iashchenko } 169*ff3ed644SAleksandr Iashchenko 170*ff3ed644SAleksandr Iashchenko void __ubsan_handle_mul_overflow(void *data_, void *lhs __unused, 171*ff3ed644SAleksandr Iashchenko void *rhs __unused) 172*ff3ed644SAleksandr Iashchenko { 173*ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_; 174*ff3ed644SAleksandr Iashchenko 175*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 176*ff3ed644SAleksandr Iashchenko } 177*ff3ed644SAleksandr Iashchenko 178*ff3ed644SAleksandr Iashchenko void __ubsan_handle_negate_overflow(void *data_, void *old_val __unused) 179*ff3ed644SAleksandr Iashchenko { 180*ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_; 181*ff3ed644SAleksandr Iashchenko 182*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 183*ff3ed644SAleksandr Iashchenko } 184*ff3ed644SAleksandr Iashchenko 185*ff3ed644SAleksandr Iashchenko void __ubsan_handle_divrem_overflow(void *data_, void *lhs __unused, 186*ff3ed644SAleksandr Iashchenko void *rhs __unused) 187*ff3ed644SAleksandr Iashchenko { 188*ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_; 189*ff3ed644SAleksandr Iashchenko 190*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 191*ff3ed644SAleksandr Iashchenko } 192*ff3ed644SAleksandr Iashchenko 193*ff3ed644SAleksandr Iashchenko void __ubsan_handle_pointer_overflow(void *data_, void *lhs __unused, 194*ff3ed644SAleksandr Iashchenko void *rhs __unused) 195*ff3ed644SAleksandr Iashchenko { 196*ff3ed644SAleksandr Iashchenko struct overflow_data *data = data_; 197*ff3ed644SAleksandr Iashchenko 198*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 199*ff3ed644SAleksandr Iashchenko } 200*ff3ed644SAleksandr Iashchenko 201*ff3ed644SAleksandr Iashchenko void __ubsan_handle_shift_out_of_bounds(void *data_, void *lhs __unused, 202*ff3ed644SAleksandr Iashchenko void *rhs __unused) 203*ff3ed644SAleksandr Iashchenko { 204*ff3ed644SAleksandr Iashchenko struct shift_out_of_bounds_data *data = data_; 205*ff3ed644SAleksandr Iashchenko 206*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 207*ff3ed644SAleksandr Iashchenko } 208*ff3ed644SAleksandr Iashchenko 209*ff3ed644SAleksandr Iashchenko void __ubsan_handle_out_of_bounds(void *data_, void *idx __unused) 210*ff3ed644SAleksandr Iashchenko { 211*ff3ed644SAleksandr Iashchenko struct out_of_bounds_data *data = data_; 212*ff3ed644SAleksandr Iashchenko 213*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 214*ff3ed644SAleksandr Iashchenko } 215*ff3ed644SAleksandr Iashchenko 216*ff3ed644SAleksandr Iashchenko void __noreturn __ubsan_handle_builtin_unreachable(void *data_) 217*ff3ed644SAleksandr Iashchenko { 218*ff3ed644SAleksandr Iashchenko struct unreachable_data *data = data_; 219*ff3ed644SAleksandr Iashchenko 220*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, false); 221*ff3ed644SAleksandr Iashchenko ubsan_panic(); 222*ff3ed644SAleksandr Iashchenko } 223*ff3ed644SAleksandr Iashchenko 224*ff3ed644SAleksandr Iashchenko void __noreturn __ubsan_handle_missing_return(void *data_) 225*ff3ed644SAleksandr Iashchenko { 226*ff3ed644SAleksandr Iashchenko struct unreachable_data *data = data_; 227*ff3ed644SAleksandr Iashchenko 228*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, false); 229*ff3ed644SAleksandr Iashchenko ubsan_panic(); 230*ff3ed644SAleksandr Iashchenko } 231*ff3ed644SAleksandr Iashchenko 232*ff3ed644SAleksandr Iashchenko void __ubsan_handle_vla_bound_not_positive(void *data_, void *bound __unused) 233*ff3ed644SAleksandr Iashchenko { 234*ff3ed644SAleksandr Iashchenko struct vla_bound_data *data = data_; 235*ff3ed644SAleksandr Iashchenko 236*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 237*ff3ed644SAleksandr Iashchenko } 238*ff3ed644SAleksandr Iashchenko 239*ff3ed644SAleksandr Iashchenko void __ubsan_handle_load_invalid_value(void *data_, void *val __unused) 240*ff3ed644SAleksandr Iashchenko { 241*ff3ed644SAleksandr Iashchenko struct invalid_value_data *data = data_; 242*ff3ed644SAleksandr Iashchenko 243*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 244*ff3ed644SAleksandr Iashchenko } 245*ff3ed644SAleksandr Iashchenko 246*ff3ed644SAleksandr Iashchenko void __ubsan_handle_nonnull_arg(void *data_ 247*ff3ed644SAleksandr Iashchenko #if __GCC_VERSION < 60000 248*ff3ed644SAleksandr Iashchenko , size_t arg_no __unused 249*ff3ed644SAleksandr Iashchenko #endif 250*ff3ed644SAleksandr Iashchenko ) 251*ff3ed644SAleksandr Iashchenko { 252*ff3ed644SAleksandr Iashchenko struct nonnull_arg_data *data = data_; 253*ff3ed644SAleksandr Iashchenko 254*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 255*ff3ed644SAleksandr Iashchenko } 256*ff3ed644SAleksandr Iashchenko 257*ff3ed644SAleksandr Iashchenko void __ubsan_handle_invalid_builtin(void *data_) 258*ff3ed644SAleksandr Iashchenko { 259*ff3ed644SAleksandr Iashchenko struct invalid_builtin_data *data = data_; 260*ff3ed644SAleksandr Iashchenko 261*ff3ed644SAleksandr Iashchenko ubsan_handle_error(__func__, &data->loc, should_panic); 262*ff3ed644SAleksandr Iashchenko } 263