]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.14.112/x86-power-fix-some-ordering-bugs-in-__restore_proces.patch
Linux 4.14.112
[thirdparty/kernel/stable-queue.git] / releases / 4.14.112 / x86-power-fix-some-ordering-bugs-in-__restore_proces.patch
CommitLineData
fcb9b3db
SL
1From 15b5e7c4808e86d9ffd15b759af8686fd1dfaa5f Mon Sep 17 00:00:00 2001
2From: Andy Lutomirski <luto@kernel.org>
3Date: Thu, 30 Nov 2017 07:57:57 -0800
4Subject: x86/power: Fix some ordering bugs in __restore_processor_context()
5
6[ Upstream commit 5b06bbcfc2c621da3009da8decb7511500c293ed ]
7
8__restore_processor_context() had a couple of ordering bugs. It
9restored GSBASE after calling load_gs_index(), and the latter can
10call into tracing code. It also tried to restore segment registers
11before restoring the LDT, which is straight-up wrong.
12
13Reorder the code so that we restore GSBASE, then the descriptor
14tables, then the segments.
15
16This fixes two bugs. First, it fixes a regression that broke resume
17under certain configurations due to irqflag tracing in
18native_load_gs_index(). Second, it fixes resume when the userspace
19process that initiated suspect had funny segments. The latter can be
20reproduced by compiling this:
21
22// SPDX-License-Identifier: GPL-2.0
23/*
24 * ldt_echo.c - Echo argv[1] while using an LDT segment
25 */
26
27int main(int argc, char **argv)
28{
29 int ret;
30 size_t len;
31 char *buf;
32
33 const struct user_desc desc = {
34 .entry_number = 0,
35 .base_addr = 0,
36 .limit = 0xfffff,
37 .seg_32bit = 1,
38 .contents = 0, /* Data, grow-up */
39 .read_exec_only = 0,
40 .limit_in_pages = 1,
41 .seg_not_present = 0,
42 .useable = 0
43 };
44
45 if (argc != 2)
46 errx(1, "Usage: %s STRING", argv[0]);
47
48 len = asprintf(&buf, "%s\n", argv[1]);
49 if (len < 0)
50 errx(1, "Out of memory");
51
52 ret = syscall(SYS_modify_ldt, 1, &desc, sizeof(desc));
53 if (ret < -1)
54 errno = -ret;
55 if (ret)
56 err(1, "modify_ldt");
57
58 asm volatile ("movw %0, %%es" :: "rm" ((unsigned short)7));
59 write(1, buf, len);
60 return 0;
61}
62
63and running ldt_echo >/sys/power/mem
64
65Without the fix, the latter causes a triple fault on resume.
66
67Fixes: ca37e57bbe0c ("x86/entry/64: Add missing irqflags tracing to native_load_gs_index()")
68Reported-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
69Signed-off-by: Andy Lutomirski <luto@kernel.org>
70Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
71Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
72Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
73Cc: Borislav Petkov <bp@alien8.de>
74Cc: Linus Torvalds <torvalds@linux-foundation.org>
75Link: https://lkml.kernel.org/r/6b31721ea92f51ea839e79bd97ade4a75b1eeea2.1512057304.git.luto@kernel.org
76Signed-off-by: Ingo Molnar <mingo@kernel.org>
77Signed-off-by: Sasha Levin <sashal@kernel.org>
78---
79 arch/x86/power/cpu.c | 21 +++++++++++++++++----
80 1 file changed, 17 insertions(+), 4 deletions(-)
81
82diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
83index 04d5157fe7f8..a51d2dfb57d1 100644
84--- a/arch/x86/power/cpu.c
85+++ b/arch/x86/power/cpu.c
86@@ -228,8 +228,20 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
87 load_idt((const struct desc_ptr *)&ctxt->idt_limit);
88 #endif
89
90+#ifdef CONFIG_X86_64
91 /*
92- * segment registers
93+ * We need GSBASE restored before percpu access can work.
94+ * percpu access can happen in exception handlers or in complicated
95+ * helpers like load_gs_index().
96+ */
97+ wrmsrl(MSR_GS_BASE, ctxt->gs_base);
98+#endif
99+
100+ fix_processor_context();
101+
102+ /*
103+ * Restore segment registers. This happens after restoring the GDT
104+ * and LDT, which happen in fix_processor_context().
105 */
106 #ifdef CONFIG_X86_32
107 loadsegment(es, ctxt->es);
108@@ -250,13 +262,14 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
109 load_gs_index(ctxt->gs);
110 asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss));
111
112+ /*
113+ * Restore FSBASE and user GSBASE after reloading the respective
114+ * segment selectors.
115+ */
116 wrmsrl(MSR_FS_BASE, ctxt->fs_base);
117- wrmsrl(MSR_GS_BASE, ctxt->gs_base);
118 wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
119 #endif
120
121- fix_processor_context();
122-
123 do_fpu_end();
124 tsc_verify_tsc_adjust(true);
125 x86_platform.restore_sched_clock_state();
126--
1272.19.1
128