From: Jiri Slaby <jslaby@suse.cz> To: stable@vger.kernel.org Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>, Borislav Petkov <bp@alien8.de>, Borislav Petkov <bp@suse.de>, Brian Gerst <brgerst@gmail.com>, Denys Vlasenko <dvlasenk@redhat.com>, "H . Peter Anvin" <hpa@zytor.com>, Josh Poimboeuf <jpoimboe@redhat.com>, Linus Torvalds <torvalds@linux-foundation.org>, Mel Gorman <mgorman@suse.de>, Peter Zijlstra <a.p.zijlstra@chello.nl>, Peter Zijlstra <peterz@infradead.org>, Thomas Gleixner <tglx@linutronix.de>, linux-mm@kvack.org, Ingo Molnar <mingo@kernel.org>, Jiri Slaby <jslaby@suse.cz> Subject: [patch added to 3.12-stable] x86/mm: Disable preemption during CR3 read+write Date: Thu, 22 Sep 2016 09:11:14 +0200 [thread overview] Message-ID: <20160922071154.1297-2-jslaby@suse.cz> (raw) In-Reply-To: <20160922071154.1297-1-jslaby@suse.cz> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> This patch has been added to the 3.12 stable tree. If you have any objections, please let us know. =============== commit 5cf0791da5c162ebc14b01eb01631cfa7ed4fa6e upstream. There's a subtle preemption race on UP kernels: Usually current->mm (and therefore mm->pgd) stays the same during the lifetime of a task so it does not matter if a task gets preempted during the read and write of the CR3. But then, there is this scenario on x86-UP: TaskA is in do_exit() and exit_mm() sets current->mm = NULL followed by: -> mmput() -> exit_mmap() -> tlb_finish_mmu() -> tlb_flush_mmu() -> tlb_flush_mmu_tlbonly() -> tlb_flush() -> flush_tlb_mm_range() -> __flush_tlb_up() -> __flush_tlb() -> __native_flush_tlb() At this point current->mm is NULL but current->active_mm still points to the "old" mm. Let's preempt taskA _after_ native_read_cr3() by taskB. TaskB has its own mm so CR3 has changed. Now preempt back to taskA. TaskA has no ->mm set so it borrows taskB's mm and so CR3 remains unchanged. Once taskA gets active it continues where it was interrupted and that means it writes its old CR3 value back. Everything is fine because userland won't need its memory anymore. Now the fun part: Let's preempt taskA one more time and get back to taskB. This time switch_mm() won't do a thing because oldmm (->active_mm) is the same as mm (as per context_switch()). So we remain with a bad CR3 / PGD and return to userland. The next thing that happens is handle_mm_fault() with an address for the execution of its code in userland. handle_mm_fault() realizes that it has a PTE with proper rights so it returns doing nothing. But the CPU looks at the wrong PGD and insists that something is wrong and faults again. And again. And one more time… This pagefault circle continues until the scheduler gets tired of it and puts another task on the CPU. It gets little difficult if the task is a RT task with a high priority. The system will either freeze or it gets fixed by the software watchdog thread which usually runs at RT-max prio. But waiting for the watchdog will increase the latency of the RT task which is no good. Fix this by disabling preemption across the critical code section. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Rik van Riel <riel@redhat.com> Acked-by: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Borislav Petkov <bp@suse.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mel Gorman <mgorman@suse.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/1470404259-26290-1-git-send-email-bigeasy@linutronix.de [ Prettified the changelog. ] Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Jiri Slaby <jslaby@suse.cz> --- arch/x86/include/asm/tlbflush.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 04905bfc508b..5e4b0cc54e43 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -17,7 +17,14 @@ static inline void __native_flush_tlb(void) { + /* + * If current->mm == NULL then we borrow a mm which may change during a + * task switch and therefore we must not be preempted while we write CR3 + * back: + */ + preempt_disable(); native_write_cr3(native_read_cr3()); + preempt_enable(); } static inline void __native_flush_tlb_global_irq_disabled(void) -- 2.10.0 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
WARNING: multiple messages have this Message-ID (diff)
From: Jiri Slaby <jslaby@suse.cz> To: stable@vger.kernel.org Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>, Borislav Petkov <bp@alien8.de>, Borislav Petkov <bp@suse.de>, Brian Gerst <brgerst@gmail.com>, Denys Vlasenko <dvlasenk@redhat.com>, "H . Peter Anvin" <hpa@zytor.com>, Josh Poimboeuf <jpoimboe@redhat.com>, Linus Torvalds <torvalds@linux-foundation.org>, Mel Gorman <mgorman@suse.de>, Peter Zijlstra <a.p.zijlstra@chello.nl>, Peter Zijlstra <peterz@infradead.org>, Thomas Gleixner <tglx@linutronix.de>, linux-mm@kvack.org, Ingo Molnar <mingo@kernel.org>, Jiri Slaby <jslaby@suse.cz> Subject: [patch added to 3.12-stable] x86/mm: Disable preemption during CR3 read+write Date: Thu, 22 Sep 2016 09:11:14 +0200 [thread overview] Message-ID: <20160922071154.1297-2-jslaby@suse.cz> (raw) In-Reply-To: <20160922071154.1297-1-jslaby@suse.cz> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> This patch has been added to the 3.12 stable tree. If you have any objections, please let us know. =============== commit 5cf0791da5c162ebc14b01eb01631cfa7ed4fa6e upstream. There's a subtle preemption race on UP kernels: Usually current->mm (and therefore mm->pgd) stays the same during the lifetime of a task so it does not matter if a task gets preempted during the read and write of the CR3. But then, there is this scenario on x86-UP: TaskA is in do_exit() and exit_mm() sets current->mm = NULL followed by: -> mmput() -> exit_mmap() -> tlb_finish_mmu() -> tlb_flush_mmu() -> tlb_flush_mmu_tlbonly() -> tlb_flush() -> flush_tlb_mm_range() -> __flush_tlb_up() -> __flush_tlb() -> __native_flush_tlb() At this point current->mm is NULL but current->active_mm still points to the "old" mm. Let's preempt taskA _after_ native_read_cr3() by taskB. TaskB has its own mm so CR3 has changed. Now preempt back to taskA. TaskA has no ->mm set so it borrows taskB's mm and so CR3 remains unchanged. Once taskA gets active it continues where it was interrupted and that means it writes its old CR3 value back. Everything is fine because userland won't need its memory anymore. Now the fun part: Let's preempt taskA one more time and get back to taskB. This time switch_mm() won't do a thing because oldmm (->active_mm) is the same as mm (as per context_switch()). So we remain with a bad CR3 / PGD and return to userland. The next thing that happens is handle_mm_fault() with an address for the execution of its code in userland. handle_mm_fault() realizes that it has a PTE with proper rights so it returns doing nothing. But the CPU looks at the wrong PGD and insists that something is wrong and faults again. And again. And one more timea?| This pagefault circle continues until the scheduler gets tired of it and puts another task on the CPU. It gets little difficult if the task is a RT task with a high priority. The system will either freeze or it gets fixed by the software watchdog thread which usually runs at RT-max prio. But waiting for the watchdog will increase the latency of the RT task which is no good. Fix this by disabling preemption across the critical code section. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Rik van Riel <riel@redhat.com> Acked-by: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Borislav Petkov <bp@suse.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mel Gorman <mgorman@suse.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/1470404259-26290-1-git-send-email-bigeasy@linutronix.de [ Prettified the changelog. ] Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Jiri Slaby <jslaby@suse.cz> --- arch/x86/include/asm/tlbflush.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 04905bfc508b..5e4b0cc54e43 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -17,7 +17,14 @@ static inline void __native_flush_tlb(void) { + /* + * If current->mm == NULL then we borrow a mm which may change during a + * task switch and therefore we must not be preempted while we write CR3 + * back: + */ + preempt_disable(); native_write_cr3(native_read_cr3()); + preempt_enable(); } static inline void __native_flush_tlb_global_irq_disabled(void) -- 2.10.0 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2016-09-22 7:11 UTC|newest] Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-09-22 7:11 [patch added to 3.12-stable] MIPS: KVM: Check for pfn noslot case Jiri Slaby 2016-09-22 7:11 ` Jiri Slaby [this message] 2016-09-22 7:11 ` [patch added to 3.12-stable] x86/mm: Disable preemption during CR3 read+write Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] arm64: Define AT_VECTOR_SIZE_ARCH for ARCH_DLINFO Jiri Slaby 2016-09-22 7:11 ` Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] parisc: Fix order of EREFUSED define in errno.h Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] PCI: Support PCIe devices with short cfg_size Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] PCI: Add Netronome vendor and device IDs Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] PCI: Limit config space size for Netronome NFP6000 family Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] PCI: Add Netronome NFP4000 PF device ID Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] PCI: Limit config space size for Netronome NFP4000 Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] usb: dwc3: gadget: increment request->actual once Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] usb: define USB_SPEED_SUPER_PLUS speed for SuperSpeedPlus USB3.1 devices Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] USB: validate wMaxPacketValue entries in endpoint descriptors Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] usb: xhci: Fix panic if disconnect Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] USB: serial: fix memleak in driver-registration error path Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] USB: serial: option: add D-Link DWM-156/A3 Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] USB: serial: option: add support for Telit LE920A4 Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] USB: serial: ftdi_sio: add device ID for WICED USB UART dev board Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] USB: serial: ftdi_sio: add PIDs for Ivium Technologies devices Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] xhci: Make sure xhci handles USB_SPEED_SUPER_PLUS devices Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] EDAC: Increment correct counter in edac_inc_ue_error() Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] s390/dasd: fix hanging device after clear subchannel Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] mac80211: fix purging multicast PS buffer queue Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] aacraid: Check size values after double-fetch from user Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] cdc-acm: fix wrong pipe type on rx interrupt xfers Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] megaraid_sas: Fix probing cards without io port Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] gpio: Fix OF build problem on UM Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] fs/seq_file: fix out-of-bounds read Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] Input: i8042 - break load dependency between atkbd/psmouse and i8042 Jiri Slaby 2016-09-22 16:37 ` Dmitry Torokhov 2016-09-23 8:23 ` Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] crypto: nx - off by one bug in nx_of_update_msc() Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] USB: fix typo in wMaxPacketSize validation Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] USB: serial: mos7720: fix non-atomic allocation in write path Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] USB: serial: mos7840: " Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] staging: comedi: daqboard2000: bug fix board type matching code Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] ACPI / sysfs: fix error code in get_status() Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] Revert "can: fix handling of unmodifiable configuration options fix" Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] be2iscsi: Fix bogus WARN_ON length check Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] HID: hid-input: Add parentheses to quell gcc warning Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] ALSA: oxygen: Fix logical-not-parentheses warning Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] stb6100: fix buffer length check in stb6100_write_reg_range() Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] ext4: validate that metadata blocks do not overlap superblock Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] s390/sclp_ctl: fix potential information leak with /dev/sclp Jiri Slaby 2016-09-22 7:11 ` [patch added to 3.12-stable] fix d_walk()/non-delayed __d_free() race Jiri Slaby
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=20160922071154.1297-2-jslaby@suse.cz \ --to=jslaby@suse.cz \ --cc=a.p.zijlstra@chello.nl \ --cc=bigeasy@linutronix.de \ --cc=bp@alien8.de \ --cc=bp@suse.de \ --cc=brgerst@gmail.com \ --cc=dvlasenk@redhat.com \ --cc=hpa@zytor.com \ --cc=jpoimboe@redhat.com \ --cc=linux-mm@kvack.org \ --cc=mgorman@suse.de \ --cc=mingo@kernel.org \ --cc=peterz@infradead.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: linkBe 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.