]> git.proxmox.com Git - pve-kernel.git/blob - patches/kernel/0147-x86-entry-Fix-assumptions-that-the-HW-TSS-is-at-the-.patch
KPTI: add follow-up fixes
[pve-kernel.git] / patches / kernel / 0147-x86-entry-Fix-assumptions-that-the-HW-TSS-is-at-the-.patch
1 From 01e4ee94acbd960e302c23481529a5f5323d9969 Mon Sep 17 00:00:00 2001
2 From: Andy Lutomirski <luto@kernel.org>
3 Date: Mon, 4 Dec 2017 15:07:17 +0100
4 Subject: [PATCH 147/241] x86/entry: Fix assumptions that the HW TSS is at the
5 beginning of cpu_tss
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 A future patch will move SYSENTER_stack to the beginning of cpu_tss
13 to help detect overflow. Before this can happen, fix several code
14 paths that hardcode assumptions about the old layout.
15
16 Signed-off-by: Andy Lutomirski <luto@kernel.org>
17 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
18 Reviewed-by: Borislav Petkov <bp@suse.de>
19 Reviewed-by: Dave Hansen <dave.hansen@intel.com>
20 Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
21 Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
22 Cc: Borislav Petkov <bp@alien8.de>
23 Cc: Borislav Petkov <bpetkov@suse.de>
24 Cc: Brian Gerst <brgerst@gmail.com>
25 Cc: Dave Hansen <dave.hansen@linux.intel.com>
26 Cc: David Laight <David.Laight@aculab.com>
27 Cc: Denys Vlasenko <dvlasenk@redhat.com>
28 Cc: Eduardo Valentin <eduval@amazon.com>
29 Cc: Greg KH <gregkh@linuxfoundation.org>
30 Cc: H. Peter Anvin <hpa@zytor.com>
31 Cc: Josh Poimboeuf <jpoimboe@redhat.com>
32 Cc: Juergen Gross <jgross@suse.com>
33 Cc: Linus Torvalds <torvalds@linux-foundation.org>
34 Cc: Peter Zijlstra <peterz@infradead.org>
35 Cc: Rik van Riel <riel@redhat.com>
36 Cc: Will Deacon <will.deacon@arm.com>
37 Cc: aliguori@amazon.com
38 Cc: daniel.gruss@iaik.tugraz.at
39 Cc: hughd@google.com
40 Cc: keescook@google.com
41 Link: https://lkml.kernel.org/r/20171204150605.722425540@linutronix.de
42 Signed-off-by: Ingo Molnar <mingo@kernel.org>
43 (backported from commit 7fb983b4dd569e08564134a850dfd4eb1c63d9b8)
44 Signed-off-by: Andy Whitcroft <apw@canonical.com>
45 Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
46 (cherry picked from commit 7123a5de72dc59dea18ce8886e7db726f7259caf)
47 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
48 ---
49 arch/x86/include/asm/desc.h | 2 +-
50 arch/x86/include/asm/processor.h | 9 +++++++--
51 arch/x86/kernel/cpu/common.c | 8 ++++----
52 arch/x86/kernel/doublefault.c | 36 +++++++++++++++++-------------------
53 arch/x86/kvm/vmx.c | 2 +-
54 arch/x86/power/cpu.c | 13 +++++++------
55 6 files changed, 37 insertions(+), 33 deletions(-)
56
57 diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
58 index 81c9b1e8cae9..b817fe247506 100644
59 --- a/arch/x86/include/asm/desc.h
60 +++ b/arch/x86/include/asm/desc.h
61 @@ -190,7 +190,7 @@ static inline void set_tssldt_descriptor(void *d, unsigned long addr,
62 #endif
63 }
64
65 -static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
66 +static inline void __set_tss_desc(unsigned cpu, unsigned int entry, struct x86_hw_tss *addr)
67 {
68 struct desc_struct *d = get_cpu_gdt_rw(cpu);
69 tss_desc tss;
70 diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
71 index 5225917f9760..78123abdb046 100644
72 --- a/arch/x86/include/asm/processor.h
73 +++ b/arch/x86/include/asm/processor.h
74 @@ -161,7 +161,7 @@ extern struct cpuinfo_x86 new_cpu_data;
75
76 #include <linux/thread_info.h>
77
78 -extern struct tss_struct doublefault_tss;
79 +extern struct x86_hw_tss doublefault_tss;
80 extern __u32 cpu_caps_cleared[NCAPINTS];
81 extern __u32 cpu_caps_set[NCAPINTS];
82
83 @@ -246,6 +246,11 @@ static inline void load_cr3(pgd_t *pgdir)
84 write_cr3(__pa(pgdir));
85 }
86
87 +/*
88 + * Note that while the legacy 'TSS' name comes from 'Task State Segment',
89 + * on modern x86 CPUs the TSS also holds information important to 64-bit mode,
90 + * unrelated to the task-switch mechanism:
91 + */
92 #ifdef CONFIG_X86_32
93 /* This is the TSS defined by the hardware. */
94 struct x86_hw_tss {
95 @@ -316,7 +321,7 @@ struct x86_hw_tss {
96 #define IO_BITMAP_BITS 65536
97 #define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
98 #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
99 -#define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap)
100 +#define IO_BITMAP_OFFSET (offsetof(struct tss_struct, io_bitmap) - offsetof(struct tss_struct, x86_tss))
101 #define INVALID_IO_BITMAP_OFFSET 0x8000
102
103 struct tss_struct {
104 diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
105 index ffee73ec1af1..e526d82b546c 100644
106 --- a/arch/x86/kernel/cpu/common.c
107 +++ b/arch/x86/kernel/cpu/common.c
108 @@ -1558,7 +1558,7 @@ void cpu_init(void)
109 }
110 }
111
112 - t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
113 + t->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
114
115 /*
116 * <= is required because the CPU will access up to
117 @@ -1576,7 +1576,7 @@ void cpu_init(void)
118 * Initialize the TSS. Don't bother initializing sp0, as the initial
119 * task never enters user mode.
120 */
121 - set_tss_desc(cpu, t);
122 + set_tss_desc(cpu, &t->x86_tss);
123 load_TR_desc();
124
125 load_mm_ldt(&init_mm);
126 @@ -1633,12 +1633,12 @@ void cpu_init(void)
127 * Initialize the TSS. Don't bother initializing sp0, as the initial
128 * task never enters user mode.
129 */
130 - set_tss_desc(cpu, t);
131 + set_tss_desc(cpu, &t->x86_tss);
132 load_TR_desc();
133
134 load_mm_ldt(&init_mm);
135
136 - t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
137 + t->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
138
139 #ifdef CONFIG_DOUBLEFAULT
140 /* Set up doublefault TSS pointer in the GDT */
141 diff --git a/arch/x86/kernel/doublefault.c b/arch/x86/kernel/doublefault.c
142 index f9c324e08d85..a9fe79d49d39 100644
143 --- a/arch/x86/kernel/doublefault.c
144 +++ b/arch/x86/kernel/doublefault.c
145 @@ -49,25 +49,23 @@ static void doublefault_fn(void)
146 cpu_relax();
147 }
148
149 -struct tss_struct doublefault_tss __cacheline_aligned = {
150 - .x86_tss = {
151 - .sp0 = STACK_START,
152 - .ss0 = __KERNEL_DS,
153 - .ldt = 0,
154 - .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
155 -
156 - .ip = (unsigned long) doublefault_fn,
157 - /* 0x2 bit is always set */
158 - .flags = X86_EFLAGS_SF | 0x2,
159 - .sp = STACK_START,
160 - .es = __USER_DS,
161 - .cs = __KERNEL_CS,
162 - .ss = __KERNEL_DS,
163 - .ds = __USER_DS,
164 - .fs = __KERNEL_PERCPU,
165 -
166 - .__cr3 = __pa_nodebug(swapper_pg_dir),
167 - }
168 +struct x86_hw_tss doublefault_tss __cacheline_aligned = {
169 + .sp0 = STACK_START,
170 + .ss0 = __KERNEL_DS,
171 + .ldt = 0,
172 + .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
173 +
174 + .ip = (unsigned long) doublefault_fn,
175 + /* 0x2 bit is always set */
176 + .flags = X86_EFLAGS_SF | 0x2,
177 + .sp = STACK_START,
178 + .es = __USER_DS,
179 + .cs = __KERNEL_CS,
180 + .ss = __KERNEL_DS,
181 + .ds = __USER_DS,
182 + .fs = __KERNEL_PERCPU,
183 +
184 + .__cr3 = __pa_nodebug(swapper_pg_dir),
185 };
186
187 /* dummy for do_double_fault() call */
188 diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
189 index dd4996a96c71..a7c5a47beab7 100644
190 --- a/arch/x86/kvm/vmx.c
191 +++ b/arch/x86/kvm/vmx.c
192 @@ -2280,7 +2280,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
193 * processors. See 22.2.4.
194 */
195 vmcs_writel(HOST_TR_BASE,
196 - (unsigned long)this_cpu_ptr(&cpu_tss));
197 + (unsigned long)this_cpu_ptr(&cpu_tss.x86_tss));
198 vmcs_writel(HOST_GDTR_BASE, (unsigned long)gdt); /* 22.2.4 */
199
200 /*
201 diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
202 index 78459a6d455a..48cd87fc7222 100644
203 --- a/arch/x86/power/cpu.c
204 +++ b/arch/x86/power/cpu.c
205 @@ -165,12 +165,13 @@ static void fix_processor_context(void)
206 struct desc_struct *desc = get_cpu_gdt_rw(cpu);
207 tss_desc tss;
208 #endif
209 - set_tss_desc(cpu, t); /*
210 - * This just modifies memory; should not be
211 - * necessary. But... This is necessary, because
212 - * 386 hardware has concept of busy TSS or some
213 - * similar stupidity.
214 - */
215 +
216 + /*
217 + * This just modifies memory; should not be necessary. But... This is
218 + * necessary, because 386 hardware has concept of busy TSS or some
219 + * similar stupidity.
220 + */
221 + set_tss_desc(cpu, &t->x86_tss);
222
223 #ifdef CONFIG_X86_64
224 memcpy(&tss, &desc[GDT_ENTRY_TSS], sizeof(tss_desc));
225 --
226 2.14.2
227