Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1739700
| From | tip-bot for Eric Biggers <tipbot@zytor.com> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [tip:x86/fpu] x86/fpu: Don't let userspace set bogus xcomp_bv |
| Date | 2017-09-26 10:50 +0200 |
| Message-ID | <utTIZ-2nL-7@gated-at.bofh.it> (permalink) |
| References | <usAfn-xX-11@gated-at.bofh.it> <usSm0-3wU-65@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
Commit-ID: 814fb7bb7db5433757d76f4c4502c96fc53b0b5e
Gitweb: http://git.kernel.org/tip/814fb7bb7db5433757d76f4c4502c96fc53b0b5e
Author: Eric Biggers <ebiggers@google.com>
AuthorDate: Sat, 23 Sep 2017 15:00:07 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 25 Sep 2017 09:26:32 +0200
x86/fpu: Don't let userspace set bogus xcomp_bv
On x86, userspace can use the ptrace() or rt_sigreturn() system calls to
set a task's extended state (xstate) or "FPU" registers. ptrace() can
set them for another task using the PTRACE_SETREGSET request with
NT_X86_XSTATE, while rt_sigreturn() can set them for the current task.
In either case, registers can be set to any value, but the kernel
assumes that the XSAVE area itself remains valid in the sense that the
CPU can restore it.
However, in the case where the kernel is using the uncompacted xstate
format (which it does whenever the XSAVES instruction is unavailable),
it was possible for userspace to set the xcomp_bv field in the
xstate_header to an arbitrary value. However, all bits in that field
are reserved in the uncompacted case, so when switching to a task with
nonzero xcomp_bv, the XRSTOR instruction failed with a #GP fault. This
caused the WARN_ON_FPU(err) in copy_kernel_to_xregs() to be hit. In
addition, since the error is otherwise ignored, the FPU registers from
the task previously executing on the CPU were leaked.
Fix the bug by checking that the user-supplied value of xcomp_bv is 0 in
the uncompacted case, and returning an error otherwise.
The reason for validating xcomp_bv rather than simply overwriting it
with 0 is that we want userspace to see an error if it (incorrectly)
provides an XSAVE area in compacted format rather than in uncompacted
format.
Note that as before, in case of error we clear the task's FPU state.
This is perhaps non-ideal, especially for PTRACE_SETREGSET; it might be
better to return an error before changing anything. But it seems the
"clear on error" behavior is fine for now, and it's a little tricky to
do otherwise because it would mean we couldn't simply copy the full
userspace state into kernel memory in one __copy_from_user().
This bug was found by syzkaller, which hit the above-mentioned
WARN_ON_FPU():
WARNING: CPU: 1 PID: 0 at ./arch/x86/include/asm/fpu/internal.h:373 __switch_to+0x5b5/0x5d0
CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.13.0 #453
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: ffff9ba2bc8e42c0 task.stack: ffffa78cc036c000
RIP: 0010:__switch_to+0x5b5/0x5d0
RSP: 0000:ffffa78cc08bbb88 EFLAGS: 00010082
RAX: 00000000fffffffe RBX: ffff9ba2b8bf2180 RCX: 00000000c0000100
RDX: 00000000ffffffff RSI: 000000005cb10700 RDI: ffff9ba2b8bf36c0
RBP: ffffa78cc08bbbd0 R08: 00000000929fdf46 R09: 0000000000000001
R10: 0000000000000000 R11: 0000000000000000 R12: ffff9ba2bc8e42c0
R13: 0000000000000000 R14: ffff9ba2b8bf3680 R15: ffff9ba2bf5d7b40
FS: 00007f7e5cb10700(0000) GS:ffff9ba2bf400000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000004005cc CR3: 0000000079fd5000 CR4: 00000000001406e0
Call Trace:
Code: 84 00 00 00 00 00 e9 11 fd ff ff 0f ff 66 0f 1f 84 00 00 00 00 00 e9 e7 fa ff ff 0f ff 66 0f 1f 84 00 00 00 00 00 e9 c2 fa ff ff <0f> ff 66 0f 1f 84 00 00 00 00 00 e9 d4 fc ff ff 66 66 2e 0f 1f
Here is a C reproducer. The expected behavior is that the program spin
forever with no output. However, on a buggy kernel running on a
processor with the "xsave" feature but without the "xsaves" feature
(e.g. Sandy Bridge through Broadwell for Intel), within a second or two
the program reports that the xmm registers were corrupted, i.e. were not
restored correctly. With CONFIG_X86_DEBUG_FPU=y it also hits the above
kernel warning.
#define _GNU_SOURCE
#include <stdbool.h>
#include <inttypes.h>
#include <linux/elf.h>
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int pid = fork();
uint64_t xstate[512];
struct iovec iov = { .iov_base = xstate, .iov_len = sizeof(xstate) };
if (pid == 0) {
bool tracee = true;
for (int i = 0; i < sysconf(_SC_NPROCESSORS_ONLN) && tracee; i++)
tracee = (fork() != 0);
uint32_t xmm0[4] = { [0 ... 3] = tracee ? 0x00000000 : 0xDEADBEEF };
asm volatile(" movdqu %0, %%xmm0\n"
" mov %0, %%rbx\n"
"1: movdqu %%xmm0, %0\n"
" mov %0, %%rax\n"
" cmp %%rax, %%rbx\n"
" je 1b\n"
: "+m" (xmm0) : : "rax", "rbx", "xmm0");
printf("BUG: xmm registers corrupted! tracee=%d, xmm0=%08X%08X%08X%08X\n",
tracee, xmm0[0], xmm0[1], xmm0[2], xmm0[3]);
} else {
usleep(100000);
ptrace(PTRACE_ATTACH, pid, 0, 0);
wait(NULL);
ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov);
xstate[65] = -1;
ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov);
ptrace(PTRACE_CONT, pid, 0, 0);
wait(NULL);
}
return 1;
}
Note: the program only tests for the bug using the ptrace() system call.
The bug can also be reproduced using the rt_sigreturn() system call, but
only when called from a 32-bit program, since for 64-bit programs the
kernel restores the FPU state from the signal frame by doing XRSTOR
directly from userspace memory (with proper error checking).
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Rik van Riel <riel@redhat.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: <stable@vger.kernel.org> [v3.17+]
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Eric Biggers <ebiggers3@gmail.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Kevin Hao <haokexin@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Michael Halcrow <mhalcrow@google.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Wanpeng Li <wanpeng.li@hotmail.com>
Cc: Yu-cheng Yu <yu-cheng.yu@intel.com>
Cc: kernel-hardening@lists.openwall.com
Fixes: 0b29643a5843 ("x86/xsaves: Change compacted format xsave area header")
Link: http://lkml.kernel.org/r/20170922174156.16780-2-ebiggers3@gmail.com
Link: http://lkml.kernel.org/r/20170923130016.21448-25-mingo@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/fpu/regset.c | 4 ++++
arch/x86/kernel/fpu/signal.c | 9 +++++++--
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c
index 19a7385..c764f74 100644
--- a/arch/x86/kernel/fpu/regset.c
+++ b/arch/x86/kernel/fpu/regset.c
@@ -141,6 +141,10 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
ret = copy_user_to_xstate(xsave, ubuf);
} else {
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1);
+
+ /* xcomp_bv must be 0 when using uncompacted format */
+ if (!ret && xsave->header.xcomp_bv)
+ ret = -EINVAL;
}
/*
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index 629106e..da68ea1 100644
--- a/arch/x86/kernel/fpu/signal.c
+++ b/arch/x86/kernel/fpu/signal.c
@@ -324,11 +324,16 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
*/
fpu__drop(fpu);
- if (using_compacted_format())
+ if (using_compacted_format()) {
err = copy_user_to_xstate(&fpu->state.xsave, buf_fx);
- else
+ } else {
err = __copy_from_user(&fpu->state.xsave, buf_fx, state_size);
+ /* xcomp_bv must be 0 when using uncompacted format */
+ if (!err && state_size > offsetof(struct xregs_state, header) && fpu->state.xsave.header.xcomp_bv)
+ err = -EINVAL;
+ }
+
if (err || __copy_from_user(&env, buf, sizeof(env))) {
fpstate_init(&fpu->state);
trace_x86_fpu_init_state(fpu);
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[PATCH 00/33] x86 FPU fixes and cleanups for v4.14 Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[PATCH 19/33] x86/fpu: Decouple fpregs_activate()/fpregs_deactivate() from fpu->fpregs_active Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Decouple fpregs_activate()/fpregs_deactivate() from fpu->fpregs_active tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 15/33] x86/fpu: Simplify fpu->fpregs_active use Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Simplify fpu->fpregs_active use tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 26/33] x86/fpu: Reinitialize FPU registers if restoring FPU state fails Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Reinitialize FPU registers if restoring FPU state fails tip-bot for Eric Biggers <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 32/33] x86/fpu: Rename fpu__activate_curr() to fpu__initialize() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Rename fpu__activate_curr() to fpu__initialize() tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:50 +0200
[PATCH 31/33] x86/fpu: Simplify and speed up fpu__copy() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Simplify and speed up fpu__copy() tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:50 +0200
[PATCH 21/33] x86/fpu: Add FPU state copying quirk to handle XRSTOR failure on Intel Skylake CPUs Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Add FPU state copying quirk to handle XRSTOR failure on Intel Skylake CPUs tip-bot for Rik van Riel <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 13/33] x86/fpu: Remove 'kbuf' parameter from the copy_user_to_xstate() API Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Remove 'kbuf' parameter from the copy_user_to_xstate() API tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 33/33] x86/fpu: Rename fpu__activate_fpstate_read/write() to fpu__read/write() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[PATCH 02/33] x86/fpu: Split copy_xstate_to_user() into copy_xstate_to_kernel() & copy_xstate_to_user() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Split copy_xstate_to_user() into copy_xstate_to_kernel() & copy_xstate_to_user() tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:30 +0200
[PATCH 16/33] x86/fpu: Make the fpu state change in fpu__clear() scheduler-atomic Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Make the fpu state change in fpu__clear() scheduler-atomic tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 14/33] x86/fpu: Flip the parameter order in copy_*_to_xstate() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Flip the parameter order in copy_*_to_xstate() tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 11/33] x86/fpu: Split copy_user_to_xstate() into copy_kernel_to_xstate() & copy_user_to_xstate() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Split copy_user_to_xstate() into copy_kernel_to_xstate() & copy_user_to_xstate() tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 07/33] x86/fpu: Remove the 'start_pos' parameter from the __copy_xstate_to_*() functions Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Remove the 'start_pos' parameter from the __copy_xstate_to_*() functions tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 01/33] x86/fpu: Rename copyin_to_xsaves()/copyout_from_xsaves() to copy_user_to_xstate()/copy_xstate_to_user() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Rename copyin_to_xsaves()/copyout_from_xsaves() to copy_user_to_xstate()/copy_xstate_to_user() tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:30 +0200
[PATCH 29/33] x86/fpu: Rename fpu::fpstate_active to fpu::initialized Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Rename fpu::fpstate_active to fpu::initialized tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:50 +0200
[PATCH 17/33] x86/fpu: Split the state handling in fpu__drop() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Split the state handling in fpu__drop() tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 09/33] x86/fpu: Change 'size_total' parameter to unsigned and standardize the size checks in copy_xstate_to_*() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Change 'size_total' parameter to unsigned and standardize the size checks in copy_xstate_to_*() tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 30/33] x86/fpu: Fix stale comments about lazy FPU logic Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Fix stale comments about lazy FPU logic tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:50 +0200
[PATCH 08/33] x86/fpu: Clarify parameter names in the copy_xstate_to_*() methods Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
Re: [PATCH 08/33] x86/fpu: Clarify parameter names in the copy_xstate_to_*() methods Thomas Gleixner <tglx@linutronix.de> - 2017-09-25 22:00 +0200
Re: [PATCH 08/33] x86/fpu: Clarify parameter names in the copy_xstate_to_*() methods Thomas Gleixner <tglx@linutronix.de> - 2017-09-25 22:10 +0200
[tip:x86/fpu] x86/fpu: Clarify parameter names in the copy_xstate_to_*() methods tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 20/33] x86/fpu: Remove struct fpu::fpregs_active Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Remove struct fpu::fpregs_active tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 03/33] x86/fpu: Remove 'ubuf' parameter from the copy_xstate_to_kernel() APIs Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Remove 'ubuf' parameter from the copy_xstate_to_kernel() APIs tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:30 +0200
[PATCH 23/33] x86/fpu: Turn WARN_ON() in context switch into WARN_ON_FPU() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Turn WARN_ON() in context switch into WARN_ON_FPU() tip-bot for Andi Kleen <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 22/33] x86/fpu: Fix boolreturn.cocci warnings Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Fix boolreturn.cocci warnings tip-bot for kbuild test robot <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 06/33] x86/fpu: Clean up the parameter definitions of copy_xstate_to_*() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Clean up the parameter definitions of copy_xstate_to_*() tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 04/33] x86/fpu: Remove 'kbuf' parameter from the copy_xstate_to_user() APIs Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Remove 'kbuf' parameter from the copy_xstate_to_user() APIs tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 05/33] x86/fpu: Clean up parameter order in the copy_xstate_to_*() APIs Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Clean up parameter order in the copy_xstate_to_*() APIs tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 24/33] x86/fpu: Don't let userspace set bogus xcomp_bv Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Don't let userspace set bogus xcomp_bv tip-bot for Eric Biggers <tipbot@zytor.com> - 2017-09-26 10:50 +0200
[PATCH 18/33] x86/fpu: Change fpu->fpregs_active users to fpu->fpstate_active Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Change fpu->fpregs_active users to fpu->fpstate_active tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 27/33] x86/fpu: Simplify fpu__activate_fpstate_read() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Fix fpu__activate_fpstate_read() and update comments tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 12/33] x86/fpu: Remove 'ubuf' parameter from the copy_kernel_to_xstate() API Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Remove 'ubuf' parameter from the copy_kernel_to_xstate() API tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
[PATCH 25/33] x86/fpu: Tighten validation of user-supplied xstate_header Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[PATCH 28/33] x86/fpu: Remove fpu__current_fpstate_write_begin/end() Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
[tip:x86/fpu] x86/fpu: Remove fpu__current_fpstate_write_begin/end() tip-bot for Ingo Molnar <tipbot@zytor.com> - 2017-09-26 10:40 +0200
Re: [PATCH 00/33] x86 FPU fixes and cleanups for v4.14 Ingo Molnar <mingo@kernel.org> - 2017-09-23 15:10 +0200
Re: [PATCH 00/33] x86 FPU fixes and cleanups for v4.14 Juergen Gross <jgross@suse.com> - 2017-09-23 17:10 +0200
Re: [PATCH 00/33] x86 FPU fixes and cleanups for v4.14 Ingo Molnar <mingo@kernel.org> - 2017-09-24 01:30 +0200
csiph-web