]>
Commit | Line | Data |
---|---|---|
321d628a FG |
1 | From f16330a748c8b8db495673108d72fcfc2873d377 Mon Sep 17 00:00:00 2001 |
2 | From: Andy Lutomirski <luto@kernel.org> | |
3 | Date: Thu, 2 Nov 2017 00:59:09 -0700 | |
b378f209 | 4 | Subject: [PATCH 097/233] x86/entry/32: Pull the MSR_IA32_SYSENTER_CS update |
321d628a FG |
5 | code out of native_load_sp0() |
6 | MIME-Version: 1.0 | |
7 | Content-Type: text/plain; charset=UTF-8 | |
8 | Content-Transfer-Encoding: 8bit | |
9 | ||
10 | CVE-2017-5754 | |
11 | ||
12 | This causes the MSR_IA32_SYSENTER_CS write to move out of the | |
13 | paravirt callback. This shouldn't affect Xen PV: Xen already ignores | |
14 | MSR_IA32_SYSENTER_ESP writes. In any event, Xen doesn't support | |
15 | vm86() in a useful way. | |
16 | ||
17 | Note to any potential backporters: This patch won't break lguest, as | |
18 | lguest didn't have any SYSENTER support at all. | |
19 | ||
20 | Signed-off-by: Andy Lutomirski <luto@kernel.org> | |
21 | Cc: Borislav Petkov <bpetkov@suse.de> | |
22 | Cc: Brian Gerst <brgerst@gmail.com> | |
23 | Cc: Dave Hansen <dave.hansen@intel.com> | |
24 | Cc: Linus Torvalds <torvalds@linux-foundation.org> | |
25 | Cc: Peter Zijlstra <peterz@infradead.org> | |
26 | Cc: Thomas Gleixner <tglx@linutronix.de> | |
27 | Link: http://lkml.kernel.org/r/75cf09fe03ae778532d0ca6c65aa58e66bc2f90c.1509609304.git.luto@kernel.org | |
28 | Signed-off-by: Ingo Molnar <mingo@kernel.org> | |
29 | (cherry picked from commit bd7dc5a6afac719d8ce4092391eef2c7e83c2a75) | |
30 | Signed-off-by: Andy Whitcroft <apw@canonical.com> | |
31 | Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> | |
32 | (cherry picked from commit 779e32d0da9a547f3b11fbecac8287e458ba67f5) | |
33 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
34 | --- | |
35 | arch/x86/include/asm/processor.h | 7 ------- | |
36 | arch/x86/include/asm/switch_to.h | 12 ++++++++++++ | |
37 | arch/x86/kernel/process_32.c | 4 +++- | |
38 | arch/x86/kernel/process_64.c | 2 +- | |
39 | arch/x86/kernel/vm86_32.c | 6 +++++- | |
40 | 5 files changed, 21 insertions(+), 10 deletions(-) | |
41 | ||
42 | diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h | |
43 | index 028245e1c42b..ee37fb86900a 100644 | |
44 | --- a/arch/x86/include/asm/processor.h | |
45 | +++ b/arch/x86/include/asm/processor.h | |
46 | @@ -513,13 +513,6 @@ static inline void | |
47 | native_load_sp0(struct tss_struct *tss, struct thread_struct *thread) | |
48 | { | |
49 | tss->x86_tss.sp0 = thread->sp0; | |
50 | -#ifdef CONFIG_X86_32 | |
51 | - /* Only happens when SEP is enabled, no need to test "SEP"arately: */ | |
52 | - if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) { | |
53 | - tss->x86_tss.ss1 = thread->sysenter_cs; | |
54 | - wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); | |
55 | - } | |
56 | -#endif | |
57 | } | |
58 | ||
59 | static inline void native_swapgs(void) | |
60 | diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h | |
61 | index fcc5cd387fd1..7ae8caffbada 100644 | |
62 | --- a/arch/x86/include/asm/switch_to.h | |
63 | +++ b/arch/x86/include/asm/switch_to.h | |
64 | @@ -72,4 +72,16 @@ do { \ | |
65 | ((last) = __switch_to_asm((prev), (next))); \ | |
66 | } while (0) | |
67 | ||
68 | +#ifdef CONFIG_X86_32 | |
69 | +static inline void refresh_sysenter_cs(struct thread_struct *thread) | |
70 | +{ | |
71 | + /* Only happens when SEP is enabled, no need to test "SEP"arately: */ | |
72 | + if (unlikely(this_cpu_read(cpu_tss.x86_tss.ss1) == thread->sysenter_cs)) | |
73 | + return; | |
74 | + | |
75 | + this_cpu_write(cpu_tss.x86_tss.ss1, thread->sysenter_cs); | |
76 | + wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); | |
77 | +} | |
78 | +#endif | |
79 | + | |
80 | #endif /* _ASM_X86_SWITCH_TO_H */ | |
81 | diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c | |
82 | index 22802162eeb9..2e42b66b8ca4 100644 | |
83 | --- a/arch/x86/kernel/process_32.c | |
84 | +++ b/arch/x86/kernel/process_32.c | |
85 | @@ -284,9 +284,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |
86 | ||
87 | /* | |
88 | * Reload esp0 and cpu_current_top_of_stack. This changes | |
89 | - * current_thread_info(). | |
90 | + * current_thread_info(). Refresh the SYSENTER configuration in | |
91 | + * case prev or next is vm86. | |
92 | */ | |
93 | load_sp0(tss, next); | |
94 | + refresh_sysenter_cs(next); | |
95 | this_cpu_write(cpu_current_top_of_stack, | |
96 | (unsigned long)task_stack_page(next_p) + | |
97 | THREAD_SIZE); | |
98 | diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c | |
99 | index 1e7701c4cd80..565daaa6f18d 100644 | |
100 | --- a/arch/x86/kernel/process_64.c | |
101 | +++ b/arch/x86/kernel/process_64.c | |
102 | @@ -465,7 +465,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |
103 | */ | |
104 | this_cpu_write(current_task, next_p); | |
105 | ||
106 | - /* Reload esp0 and ss1. This changes current_thread_info(). */ | |
107 | + /* Reload sp0. */ | |
108 | load_sp0(tss, next); | |
109 | ||
110 | /* | |
111 | diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c | |
112 | index 7924a5356c8a..5bc1c3ab6287 100644 | |
113 | --- a/arch/x86/kernel/vm86_32.c | |
114 | +++ b/arch/x86/kernel/vm86_32.c | |
115 | @@ -54,6 +54,7 @@ | |
116 | #include <asm/irq.h> | |
117 | #include <asm/traps.h> | |
118 | #include <asm/vm86.h> | |
119 | +#include <asm/switch_to.h> | |
120 | ||
121 | /* | |
122 | * Known problems: | |
123 | @@ -149,6 +150,7 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval) | |
124 | tsk->thread.sp0 = vm86->saved_sp0; | |
125 | tsk->thread.sysenter_cs = __KERNEL_CS; | |
126 | load_sp0(tss, &tsk->thread); | |
127 | + refresh_sysenter_cs(&tsk->thread); | |
128 | vm86->saved_sp0 = 0; | |
129 | put_cpu(); | |
130 | ||
131 | @@ -368,8 +370,10 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus) | |
132 | /* make room for real-mode segments */ | |
133 | tsk->thread.sp0 += 16; | |
134 | ||
135 | - if (static_cpu_has(X86_FEATURE_SEP)) | |
136 | + if (static_cpu_has(X86_FEATURE_SEP)) { | |
137 | tsk->thread.sysenter_cs = 0; | |
138 | + refresh_sysenter_cs(&tsk->thread); | |
139 | + } | |
140 | ||
141 | load_sp0(tss, &tsk->thread); | |
142 | put_cpu(); | |
143 | -- | |
144 | 2.14.2 | |
145 |