xref: /linux/lib/ubsan.h (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
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