ubsan: Avoid i386 UBSAN handler crashes with Clang
Subsystems (2)
PATCH v2 1/1 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.
---
Cc: Marco Elver <[email protected]>
Cc: Andrey Konovalov <[email protected]>
Cc: Andrey Ryabinin <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nick Desaulniers <[email protected]>
Cc: Bill Wendling <[email protected]>
Cc: Justin Stitt <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
v2:
- use email address in Reported-by
- link to upstream llvm bug in ubsan.h comment
- drop needless /**/
- explicitly test Clang version
v1: https://lore.kernel.org/lkml/[email protected]/
--- lib/ubsan.h | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-)
lib/ubsan.h +27 -14
@@ -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
Signature · 1 line
2.34.1
Quoted 9 lines · Kees Cook
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 <[email protected]>Signed-off-by Kees Cook <[email protected]>
Quoted 75 lines
---
Cc: Marco Elver <[email protected]>
Cc: Andrey Konovalov <[email protected]>
Cc: Andrey Ryabinin <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nick Desaulniers <[email protected]>
Cc: Bill Wendling <[email protected]>
Cc: Justin Stitt <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
v2:
- use email address in Reported-by
- link to upstream llvm bug inubsan.hcomment
- drop needless /**/
- explicitly test Clang version
v1: https://lore.kernel.org/lkml/[email protected]/--- lib/ubsan.h | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-)lib/ubsan.h +27
-14@@ -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 Signature · 1 line
2.34.1
Hi,
Quoted 51 lines · Kees Cook
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 <[email protected]>Signed-off-by Kees Cook <[email protected]>---
Cc: Marco Elver <[email protected]>
Cc: Andrey Konovalov <[email protected]>
Cc: Andrey Ryabinin <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nick Desaulniers <[email protected]>
Cc: Bill Wendling <[email protected]>
Cc: Justin Stitt <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
v2:
- use email address in Reported-by
- link to upstream llvm bug inubsan.hcomment
- drop needless /**/
- explicitly test Clang version
v1: https://lore.kernel.org/lkml/[email protected]/--- lib/ubsan.h | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-)lib/ubsan.h +0
-13@@ -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,
lib/ubsan.h typedef s64 s_max; · line 135
Quoted 10 lines
lib/ubsan.h +9
-1- 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
Clever.
Quoted 23 lines
lib/ubsan.h +18
-0+#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 Signature · 1 line
2.34.1
Thanks
Justin