From e6eebfeeaac2604136df9a77cdc13dac00f66c2c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 7 Nov 2014 16:41:40 -0800 Subject: [PATCH] 3.14-stable patches added patches: x86-fpu-__restore_xstate_sig-math_state_restore-needs-preempt_disable.patch x86-fpu-shift-drop_init_fpu-from-save_xstate_sig-to-handle_signal.patch x86-pageattr-prevent-overflow-in-slow_virt_to_phys-for-x86_pae.patch x86-reject-x32-executables-if-x32-abi-not-supported.patch x86_64-entry-filter-rflags.nt-on-entry-from-userspace.patch x86_64-entry-fix-out-of-bounds-read-on-sysenter.patch --- queue-3.14/series | 6 + ..._state_restore-needs-preempt_disable.patch | 38 ++++++ ...rom-save_xstate_sig-to-handle_signal.patch | 118 ++++++++++++++++++ ...low-in-slow_virt_to_phys-for-x86_pae.patch | 50 ++++++++ ...executables-if-x32-abi-not-supported.patch | 39 ++++++ ...er-rflags.nt-on-entry-from-userspace.patch | 116 +++++++++++++++++ ...y-fix-out-of-bounds-read-on-sysenter.patch | 45 +++++++ 7 files changed, 412 insertions(+) create mode 100644 queue-3.14/x86-fpu-__restore_xstate_sig-math_state_restore-needs-preempt_disable.patch create mode 100644 queue-3.14/x86-fpu-shift-drop_init_fpu-from-save_xstate_sig-to-handle_signal.patch create mode 100644 queue-3.14/x86-pageattr-prevent-overflow-in-slow_virt_to_phys-for-x86_pae.patch create mode 100644 queue-3.14/x86-reject-x32-executables-if-x32-abi-not-supported.patch create mode 100644 queue-3.14/x86_64-entry-filter-rflags.nt-on-entry-from-userspace.patch create mode 100644 queue-3.14/x86_64-entry-fix-out-of-bounds-read-on-sysenter.patch diff --git a/queue-3.14/series b/queue-3.14/series index 1e63f8a38ef..dcca329802c 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -27,3 +27,9 @@ ubifs-remove-mst_mutex.patch ubifs-fix-a-race-condition.patch ubifs-fix-free-log-space-calculation.patch vfs-fix-data-corruption-when-blocksize-pagesize-for-mmaped-data.patch +x86-reject-x32-executables-if-x32-abi-not-supported.patch +x86-fpu-__restore_xstate_sig-math_state_restore-needs-preempt_disable.patch +x86-fpu-shift-drop_init_fpu-from-save_xstate_sig-to-handle_signal.patch +x86_64-entry-filter-rflags.nt-on-entry-from-userspace.patch +x86_64-entry-fix-out-of-bounds-read-on-sysenter.patch +x86-pageattr-prevent-overflow-in-slow_virt_to_phys-for-x86_pae.patch diff --git a/queue-3.14/x86-fpu-__restore_xstate_sig-math_state_restore-needs-preempt_disable.patch b/queue-3.14/x86-fpu-__restore_xstate_sig-math_state_restore-needs-preempt_disable.patch new file mode 100644 index 00000000000..40d5cd0629d --- /dev/null +++ b/queue-3.14/x86-fpu-__restore_xstate_sig-math_state_restore-needs-preempt_disable.patch @@ -0,0 +1,38 @@ +From df24fb859a4e200d9324e2974229fbb7adf00aef Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Tue, 2 Sep 2014 19:57:17 +0200 +Subject: x86, fpu: __restore_xstate_sig()->math_state_restore() needs preempt_disable() + +From: Oleg Nesterov + +commit df24fb859a4e200d9324e2974229fbb7adf00aef upstream. + +Add preempt_disable() + preempt_enable() around math_state_restore() in +__restore_xstate_sig(). Otherwise __switch_to() after __thread_fpu_begin() +can overwrite fpu->state we are going to restore. + +Signed-off-by: Oleg Nesterov +Link: http://lkml.kernel.org/r/20140902175717.GA21649@redhat.com +Reviewed-by: Suresh Siddha +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/xsave.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/arch/x86/kernel/xsave.c ++++ b/arch/x86/kernel/xsave.c +@@ -399,8 +399,11 @@ int __restore_xstate_sig(void __user *bu + set_used_math(); + } + +- if (use_eager_fpu()) ++ if (use_eager_fpu()) { ++ preempt_disable(); + math_state_restore(); ++ preempt_enable(); ++ } + + return err; + } else { diff --git a/queue-3.14/x86-fpu-shift-drop_init_fpu-from-save_xstate_sig-to-handle_signal.patch b/queue-3.14/x86-fpu-shift-drop_init_fpu-from-save_xstate_sig-to-handle_signal.patch new file mode 100644 index 00000000000..4bac25a15aa --- /dev/null +++ b/queue-3.14/x86-fpu-shift-drop_init_fpu-from-save_xstate_sig-to-handle_signal.patch @@ -0,0 +1,118 @@ +From 66463db4fc5605d51c7bb81d009d5bf30a783a2c Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Tue, 2 Sep 2014 19:57:13 +0200 +Subject: x86, fpu: shift drop_init_fpu() from save_xstate_sig() to handle_signal() + +From: Oleg Nesterov + +commit 66463db4fc5605d51c7bb81d009d5bf30a783a2c upstream. + +save_xstate_sig()->drop_init_fpu() doesn't look right. setup_rt_frame() +can fail after that, in this case the next setup_rt_frame() triggered +by SIGSEGV won't save fpu simply because the old state was lost. This +obviously mean that fpu won't be restored after sys_rt_sigreturn() from +SIGSEGV handler. + +Shift drop_init_fpu() into !failed branch in handle_signal(). + +Test-case (needs -O2): + + #include + #include + #include + #include + #include + #include + #include + + volatile double D; + + void test(double d) + { + int pid = getpid(); + + for (D = d; D == d; ) { + /* sys_tkill(pid, SIGHUP); asm to avoid save/reload + * fp regs around "C" call */ + asm ("" : : "a"(200), "D"(pid), "S"(1)); + asm ("syscall" : : : "ax"); + } + + printf("ERR!!\n"); + } + + void sigh(int sig) + { + } + + char altstack[4096 * 10] __attribute__((aligned(4096))); + + void *tfunc(void *arg) + { + for (;;) { + mprotect(altstack, sizeof(altstack), PROT_READ); + mprotect(altstack, sizeof(altstack), PROT_READ|PROT_WRITE); + } + } + + int main(void) + { + stack_t st = { + .ss_sp = altstack, + .ss_size = sizeof(altstack), + .ss_flags = SS_ONSTACK, + }; + + struct sigaction sa = { + .sa_handler = sigh, + }; + + pthread_t pt; + + sigaction(SIGSEGV, &sa, NULL); + sigaltstack(&st, NULL); + sa.sa_flags = SA_ONSTACK; + sigaction(SIGHUP, &sa, NULL); + + pthread_create(&pt, NULL, tfunc, NULL); + + test(123.456); + return 0; + } + +Reported-by: Bean Anderson +Signed-off-by: Oleg Nesterov +Link: http://lkml.kernel.org/r/20140902175713.GA21646@redhat.com +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/signal.c | 5 +++++ + arch/x86/kernel/xsave.c | 2 -- + 2 files changed, 5 insertions(+), 2 deletions(-) + +--- a/arch/x86/kernel/signal.c ++++ b/arch/x86/kernel/signal.c +@@ -673,6 +673,11 @@ handle_signal(struct ksignal *ksig, stru + * handler too. + */ + regs->flags &= ~(X86_EFLAGS_DF|X86_EFLAGS_RF|X86_EFLAGS_TF); ++ /* ++ * Ensure the signal handler starts with the new fpu state. ++ */ ++ if (used_math()) ++ drop_init_fpu(current); + } + signal_setup_done(failed, ksig, test_thread_flag(TIF_SINGLESTEP)); + } +--- a/arch/x86/kernel/xsave.c ++++ b/arch/x86/kernel/xsave.c +@@ -268,8 +268,6 @@ int save_xstate_sig(void __user *buf, vo + if (use_fxsr() && save_xstate_epilog(buf_fx, ia32_fxstate)) + return -1; + +- drop_init_fpu(tsk); /* trigger finit */ +- + return 0; + } + diff --git a/queue-3.14/x86-pageattr-prevent-overflow-in-slow_virt_to_phys-for-x86_pae.patch b/queue-3.14/x86-pageattr-prevent-overflow-in-slow_virt_to_phys-for-x86_pae.patch new file mode 100644 index 00000000000..808284041bf --- /dev/null +++ b/queue-3.14/x86-pageattr-prevent-overflow-in-slow_virt_to_phys-for-x86_pae.patch @@ -0,0 +1,50 @@ +From d1cd1210834649ce1ca6bafe5ac25d2f40331343 Mon Sep 17 00:00:00 2001 +From: Dexuan Cui +Date: Wed, 29 Oct 2014 03:53:37 -0700 +Subject: x86, pageattr: Prevent overflow in slow_virt_to_phys() for X86_PAE + +From: Dexuan Cui + +commit d1cd1210834649ce1ca6bafe5ac25d2f40331343 upstream. + +pte_pfn() returns a PFN of long (32 bits in 32-PAE), so "long << +PAGE_SHIFT" will overflow for PFNs above 4GB. + +Due to this issue, some Linux 32-PAE distros, running as guests on Hyper-V, +with 5GB memory assigned, can't load the netvsc driver successfully and +hence the synthetic network device can't work (we can use the kernel parameter +mem=3000M to work around the issue). + +Cast pte_pfn() to phys_addr_t before shifting. + +Fixes: "commit d76565344512: x86, mm: Create slow_virt_to_phys()" +Signed-off-by: Dexuan Cui +Cc: K. Y. Srinivasan +Cc: Haiyang Zhang +Cc: gregkh@linuxfoundation.org +Cc: linux-mm@kvack.org +Cc: olaf@aepfle.de +Cc: apw@canonical.com +Cc: jasowang@redhat.com +Cc: dave.hansen@intel.com +Cc: riel@redhat.com +Cc: stable@vger.kernel.org +Link: http://lkml.kernel.org/r/1414580017-27444-1-git-send-email-decui@microsoft.com +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/mm/pageattr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/mm/pageattr.c ++++ b/arch/x86/mm/pageattr.c +@@ -405,7 +405,7 @@ phys_addr_t slow_virt_to_phys(void *__vi + psize = page_level_size(level); + pmask = page_level_mask(level); + offset = virt_addr & ~pmask; +- phys_addr = pte_pfn(*pte) << PAGE_SHIFT; ++ phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT; + return (phys_addr | offset); + } + EXPORT_SYMBOL_GPL(slow_virt_to_phys); diff --git a/queue-3.14/x86-reject-x32-executables-if-x32-abi-not-supported.patch b/queue-3.14/x86-reject-x32-executables-if-x32-abi-not-supported.patch new file mode 100644 index 00000000000..73cf271a6d1 --- /dev/null +++ b/queue-3.14/x86-reject-x32-executables-if-x32-abi-not-supported.patch @@ -0,0 +1,39 @@ +From 0e6d3112a4e95d55cf6dca88f298d5f4b8f29bd1 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sun, 7 Sep 2014 21:05:05 +0100 +Subject: x86: Reject x32 executables if x32 ABI not supported + +From: Ben Hutchings + +commit 0e6d3112a4e95d55cf6dca88f298d5f4b8f29bd1 upstream. + +It is currently possible to execve() an x32 executable on an x86_64 +kernel that has only ia32 compat enabled. However all its syscalls +will fail, even _exit(). This usually causes it to segfault. + +Change the ELF compat architecture check so that x32 executables are +rejected if we don't support the x32 ABI. + +Signed-off-by: Ben Hutchings +Link: http://lkml.kernel.org/r/1410120305.6822.9.camel@decadent.org.uk +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/elf.h | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/arch/x86/include/asm/elf.h ++++ b/arch/x86/include/asm/elf.h +@@ -155,8 +155,9 @@ do { \ + #define elf_check_arch(x) \ + ((x)->e_machine == EM_X86_64) + +-#define compat_elf_check_arch(x) \ +- (elf_check_arch_ia32(x) || (x)->e_machine == EM_X86_64) ++#define compat_elf_check_arch(x) \ ++ (elf_check_arch_ia32(x) || \ ++ (IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64)) + + #if __USER32_DS != __USER_DS + # error "The following code assumes __USER32_DS == __USER_DS" diff --git a/queue-3.14/x86_64-entry-filter-rflags.nt-on-entry-from-userspace.patch b/queue-3.14/x86_64-entry-filter-rflags.nt-on-entry-from-userspace.patch new file mode 100644 index 00000000000..524101f0221 --- /dev/null +++ b/queue-3.14/x86_64-entry-filter-rflags.nt-on-entry-from-userspace.patch @@ -0,0 +1,116 @@ +From 8c7aa698baca5e8f1ba9edb68081f1e7a1abf455 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Wed, 1 Oct 2014 11:49:04 -0700 +Subject: x86_64, entry: Filter RFLAGS.NT on entry from userspace + +From: Andy Lutomirski + +commit 8c7aa698baca5e8f1ba9edb68081f1e7a1abf455 upstream. + +The NT flag doesn't do anything in long mode other than causing IRET +to #GP. Oddly, CPL3 code can still set NT using popf. + +Entry via hardware or software interrupt clears NT automatically, so +the only relevant entries are fast syscalls. + +If user code causes kernel code to run with NT set, then there's at +least some (small) chance that it could cause trouble. For example, +user code could cause a call to EFI code with NT set, and who knows +what would happen? Apparently some games on Wine sometimes do +this (!), and, if an IRET return happens, they will segfault. That +segfault cannot be handled, because signal delivery fails, too. + +This patch programs the CPU to clear NT on entry via SYSCALL (both +32-bit and 64-bit, by my reading of the AMD APM), and it clears NT +in software on entry via SYSENTER. + +To save a few cycles, this borrows a trick from Jan Beulich in Xen: +it checks whether NT is set before trying to clear it. As a result, +it seems to have very little effect on SYSENTER performance on my +machine. + +There's another minor bug fix in here: it looks like the CFI +annotations were wrong if CONFIG_AUDITSYSCALL=n. + +Testers beware: on Xen, SYSENTER with NT set turns into a GPF. + +I haven't touched anything on 32-bit kernels. + +The syscall mask change comes from a variant of this patch by Anish +Bhatt. + +Note to stable maintainers: there is no known security issue here. +A misguided program can set NT and cause the kernel to try and fail +to deliver SIGSEGV, crashing the program. This patch fixes Far Cry +on Wine: https://bugs.winehq.org/show_bug.cgi?id=33275 + +Reported-by: Anish Bhatt +Signed-off-by: Andy Lutomirski +Link: http://lkml.kernel.org/r/395749a5d39a29bd3e4b35899cf3a3c1340e5595.1412189265.git.luto@amacapital.net +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/ia32/ia32entry.S | 18 +++++++++++++++++- + arch/x86/kernel/cpu/common.c | 2 +- + 2 files changed, 18 insertions(+), 2 deletions(-) + +--- a/arch/x86/ia32/ia32entry.S ++++ b/arch/x86/ia32/ia32entry.S +@@ -151,6 +151,16 @@ ENTRY(ia32_sysenter_target) + 1: movl (%rbp),%ebp + _ASM_EXTABLE(1b,ia32_badarg) + ASM_CLAC ++ ++ /* ++ * Sysenter doesn't filter flags, so we need to clear NT ++ * ourselves. To save a few cycles, we can check whether ++ * NT was set instead of doing an unconditional popfq. ++ */ ++ testl $X86_EFLAGS_NT,EFLAGS(%rsp) /* saved EFLAGS match cpu */ ++ jnz sysenter_fix_flags ++sysenter_flags_fixed: ++ + orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + CFI_REMEMBER_STATE +@@ -184,6 +194,8 @@ sysexit_from_sys_call: + TRACE_IRQS_ON + ENABLE_INTERRUPTS_SYSEXIT32 + ++ CFI_RESTORE_STATE ++ + #ifdef CONFIG_AUDITSYSCALL + .macro auditsys_entry_common + movl %esi,%r9d /* 6th arg: 4th syscall arg */ +@@ -226,7 +238,6 @@ sysexit_from_sys_call: + .endm + + sysenter_auditsys: +- CFI_RESTORE_STATE + auditsys_entry_common + movl %ebp,%r9d /* reload 6th syscall arg */ + jmp sysenter_dispatch +@@ -235,6 +246,11 @@ sysexit_audit: + auditsys_exit sysexit_from_sys_call + #endif + ++sysenter_fix_flags: ++ pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_FIXED) ++ popfq_cfi ++ jmp sysenter_flags_fixed ++ + sysenter_tracesys: + #ifdef CONFIG_AUDITSYSCALL + testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -1141,7 +1141,7 @@ void syscall_init(void) + /* Flags to clear on syscall */ + wrmsrl(MSR_SYSCALL_MASK, + X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF| +- X86_EFLAGS_IOPL|X86_EFLAGS_AC); ++ X86_EFLAGS_IOPL|X86_EFLAGS_AC|X86_EFLAGS_NT); + } + + /* diff --git a/queue-3.14/x86_64-entry-fix-out-of-bounds-read-on-sysenter.patch b/queue-3.14/x86_64-entry-fix-out-of-bounds-read-on-sysenter.patch new file mode 100644 index 00000000000..3088194e96c --- /dev/null +++ b/queue-3.14/x86_64-entry-fix-out-of-bounds-read-on-sysenter.patch @@ -0,0 +1,45 @@ +From 653bc77af60911ead1f423e588f54fc2547c4957 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Fri, 31 Oct 2014 18:08:45 -0700 +Subject: x86_64, entry: Fix out of bounds read on sysenter + +From: Andy Lutomirski + +commit 653bc77af60911ead1f423e588f54fc2547c4957 upstream. + +Rusty noticed a Really Bad Bug (tm) in my NT fix. The entry code +reads out of bounds, causing the NT fix to be unreliable. But, and +this is much, much worse, if your stack is somehow just below the +top of the direct map (or a hole), you read out of bounds and crash. + +Excerpt from the crash: + +[ 1.129513] RSP: 0018:ffff88001da4bf88 EFLAGS: 00010296 + + 2b:* f7 84 24 90 00 00 00 testl $0x4000,0x90(%rsp) + +That read is deterministically above the top of the stack. I +thought I even single-stepped through this code when I wrote it to +check the offset, but I clearly screwed it up. + +Fixes: 8c7aa698baca ("x86_64, entry: Filter RFLAGS.NT on entry from userspace") +Reported-by: Rusty Russell +Signed-off-by: Andy Lutomirski +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/ia32/ia32entry.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/ia32/ia32entry.S ++++ b/arch/x86/ia32/ia32entry.S +@@ -157,7 +157,7 @@ ENTRY(ia32_sysenter_target) + * ourselves. To save a few cycles, we can check whether + * NT was set instead of doing an unconditional popfq. + */ +- testl $X86_EFLAGS_NT,EFLAGS(%rsp) /* saved EFLAGS match cpu */ ++ testl $X86_EFLAGS_NT,EFLAGS-ARGOFFSET(%rsp) + jnz sysenter_fix_flags + sysenter_flags_fixed: + -- 2.47.3