From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.linuxfoundation.org ([140.211.169.12]:53235 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751898AbbHMBD2 (ORCPT ); Wed, 12 Aug 2015 21:03:28 -0400 Subject: Patch "x86/nmi/64: Use DF to avoid userspace RSP confusing nested NMI detection" has been added to the 4.1-stable tree To: luto@kernel.org, bp@suse.de, gregkh@linuxfoundation.org, mingo@kernel.org, peterz@infradead.org, rostedt@goodmis.org, tglx@linutronix.de, torvalds@linux-foundation.org Cc: , From: Date: Wed, 12 Aug 2015 18:03:27 -0700 Message-ID: <1439427807143117@kroah.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ANSI_X3.4-1968 Content-Transfer-Encoding: 8bit Sender: stable-owner@vger.kernel.org List-ID: This is a note to let you know that I've just added the patch titled x86/nmi/64: Use DF to avoid userspace RSP confusing nested NMI detection to the 4.1-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: x86-nmi-64-use-df-to-avoid-userspace-rsp-confusing-nested-nmi-detection.patch and it can be found in the queue-4.1 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let know about it. >>From 810bc075f78ff2c221536eb3008eac6a492dba2d Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 15 Jul 2015 10:29:38 -0700 Subject: x86/nmi/64: Use DF to avoid userspace RSP confusing nested NMI detection From: Andy Lutomirski commit 810bc075f78ff2c221536eb3008eac6a492dba2d upstream. We have a tricky bug in the nested NMI code: if we see RSP pointing to the NMI stack on NMI entry from kernel mode, we assume that we are executing a nested NMI. This isn't quite true. A malicious userspace program can point RSP at the NMI stack, issue SYSCALL, and arrange for an NMI to happen while RSP is still pointing at the NMI stack. Fix it with a sneaky trick. Set DF in the region of code that the RSP check is intended to detect. IRET will clear DF atomically. ( Note: other than paravirt, there's little need for all this complexity. We could check RIP instead of RSP. ) Signed-off-by: Andy Lutomirski Reviewed-by: Steven Rostedt Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: stable@vger.kernel.org Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/entry_64.S | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1562,7 +1562,14 @@ ENTRY(nmi) /* * Now test if the previous stack was an NMI stack. This covers * the case where we interrupt an outer NMI after it clears - * "NMI executing" but before IRET. + * "NMI executing" but before IRET. We need to be careful, though: + * there is one case in which RSP could point to the NMI stack + * despite there being no NMI active: naughty userspace controls + * RSP at the very beginning of the SYSCALL targets. We can + * pull a fast one on naughty userspace, though: we program + * SYSCALL to mask DF, so userspace cannot cause DF to be set + * if it controls the kernel's RSP. We set DF before we clear + * "NMI executing". */ lea 6*8(%rsp), %rdx /* Compare the NMI stack (rdx) with the stack we came from (4*8(%rsp)) */ @@ -1573,7 +1580,13 @@ ENTRY(nmi) cmpq %rdx, 4*8(%rsp) /* If it is below the NMI stack, it is a normal NMI */ jb first_nmi - /* Ah, it is within the NMI stack, treat it as nested */ + + /* Ah, it is within the NMI stack. */ + + testb $(X86_EFLAGS_DF >> 8), (3*8 + 1)(%rsp) + jz first_nmi /* RSP was user controlled. */ + + /* This is a nested NMI. */ CFI_REMEMBER_STATE @@ -1691,8 +1704,16 @@ nmi_restore: /* Point RSP at the "iret" frame. */ REMOVE_PT_GPREGS_FROM_STACK 6*8 - /* Clear "NMI executing". */ - movq $0, 5*8(%rsp) + /* + * Clear "NMI executing". Set DF first so that we can easily + * distinguish the remaining code between here and IRET from + * the SYSCALL entry and exit paths. On a native kernel, we + * could just inspect RIP, but, on paravirt kernels, + * INTERRUPT_RETURN can translate into a jump into a + * hypercall page. + */ + std + movq $0, 5*8(%rsp) /* clear "NMI executing" */ /* * INTERRUPT_RETURN reads the "iret" frame and exits the NMI Patches currently in stable-queue which might be from luto@kernel.org are queue-4.1/x86-nmi-enable-nested-do_nmi-handling-for-64-bit-kernels.patch queue-4.1/x86-nmi-64-switch-stacks-on-userspace-nmi-entry.patch queue-4.1/x86-nmi-64-remove-asm-code-that-saves-cr2.patch queue-4.1/x86-nmi-64-use-df-to-avoid-userspace-rsp-confusing-nested-nmi-detection.patch queue-4.1/x86-asm-entry-64-remove-pointless-jump-to-irq_return.patch queue-4.1/x86-nmi-64-reorder-nested-nmi-checks.patch queue-4.1/x86-nmi-64-improve-nested-nmi-comments.patch