3.13.11-ckt25 -stable review patch.  If anyone has any objections, please let 
me know.

------------------

From: Andy Lutomirski <[email protected]>

commit a27507ca2d796cfa8d907de31ad730359c8a6d06 upstream.

Check the repeat_nmi .. end_repeat_nmi special case first.  The next
patch will rework the RSP check and, as a side effect, the RSP check
will no longer detect repeat_nmi .. end_repeat_nmi, so we'll need
this ordering of the checks.

Note: this is more subtle than it appears.  The check for repeat_nmi
.. end_repeat_nmi jumps straight out of the NMI code instead of
adjusting the "iret" frame to force a repeat.  This is necessary,
because the code between repeat_nmi and end_repeat_nmi sets "NMI
executing" and then writes to the "iret" frame itself.  If a nested
NMI comes in and modifies the "iret" frame while repeat_nmi is also
modifying it, we'll end up with garbage.  The old code got this
right, as does the new code, but the new code is a bit more
explicit.

If we were to move the check right after the "NMI executing" check,
then we'd get it wrong and have random crashes.

This is a prerequisite for the fix for CVE-2015-3291.

Signed-off-by: Andy Lutomirski <[email protected]>
[bwh: Backported to 4.0: adjust filename, spacing]
Signed-off-by: Ben Hutchings <[email protected]>
Acked-by: John Johansen <[email protected]>
Acked-by: Andy Whitcroft <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
Signed-off-by: Andy Whitcroft <[email protected]>
Signed-off-by: Kamal Mostafa <[email protected]>
---
 arch/x86/kernel/entry_64.S | 34 ++++++++++++++++++----------------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 1283ccf..e70afa4 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1869,7 +1869,24 @@ ENTRY(nmi)
        /*
         * Determine whether we're a nested NMI.
         *
-        * First check "NMI executing".  If it's set, then we're nested.
+        * If we interrupted kernel code between repeat_nmi and
+        * end_repeat_nmi, then we are a nested NMI.  We must not
+        * modify the "iret" frame because it's being written by
+        * the outer NMI.  That's okay: the outer NMI handler is
+        * about to about to call do_nmi anyway, so we can just
+        * resume the outer NMI.
+        */
+
+       movq    $repeat_nmi, %rdx
+       cmpq    8(%rsp), %rdx
+       ja      1f
+       movq    $end_repeat_nmi, %rdx
+       cmpq    8(%rsp), %rdx
+       ja      nested_nmi_out
+1:
+
+       /*
+        * Now check "NMI executing".  If it's set, then we're nested.
         * This will not detect if we interrupted an outer NMI just
         * before IRET.
         */
@@ -1896,21 +1913,6 @@ ENTRY(nmi)
 
 nested_nmi:
        /*
-        * If we interrupted an NMI that is between repeat_nmi and
-        * end_repeat_nmi, then we must not modify the "iret" frame
-        * because it's being written by the outer NMI.  That's okay:
-        * the outer NMI handler is about to call do_nmi anyway,
-        * so we can just resume the outer NMI.
-        */
-       movq $repeat_nmi, %rdx
-       cmpq 8(%rsp), %rdx
-       ja 1f
-       movq $end_repeat_nmi, %rdx
-       cmpq 8(%rsp), %rdx
-       ja nested_nmi_out
-
-1:
-       /*
         * Modify the "iret" frame to point to repeat_nmi, forcing another
         * iteration of NMI handling.
         */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to