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)
next prev parent reply other threads:[~2015-09-29 15:30 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.