diff options
author | Kees Cook | 2024-04-24 15:40:29 -0700 |
---|---|---|
committer | Kees Cook | 2024-04-24 15:45:38 -0700 |
commit | 2e431b23a13ce4459cf484c8f0b3218c7048b515 (patch) | |
tree | d1946fc55676c51e2b83fb1ffc4bd4fe102e6c60 /lib | |
parent | c209826737b733b4ccd38448d7b025bb128aaa8a (diff) |
ubsan: Avoid i386 UBSAN handler crashes with Clang
When generating Runtime Calls, Clang doesn't respect the -mregparm=3
option used on i386. Hopefully this will be fixed correctly in Clang 19:
https://github.com/llvm/llvm-project/pull/89707
but we need to fix this for earlier Clang versions today. Force the
calling convention to use non-register arguments.
Reported-by: Erhard Furtner <erhard_f@mailbox.org>
Closes: https://github.com/KSPP/linux/issues/350
Link: https://lore.kernel.org/r/20240424224026.it.216-kees@kernel.org
Acked-by: Nathan Chancellor <nathan@kernel.org>
Acked-by: Justin Stitt <justinstitt@google.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ubsan.h | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/lib/ubsan.h b/lib/ubsan.h index 50ef50811b7c..07e37d4429b4 100644 --- a/lib/ubsan.h +++ b/lib/ubsan.h @@ -124,19 +124,32 @@ typedef s64 s_max; typedef u64 u_max; #endif -void __ubsan_handle_add_overflow(void *data, void *lhs, void *rhs); -void __ubsan_handle_sub_overflow(void *data, void *lhs, void *rhs); -void __ubsan_handle_mul_overflow(void *data, void *lhs, void *rhs); -void __ubsan_handle_negate_overflow(void *_data, void *old_val); -void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs); -void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, void *ptr); -void __ubsan_handle_type_mismatch_v1(void *_data, void *ptr); -void __ubsan_handle_out_of_bounds(void *_data, void *index); -void __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs); -void __ubsan_handle_builtin_unreachable(void *_data); -void __ubsan_handle_load_invalid_value(void *_data, void *val); -void __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr, - unsigned long align, - unsigned long offset); +/* + * When generating Runtime Calls, Clang doesn't respect the -mregparm=3 + * option used on i386: https://github.com/llvm/llvm-project/issues/89670 + * Fix this for earlier Clang versions by forcing the calling convention + * to use non-register arguments. + */ +#if defined(CONFIG_X86_32) && \ + defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 190000 +# define ubsan_linkage asmlinkage +#else +# define ubsan_linkage +#endif + +void ubsan_linkage __ubsan_handle_add_overflow(void *data, void *lhs, void *rhs); +void ubsan_linkage __ubsan_handle_sub_overflow(void *data, void *lhs, void *rhs); +void ubsan_linkage __ubsan_handle_mul_overflow(void *data, void *lhs, void *rhs); +void ubsan_linkage __ubsan_handle_negate_overflow(void *_data, void *old_val); +void ubsan_linkage __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs); +void ubsan_linkage __ubsan_handle_type_mismatch(struct type_mismatch_data *data, void *ptr); +void ubsan_linkage __ubsan_handle_type_mismatch_v1(void *_data, void *ptr); +void ubsan_linkage __ubsan_handle_out_of_bounds(void *_data, void *index); +void ubsan_linkage __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs); +void ubsan_linkage __ubsan_handle_builtin_unreachable(void *_data); +void ubsan_linkage __ubsan_handle_load_invalid_value(void *_data, void *val); +void ubsan_linkage __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr, + unsigned long align, + unsigned long offset); #endif |