stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Andy Lutomirski <luto@kernel.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Borislav Petkov <bp@suse.de>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@kernel.org>
Subject: [PATCH 3.14 77/84] x86/nmi: Enable nested do_nmi() handling for 64-bit kernels
Date: Tue, 29 Sep 2015 17:19:09 +0200	[thread overview]
Message-ID: <20150929145334.396284386@linuxfoundation.org> (raw)
In-Reply-To: <20150929145330.924730721@linuxfoundation.org>

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

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

From: Andy Lutomirski <luto@kernel.org>

commit 9d05041679904b12c12421cbcf9cb5f4860a8d7b upstream.

32-bit kernels handle nested NMIs in C.  Enable the exact same
handling on 64-bit kernels as well.  This isn't currently
necessary, but it will become necessary once the asm code starts
allowing limited nesting.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 arch/x86/kernel/nmi.c |  125 +++++++++++++++++++++-----------------------------
 1 file changed, 53 insertions(+), 72 deletions(-)

--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -392,15 +392,15 @@ static __kprobes void default_do_nmi(str
 }
 
 /*
- * NMIs can hit breakpoints which will cause it to lose its
- * NMI context with the CPU when the breakpoint does an iret.
- */
-#ifdef CONFIG_X86_32
-/*
- * For i386, NMIs use the same stack as the kernel, and we can
- * add a workaround to the iret problem in C (preventing nested
- * NMIs if an NMI takes a trap). Simply have 3 states the NMI
- * can be in:
+ * NMIs can hit breakpoints which will cause it to lose its NMI context
+ * with the CPU when the breakpoint or page fault does an IRET.
+ *
+ * As a result, NMIs can nest if NMIs get unmasked due an IRET during
+ * NMI processing.  On x86_64, the asm glue protects us from nested NMIs
+ * if the outer NMI came from kernel mode, but we can still nest if the
+ * outer NMI came from user mode.
+ *
+ * To handle these nested NMIs, we have three states:
  *
  *  1) not running
  *  2) executing
@@ -414,15 +414,14 @@ static __kprobes void default_do_nmi(str
  * (Note, the latch is binary, thus multiple NMIs triggering,
  *  when one is running, are ignored. Only one NMI is restarted.)
  *
- * If an NMI hits a breakpoint that executes an iret, another
- * NMI can preempt it. We do not want to allow this new NMI
- * to run, but we want to execute it when the first one finishes.
- * We set the state to "latched", and the exit of the first NMI will
- * perform a dec_return, if the result is zero (NOT_RUNNING), then
- * it will simply exit the NMI handler. If not, the dec_return
- * would have set the state to NMI_EXECUTING (what we want it to
- * be when we are running). In this case, we simply jump back
- * to rerun the NMI handler again, and restart the 'latched' NMI.
+ * If an NMI executes an iret, another NMI can preempt it. We do not
+ * want to allow this new NMI to run, but we want to execute it when the
+ * first one finishes.  We set the state to "latched", and the exit of
+ * the first NMI will perform a dec_return, if the result is zero
+ * (NOT_RUNNING), then it will simply exit the NMI handler. If not, the
+ * dec_return would have set the state to NMI_EXECUTING (what we want it
+ * to be when we are running). In this case, we simply jump back to
+ * rerun the NMI handler again, and restart the 'latched' NMI.
  *
  * No trap (breakpoint or page fault) should be hit before nmi_restart,
  * thus there is no race between the first check of state for NOT_RUNNING
@@ -445,49 +444,36 @@ enum nmi_states {
 static DEFINE_PER_CPU(enum nmi_states, nmi_state);
 static DEFINE_PER_CPU(unsigned long, nmi_cr2);
 
-#define nmi_nesting_preprocess(regs)					\
-	do {								\
-		if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {	\
-			this_cpu_write(nmi_state, NMI_LATCHED);		\
-			return;						\
-		}							\
-		this_cpu_write(nmi_state, NMI_EXECUTING);		\
-		this_cpu_write(nmi_cr2, read_cr2());			\
-	} while (0);							\
-	nmi_restart:
-
-#define nmi_nesting_postprocess()					\
-	do {								\
-		if (unlikely(this_cpu_read(nmi_cr2) != read_cr2()))	\
-			write_cr2(this_cpu_read(nmi_cr2));		\
-		if (this_cpu_dec_return(nmi_state))			\
-			goto nmi_restart;				\
-	} while (0)
-#else /* x86_64 */
+#ifdef CONFIG_X86_64
 /*
- * In x86_64 things are a bit more difficult. This has the same problem
- * where an NMI hitting a breakpoint that calls iret will remove the
- * NMI context, allowing a nested NMI to enter. What makes this more
- * difficult is that both NMIs and breakpoints have their own stack.
- * When a new NMI or breakpoint is executed, the stack is set to a fixed
- * point. If an NMI is nested, it will have its stack set at that same
- * fixed address that the first NMI had, and will start corrupting the
- * stack. This is handled in entry_64.S, but the same problem exists with
- * the breakpoint stack.
- *
- * If a breakpoint is being processed, and the debug stack is being used,
- * if an NMI comes in and also hits a breakpoint, the stack pointer
- * will be set to the same fixed address as the breakpoint that was
- * interrupted, causing that stack to be corrupted. To handle this case,
- * check if the stack that was interrupted is the debug stack, and if
- * so, change the IDT so that new breakpoints will use the current stack
- * and not switch to the fixed address. On return of the NMI, switch back
- * to the original IDT.
+ * In x86_64, we need to handle breakpoint -> NMI -> breakpoint.  Without
+ * some care, the inner breakpoint will clobber the outer breakpoint's
+ * stack.
+ *
+ * If a breakpoint is being processed, and the debug stack is being
+ * used, if an NMI comes in and also hits a breakpoint, the stack
+ * pointer will be set to the same fixed address as the breakpoint that
+ * was interrupted, causing that stack to be corrupted. To handle this
+ * case, check if the stack that was interrupted is the debug stack, and
+ * if so, change the IDT so that new breakpoints will use the current
+ * stack and not switch to the fixed address. On return of the NMI,
+ * switch back to the original IDT.
  */
 static DEFINE_PER_CPU(int, update_debug_stack);
