| From d278f5b1d3e7debb5c28f2ac4eda8b5295896bef Mon Sep 17 00:00:00 2001 |
| From: Peter Zijlstra <peterz@infradead.org> |
| Date: Mon, 21 Oct 2019 15:11:49 +0200 |
| Subject: [PATCH] ubsan, x86: Annotate and allow |
| __ubsan_handle_shift_out_of_bounds() in uaccess regions |
| |
| commit 9a50dcaf0416a43e1fe411dc61a99c8333c90119 upstream. |
| |
| The new check_zeroed_user() function uses variable shifts inside of a |
| user_access_begin()/user_access_end() section and that results in GCC |
| emitting __ubsan_handle_shift_out_of_bounds() calls, even though |
| through value range analysis it would be able to see that the UB in |
| question is impossible. |
| |
| Annotate and whitelist this UBSAN function; continued use of |
| user_access_begin()/user_access_end() will undoubtedly result in |
| further uses of function. |
| |
| Reported-by: Randy Dunlap <rdunlap@infradead.org> |
| Tested-by: Randy Dunlap <rdunlap@infradead.org> |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Acked-by: Randy Dunlap <rdunlap@infradead.org> |
| Acked-by: Christian Brauner <christian.brauner@ubuntu.com> |
| Cc: Josh Poimboeuf <jpoimboe@redhat.com> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Stephen Rothwell <sfr@canb.auug.org.au> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: cyphar@cyphar.com |
| Cc: keescook@chromium.org |
| Cc: linux@rasmusvillemoes.dk |
| Fixes: f5a1a536fa14 ("lib: introduce copy_struct_from_user() helper") |
| Link: https://lkml.kernel.org/r/20191021131149.GA19358@hirez.programming.kicks-ass.net |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/lib/ubsan.c b/lib/ubsan.c |
| index e7d31735950d..0c4681118fcd 100644 |
| --- a/lib/ubsan.c |
| +++ b/lib/ubsan.c |
| @@ -374,9 +374,10 @@ void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, |
| struct type_descriptor *lhs_type = data->lhs_type; |
| char rhs_str[VALUE_LENGTH]; |
| char lhs_str[VALUE_LENGTH]; |
| + unsigned long ua_flags = user_access_save(); |
| |
| if (suppress_report(&data->location)) |
| - return; |
| + goto out; |
| |
| ubsan_prologue(&data->location, &flags); |
| |
| @@ -402,6 +403,8 @@ void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, |
| lhs_type->type_name); |
| |
| ubsan_epilogue(&flags); |
| +out: |
| + user_access_restore(ua_flags); |
| } |
| EXPORT_SYMBOL(__ubsan_handle_shift_out_of_bounds); |
| |
| diff --git a/tools/objtool/check.c b/tools/objtool/check.c |
| index 172f99195726..f2f284bd4c85 100644 |
| --- a/tools/objtool/check.c |
| +++ b/tools/objtool/check.c |
| @@ -485,6 +485,7 @@ static const char *uaccess_safe_builtin[] = { |
| "ubsan_type_mismatch_common", |
| "__ubsan_handle_type_mismatch", |
| "__ubsan_handle_type_mismatch_v1", |
| + "__ubsan_handle_shift_out_of_bounds", |
| /* misc */ |
| "csum_partial_copy_generic", |
| "__memcpy_mcsafe", |
| -- |
| 2.7.4 |
| |