1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2c6d30853SAndrey Ryabinin #ifndef _LIB_UBSAN_H 3c6d30853SAndrey Ryabinin #define _LIB_UBSAN_H 4c6d30853SAndrey Ryabinin 525b84002SKees Cook /* 625b84002SKees Cook * ABI defined by Clang's UBSAN enum SanitizerHandler: 725b84002SKees Cook * https://github.com/llvm/llvm-project/blob/release/16.x/clang/lib/CodeGen/CodeGenFunction.h#L113 825b84002SKees Cook */ 925b84002SKees Cook enum ubsan_checks { 1025b84002SKees Cook ubsan_add_overflow, 1125b84002SKees Cook ubsan_builtin_unreachable, 1225b84002SKees Cook ubsan_cfi_check_fail, 1325b84002SKees Cook ubsan_divrem_overflow, 1425b84002SKees Cook ubsan_dynamic_type_cache_miss, 1525b84002SKees Cook ubsan_float_cast_overflow, 1625b84002SKees Cook ubsan_function_type_mismatch, 1725b84002SKees Cook ubsan_implicit_conversion, 1825b84002SKees Cook ubsan_invalid_builtin, 1925b84002SKees Cook ubsan_invalid_objc_cast, 2025b84002SKees Cook ubsan_load_invalid_value, 2125b84002SKees Cook ubsan_missing_return, 2225b84002SKees Cook ubsan_mul_overflow, 2325b84002SKees Cook ubsan_negate_overflow, 2425b84002SKees Cook ubsan_nullability_arg, 2525b84002SKees Cook ubsan_nullability_return, 2625b84002SKees Cook ubsan_nonnull_arg, 2725b84002SKees Cook ubsan_nonnull_return, 2825b84002SKees Cook ubsan_out_of_bounds, 2925b84002SKees Cook ubsan_pointer_overflow, 3025b84002SKees Cook ubsan_shift_out_of_bounds, 3125b84002SKees Cook ubsan_sub_overflow, 3225b84002SKees Cook ubsan_type_mismatch, 3325b84002SKees Cook ubsan_alignment_assumption, 3425b84002SKees Cook ubsan_vla_bound_not_positive, 3525b84002SKees Cook }; 3625b84002SKees Cook 37c6d30853SAndrey Ryabinin enum { 38c6d30853SAndrey Ryabinin type_kind_int = 0, 39c6d30853SAndrey Ryabinin type_kind_float = 1, 40c6d30853SAndrey Ryabinin type_unknown = 0xffff 41c6d30853SAndrey Ryabinin }; 42c6d30853SAndrey Ryabinin 43c6d30853SAndrey Ryabinin struct type_descriptor { 44c6d30853SAndrey Ryabinin u16 type_kind; 45c6d30853SAndrey Ryabinin u16 type_info; 46c2098267SKees Cook char type_name[]; 47c6d30853SAndrey Ryabinin }; 48c6d30853SAndrey Ryabinin 49c6d30853SAndrey Ryabinin struct source_location { 50c6d30853SAndrey Ryabinin const char *file_name; 51c6d30853SAndrey Ryabinin union { 52c6d30853SAndrey Ryabinin unsigned long reported; 53c6d30853SAndrey Ryabinin struct { 54c6d30853SAndrey Ryabinin u32 line; 55c6d30853SAndrey Ryabinin u32 column; 56c6d30853SAndrey Ryabinin }; 57c6d30853SAndrey Ryabinin }; 58c6d30853SAndrey Ryabinin }; 59c6d30853SAndrey Ryabinin 60c6d30853SAndrey Ryabinin struct overflow_data { 61c6d30853SAndrey Ryabinin struct source_location location; 62c6d30853SAndrey Ryabinin struct type_descriptor *type; 63c6d30853SAndrey Ryabinin }; 64c6d30853SAndrey Ryabinin 65c6d30853SAndrey Ryabinin struct type_mismatch_data { 66c6d30853SAndrey Ryabinin struct source_location location; 67c6d30853SAndrey Ryabinin struct type_descriptor *type; 68c6d30853SAndrey Ryabinin unsigned long alignment; 69c6d30853SAndrey Ryabinin unsigned char type_check_kind; 70c6d30853SAndrey Ryabinin }; 71c6d30853SAndrey Ryabinin 7242440c1fSAndrey Ryabinin struct type_mismatch_data_v1 { 7342440c1fSAndrey Ryabinin struct source_location location; 7442440c1fSAndrey Ryabinin struct type_descriptor *type; 7542440c1fSAndrey Ryabinin unsigned char log_alignment; 7642440c1fSAndrey Ryabinin unsigned char type_check_kind; 7742440c1fSAndrey Ryabinin }; 7842440c1fSAndrey Ryabinin 7942440c1fSAndrey Ryabinin struct type_mismatch_data_common { 8042440c1fSAndrey Ryabinin struct source_location *location; 8142440c1fSAndrey Ryabinin struct type_descriptor *type; 8242440c1fSAndrey Ryabinin unsigned long alignment; 8342440c1fSAndrey Ryabinin unsigned char type_check_kind; 8442440c1fSAndrey Ryabinin }; 8542440c1fSAndrey Ryabinin 86c6d30853SAndrey Ryabinin struct nonnull_arg_data { 87c6d30853SAndrey Ryabinin struct source_location location; 88c6d30853SAndrey Ryabinin struct source_location attr_location; 89c6d30853SAndrey Ryabinin int arg_index; 90c6d30853SAndrey Ryabinin }; 91c6d30853SAndrey Ryabinin 92c6d30853SAndrey Ryabinin struct out_of_bounds_data { 93c6d30853SAndrey Ryabinin struct source_location location; 94c6d30853SAndrey Ryabinin struct type_descriptor *array_type; 95c6d30853SAndrey Ryabinin struct type_descriptor *index_type; 96c6d30853SAndrey Ryabinin }; 97c6d30853SAndrey Ryabinin 98c6d30853SAndrey Ryabinin struct shift_out_of_bounds_data { 99c6d30853SAndrey Ryabinin struct source_location location; 100c6d30853SAndrey Ryabinin struct type_descriptor *lhs_type; 101c6d30853SAndrey Ryabinin struct type_descriptor *rhs_type; 102c6d30853SAndrey Ryabinin }; 103c6d30853SAndrey Ryabinin 104c6d30853SAndrey Ryabinin struct unreachable_data { 105c6d30853SAndrey Ryabinin struct source_location location; 106c6d30853SAndrey Ryabinin }; 107c6d30853SAndrey Ryabinin 108c6d30853SAndrey Ryabinin struct invalid_value_data { 109c6d30853SAndrey Ryabinin struct source_location location; 110c6d30853SAndrey Ryabinin struct type_descriptor *type; 111c6d30853SAndrey Ryabinin }; 112c6d30853SAndrey Ryabinin 11328abcc96SNathan Chancellor struct alignment_assumption_data { 11428abcc96SNathan Chancellor struct source_location location; 11528abcc96SNathan Chancellor struct source_location assumption_location; 11628abcc96SNathan Chancellor struct type_descriptor *type; 11728abcc96SNathan Chancellor }; 11828abcc96SNathan Chancellor 119c12d3362SArd Biesheuvel #if defined(CONFIG_ARCH_SUPPORTS_INT128) 120c6d30853SAndrey Ryabinin typedef __int128 s_max; 121c6d30853SAndrey Ryabinin typedef unsigned __int128 u_max; 122c6d30853SAndrey Ryabinin #else 123c6d30853SAndrey Ryabinin typedef s64 s_max; 124c6d30853SAndrey Ryabinin typedef u64 u_max; 125c6d30853SAndrey Ryabinin #endif 126c6d30853SAndrey Ryabinin 127*2e431b23SKees Cook /* 128*2e431b23SKees Cook * When generating Runtime Calls, Clang doesn't respect the -mregparm=3 129*2e431b23SKees Cook * option used on i386: https://github.com/llvm/llvm-project/issues/89670 130*2e431b23SKees Cook * Fix this for earlier Clang versions by forcing the calling convention 131*2e431b23SKees Cook * to use non-register arguments. 132*2e431b23SKees Cook */ 133*2e431b23SKees Cook #if defined(CONFIG_X86_32) && \ 134*2e431b23SKees Cook defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 190000 135*2e431b23SKees Cook # define ubsan_linkage asmlinkage 136*2e431b23SKees Cook #else 137*2e431b23SKees Cook # define ubsan_linkage 138*2e431b23SKees Cook #endif 139*2e431b23SKees Cook 140*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_add_overflow(void *data, void *lhs, void *rhs); 141*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_sub_overflow(void *data, void *lhs, void *rhs); 142*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_mul_overflow(void *data, void *lhs, void *rhs); 143*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_negate_overflow(void *_data, void *old_val); 144*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs); 145*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_type_mismatch(struct type_mismatch_data *data, void *ptr); 146*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_type_mismatch_v1(void *_data, void *ptr); 147*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_out_of_bounds(void *_data, void *index); 148*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs); 149*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_builtin_unreachable(void *_data); 150*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_load_invalid_value(void *_data, void *val); 151*2e431b23SKees Cook void ubsan_linkage __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr, 15226f15e5dSArnd Bergmann unsigned long align, 15326f15e5dSArnd Bergmann unsigned long offset); 15426f15e5dSArnd Bergmann 155c6d30853SAndrey Ryabinin #endif 156