+#endif
 
-static inline void nmi_nesting_preprocess(struct pt_regs *regs)
+dotraplinkage notrace void
+do_nmi(struct pt_regs *regs, long error_code)
 {
+	if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {
+		this_cpu_write(nmi_state, NMI_LATCHED);
+		return;
+	}
+	this_cpu_write(nmi_state, NMI_EXECUTING);
+	this_cpu_write(nmi_cr2, read_cr2());
+nmi_restart:
+
+#ifdef CONFIG_X86_64
 	/*
 	 * If we interrupted a breakpoint, it is possible that
 	 * the nmi handler will have breakpoints too. We need to
@@ -498,22 +484,8 @@ static inline void nmi_nesting_preproces
 		debug_stack_set_zero();
 		this_cpu_write(update_debug_stack, 1);
 	}
-}
-
-static inline void nmi_nesting_postprocess(void)
-{
-	if (unlikely(this_cpu_read(update_debug_stack))) {
-		debug_stack_reset();
-		this_cpu_write(update_debug_stack, 0);
-	}
-}
 #endif
 
-dotraplinkage notrace __kprobes void
-do_nmi(struct pt_regs *regs, long error_code)
-{
-	nmi_nesting_preprocess(regs);
-
 	nmi_enter();
 
 	inc_irq_stat(__nmi_count);
@@ -523,8 +495,17 @@ do_nmi(struct pt_regs *regs, long error_
 
 	nmi_exit();
 
-	/* On i386, may loop back to preprocess */
-	nmi_nesting_postprocess();
+#ifdef CONFIG_X86_64
+	if (unlikely(this_cpu_read(update_debug_stack))) {
+		debug_stack_reset();
+		this_cpu_write(update_debug_stack, 0);
+	}
+#endif
+
+	if (unlikely(this_cpu_read(nmi_cr2) != read_cr2()))
+		write_cr2(this_cpu_read(nmi_cr2));
+	if (this_cpu_dec_return(nmi_state))
+		goto nmi_restart;
 }
 
 void stop_nmi(void)



  parent reply	other threads:[~2015-09-29 15:23 UTC|newest]

