]>
Commit | Line | Data |
---|---|---|
5d74b627 GKH |
1 | From 2a418cf3f5f1caf911af288e978d61c9844b0695 Mon Sep 17 00:00:00 2001 |
2 | From: Andy Lutomirski <luto@kernel.org> | |
3 | Date: Fri, 22 Feb 2019 17:17:04 -0800 | |
4 | Subject: x86/uaccess: Don't leak the AC flag into __put_user() value evaluation | |
5 | ||
6 | From: Andy Lutomirski <luto@kernel.org> | |
7 | ||
8 | commit 2a418cf3f5f1caf911af288e978d61c9844b0695 upstream. | |
9 | ||
10 | When calling __put_user(foo(), ptr), the __put_user() macro would call | |
11 | foo() in between __uaccess_begin() and __uaccess_end(). If that code | |
12 | were buggy, then those bugs would be run without SMAP protection. | |
13 | ||
14 | Fortunately, there seem to be few instances of the problem in the | |
15 | kernel. Nevertheless, __put_user() should be fixed to avoid doing this. | |
16 | Therefore, evaluate __put_user()'s argument before setting AC. | |
17 | ||
18 | This issue was noticed when an objtool hack by Peter Zijlstra complained | |
19 | about genregs_get() and I compared the assembly output to the C source. | |
20 | ||
21 | [ bp: Massage commit message and fixed up whitespace. ] | |
22 | ||
23 | Fixes: 11f1a4b9755f ("x86: reorganize SMAP handling in user space accesses") | |
24 | Signed-off-by: Andy Lutomirski <luto@kernel.org> | |
25 | Signed-off-by: Borislav Petkov <bp@suse.de> | |
26 | Acked-by: Linus Torvalds <torvalds@linux-foundation.org> | |
27 | Cc: Peter Zijlstra <peterz@infradead.org> | |
28 | Cc: Brian Gerst <brgerst@gmail.com> | |
29 | Cc: Josh Poimboeuf <jpoimboe@redhat.com> | |
30 | Cc: Denys Vlasenko <dvlasenk@redhat.com> | |
31 | Cc: stable@vger.kernel.org | |
32 | Link: http://lkml.kernel.org/r/20190225125231.845656645@infradead.org | |
33 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
34 | ||
35 | --- | |
36 | arch/x86/include/asm/uaccess.h | 7 ++++--- | |
37 | 1 file changed, 4 insertions(+), 3 deletions(-) | |
38 | ||
39 | --- a/arch/x86/include/asm/uaccess.h | |
40 | +++ b/arch/x86/include/asm/uaccess.h | |
41 | @@ -314,8 +314,7 @@ do { \ | |
42 | __put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \ | |
43 | break; \ | |
44 | case 8: \ | |
45 | - __put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval, \ | |
46 | - errret); \ | |
47 | + __put_user_asm_u64(x, ptr, retval, errret); \ | |
48 | break; \ | |
49 | default: \ | |
50 | __put_user_bad(); \ | |
51 | @@ -426,8 +425,10 @@ do { \ | |
52 | #define __put_user_nocheck(x, ptr, size) \ | |
53 | ({ \ | |
54 | int __pu_err; \ | |
55 | + __typeof__(*(ptr)) __pu_val; \ | |
56 | + __pu_val = x; \ | |
57 | __uaccess_begin(); \ | |
58 | - __put_user_size((x), (ptr), (size), __pu_err, -EFAULT); \ | |
59 | + __put_user_size(__pu_val, (ptr), (size), __pu_err, -EFAULT);\ | |
60 | __uaccess_end(); \ | |
61 | __builtin_expect(__pu_err, 0); \ | |
62 | }) |