Thread overview: 93+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-29 15:17 [PATCH 3.14 00/84] 3.14.54-stable review Greg Kroah-Hartman
2015-09-29 15:17 ` [PATCH 3.14 01/84] blk-mq: fix buffer overflow when reading sysfs file of pending Greg Kroah-Hartman
2015-09-29 15:17 ` [PATCH 3.14 02/84] unshare: Unsharing a thread does not require unsharing a vm Greg Kroah-Hartman
2015-09-29 15:17 ` [PATCH 3.14 03/84] rtlwifi: rtl8192cu: Add new device ID Greg Kroah-Hartman
2015-09-29 15:17 ` [PATCH 3.14 04/84] tg3: Fix temperature reporting Greg Kroah-Hartman
2015-09-29 15:17 ` [PATCH 3.14 05/84] mac80211: enable assoc check for mesh interfaces Greg Kroah-Hartman
2015-09-29 15:17 ` [PATCH 3.14 06/84] arm64: kconfig: Move LIST_POISON to a safe value Greg Kroah-Hartman
2015-09-29 15:17 ` [PATCH 3.14 07/84] arm64: compat: fix vfp save/restore across signal handlers in big-endian Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 08/84] arm64: head.S: initialise mdcr_el2 in el2_setup Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 09/84] arm64: errata: add module build workaround for erratum #843419 Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 10/84] arm64: KVM: Disable virtual timer even if the guest is not using it Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 11/84] Input: evdev - do not report errors form flush() Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 12/84] ALSA: hda - Enable headphone jack detect on old Fujitsu laptops Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 13/84] ALSA: hda - Use ALC880_FIXUP_FUJITSU for FSC Amilo M1437 Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 14/84] powerpc/mm: Fix pte_pagesize_index() crash on 4K w/64K hash Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 15/84] powerpc/rtas: Introduce rtas_get_sensor_fast() for IRQ handlers Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 16/84] powerpc/mm: Recompute hash value after a failed update Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 17/84] CIFS: fix type confusion in copy offload ioctl Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 18/84] Add radeon suspend/resume quirk for HP Compaq dc5750 Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 19/84] mm: check if section present during memory block registering Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 20/84] x86/mm: Initialize pmd_idx in page_table_range_init_count() Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 22/84] [media] v4l: omap3isp: Fix sub-device power management code Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 23/84] Btrfs: check if previous transaction aborted to avoid fs corruption Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 24/84] NFSv4: dont set SETATTR for O_RDONLY|O_EXCL Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 25/84] NFS: Fix a NULL pointer dereference of migration recovery ops for v4.2 client Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 26/84] NFS: nfs_set_pgio_error sometimes misses errors Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 27/84] parisc: Use double word condition in 64bit CAS operation Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 28/84] parisc: Filter out spurious interrupts in PA-RISC irq handler Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 29/84] vmscan: fix increasing nr_isolated incurred by putback unevictable pages Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 30/84] fs: if a coredump already exists, unlink and recreate with O_EXCL Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 31/84] mmc: core: fix race condition in mmc_wait_data_done Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 32/84] md/raid10: always set reshape_safe when initializing reshape_position Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 33/84] xen/gntdev: convert priv->lock to a mutex Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 34/84] hfs: fix B-tree corruption after insertion at position 0 Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 35/84] IB/qib: Change lkey table allocation to support more MRs Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 36/84] IB/uverbs: reject invalid or unknown opcodes Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 37/84] IB/uverbs: Fix race between ib_uverbs_open and remove_one Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 38/84] IB/mlx4: Forbid using sysfs to change RoCE pkeys Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 39/84] IB/mlx4: Use correct SL on AH query under RoCE Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 40/84] stmmac: fix check for phydev being open Greg Kroah-Hartman
2015-09-30 11:22   ` Sergei Shtylyov
2015-10-01  3:04     ` Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 41/84] stmmac: troubleshoot unexpected bits in des0 & des1 Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 42/84] hfs,hfsplus: cache pages correctly between bnode_create and bnode_free Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 43/84] ipv6: Make MLD packets to only be processed locally Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 44/84] net: graceful exit from netif_alloc_netdev_queues() Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 45/84] rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 47/84] net/tipc: initialize security state for new connection socket Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 48/84] bridge: mdb: zero out the local br_ip variable before use Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 49/84] net: pktgen: fix race between pktgen_thread_worker() and kthread_stop() Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 50/84] net: do not process device backlog during unregistration Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 51/84] net: call rcu_read_lock early in process_backlog Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 52/84] net: Clone skb before setting peeked flag Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 53/84] net: Fix skb csum races when peeking Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 54/84] net: Fix skb_set_peeked use-after-free bug Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 55/84] bridge: mdb: fix double add notification Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 56/84] isdn/gigaset: reset tty->receive_room when attaching ser_gigaset Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 57/84] ipv6: lock socket in ip6_datagram_connect() Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 58/84] bonding: fix destruction of bond with devices different from arphrd_ether Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 59/84] bonding: correct the MAC address for "follow" fail_over_mac policy Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 60/84] inet: frags: fix defragmented packets IP header for af_packet Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 61/84] netlink: dont hold mutex in rcu callback when releasing mmapd ring Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 62/84] net/mlx4_core: Fix wrong index in propagating port change event to VFs Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 63/84] ip6_gre: release cached dst on tunnel removal Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 64/84] usbnet: Get EVENT_NO_RUNTIME_PM bit before it is cleared Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 65/84] ipv6: fix exthdrs offload registration in out_rt path Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 66/84] net/ipv6: Correct PIM6 mrt_lock handling Greg Kroah-Hartman
2015-09-29 15:18 ` [PATCH 3.14 67/84] netlink, mmap: transform mmap skb into full skb on taps Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 68/84] sctp: fix race on protocol/netns initialization Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 69/84] openvswitch: Zero flows on allocation Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 70/84] fib_rules: fix fib rule dumps across multiple skbs Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 71/84] packet: missing dev_put() in packet_do_bind() Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 72/84] rds: fix an integer overflow test in rds_info_getsockopt() Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 74/84] bna: fix interrupts storm caused by erroneous packets Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 75/84] net: gso: use feature flag argument in all protocol gso handlers Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 76/84] Revert "iio: bmg160: IIO_BUFFER and IIO_TRIGGERED_BUFFER are required" Greg Kroah-Hartman
2015-09-29 15:19 ` Greg Kroah-Hartman [this message]
2015-09-29 15:19 ` [PATCH 3.14 78/84] x86/nmi/64: Remove asm code that saves CR2 Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 79/84] x86/nmi/64: Switch stacks on userspace NMI entry Greg Kroah-Hartman
2015-09-29 17:25   ` Andy Lutomirski
2015-09-29 17:57     ` Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 80/84] x86/nmi/64: Improve nested NMI comments Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 81/84] x86/nmi/64: Reorder nested NMI checks Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 82/84] x86/nmi/64: Use DF to avoid userspace RSP confusing nested NMI detection Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 83/84] udf: Check length of extended attributes and allocation descriptors Greg Kroah-Hartman
2015-09-29 15:19 ` [PATCH 3.14 84/84] NVMe: Initialize device reference count earlier Greg Kroah-Hartman
2015-09-29 16:53 ` [PATCH 3.14 00/84] 3.14.54-stable review Shuah Khan
2015-09-29 19:41   ` Greg Kroah-Hartman
2015-09-29 21:15 ` Guenter Roeck
2015-09-30  2:11   ` Greg Kroah-Hartman
2015-09-30  5:53 ` Sudip Mukherjee
2015-09-30  6:00   ` Greg Kroah-Hartman
     [not found] ` <560e8874.e968c20a.57231.fffff396@mx.google.com>
2015-10-02 13:38   ` Kevin Hilman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150929145334.396284386@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=bp@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=stable@vger.kernel.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).