]>
Commit | Line | Data |
---|---|---|
59d5af67 | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
321d628a FG |
2 | From: Andy Lutomirski <luto@kernel.org> |
3 | Date: Mon, 4 Dec 2017 15:07:28 +0100 | |
59d5af67 | 4 | Subject: [PATCH] x86/entry: Clean up the SYSENTER_stack code |
321d628a FG |
5 | MIME-Version: 1.0 |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | CVE-2017-5754 | |
10 | ||
11 | The existing code was a mess, mainly because C arrays are nasty. Turn | |
12 | SYSENTER_stack into a struct, add a helper to find it, and do all the | |
13 | obvious cleanups this enables. | |
14 | ||
15 | Signed-off-by: Andy Lutomirski <luto@kernel.org> | |
16 | Signed-off-by: Thomas Gleixner <tglx@linutronix.de> | |
17 | Reviewed-by: Thomas Gleixner <tglx@linutronix.de> | |
18 | Reviewed-by: Borislav Petkov <bpetkov@suse.de> | |
19 | Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> | |
20 | Cc: Borislav Petkov <bp@alien8.de> | |
21 | Cc: Brian Gerst <brgerst@gmail.com> | |
22 | Cc: Dave Hansen <dave.hansen@intel.com> | |
23 | Cc: Dave Hansen <dave.hansen@linux.intel.com> | |
24 | Cc: David Laight <David.Laight@aculab.com> | |
25 | Cc: Denys Vlasenko <dvlasenk@redhat.com> | |
26 | Cc: Eduardo Valentin <eduval@amazon.com> | |
27 | Cc: Greg KH <gregkh@linuxfoundation.org> | |
28 | Cc: H. Peter Anvin <hpa@zytor.com> | |
29 | Cc: Josh Poimboeuf <jpoimboe@redhat.com> | |
30 | Cc: Juergen Gross <jgross@suse.com> | |
31 | Cc: Linus Torvalds <torvalds@linux-foundation.org> | |
32 | Cc: Peter Zijlstra <peterz@infradead.org> | |
33 | Cc: Rik van Riel <riel@redhat.com> | |
34 | Cc: Will Deacon <will.deacon@arm.com> | |
35 | Cc: aliguori@amazon.com | |
36 | Cc: daniel.gruss@iaik.tugraz.at | |
37 | Cc: hughd@google.com | |
38 | Cc: keescook@google.com | |
39 | Link: https://lkml.kernel.org/r/20171204150606.653244723@linutronix.de | |
40 | Signed-off-by: Ingo Molnar <mingo@kernel.org> | |
41 | (cherry picked from commit 0f9a48100fba3f189724ae88a450c2261bf91c80) | |
42 | Signed-off-by: Andy Whitcroft <apw@canonical.com> | |
43 | Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> | |
44 | (cherry picked from commit a308af33c794110c52427ad11d3a6d35ffc14b76) | |
45 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
46 | --- | |
47 | arch/x86/include/asm/fixmap.h | 5 +++++ | |
48 | arch/x86/include/asm/processor.h | 6 +++++- | |
49 | arch/x86/kernel/asm-offsets.c | 6 ++---- | |
50 | arch/x86/kernel/cpu/common.c | 14 +++----------- | |
51 | arch/x86/kernel/dumpstack.c | 7 +++---- | |
52 | arch/x86/entry/entry_32.S | 4 ++-- | |
53 | arch/x86/entry/entry_64.S | 2 +- | |
54 | 7 files changed, 21 insertions(+), 23 deletions(-) | |
55 | ||
56 | diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h | |
57 | index 953aed54cb5e..56aaffbbffd6 100644 | |
58 | --- a/arch/x86/include/asm/fixmap.h | |
59 | +++ b/arch/x86/include/asm/fixmap.h | |
60 | @@ -225,5 +225,10 @@ static inline struct cpu_entry_area *get_cpu_entry_area(int cpu) | |
61 | return (struct cpu_entry_area *)__fix_to_virt(__get_cpu_entry_area_page_index(cpu, 0)); | |
62 | } | |
63 | ||
64 | +static inline struct SYSENTER_stack *cpu_SYSENTER_stack(int cpu) | |
65 | +{ | |
66 | + return &get_cpu_entry_area(cpu)->tss.SYSENTER_stack; | |
67 | +} | |
68 | + | |
69 | #endif /* !__ASSEMBLY__ */ | |
70 | #endif /* _ASM_X86_FIXMAP_H */ | |
71 | diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h | |
72 | index 4737d378d7b5..2d489a414a86 100644 | |
73 | --- a/arch/x86/include/asm/processor.h | |
74 | +++ b/arch/x86/include/asm/processor.h | |
75 | @@ -330,12 +330,16 @@ struct x86_hw_tss { | |
76 | #define IO_BITMAP_OFFSET (offsetof(struct tss_struct, io_bitmap) - offsetof(struct tss_struct, x86_tss)) | |
77 | #define INVALID_IO_BITMAP_OFFSET 0x8000 | |
78 | ||
79 | +struct SYSENTER_stack { | |
80 | + unsigned long words[64]; | |
81 | +}; | |
82 | + | |
83 | struct tss_struct { | |
84 | /* | |
85 | * Space for the temporary SYSENTER stack, used for SYSENTER | |
86 | * and the entry trampoline as well. | |
87 | */ | |
88 | - unsigned long SYSENTER_stack[64]; | |
89 | + struct SYSENTER_stack SYSENTER_stack; | |
90 | ||
91 | /* | |
92 | * The fixed hardware portion. This must not cross a page boundary | |
93 | diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c | |
94 | index 822be00c85ff..00ea20bfa857 100644 | |
95 | --- a/arch/x86/kernel/asm-offsets.c | |
96 | +++ b/arch/x86/kernel/asm-offsets.c | |
97 | @@ -93,10 +93,8 @@ void common(void) { | |
98 | BLANK(); | |
99 | DEFINE(PTREGS_SIZE, sizeof(struct pt_regs)); | |
100 | ||
101 | - /* Offset from cpu_tss to SYSENTER_stack */ | |
102 | - OFFSET(CPU_TSS_SYSENTER_stack, tss_struct, SYSENTER_stack); | |
103 | - /* Size of SYSENTER_stack */ | |
104 | - DEFINE(SIZEOF_SYSENTER_stack, sizeof(((struct tss_struct *)0)->SYSENTER_stack)); | |
105 | + OFFSET(TSS_STRUCT_SYSENTER_stack, tss_struct, SYSENTER_stack); | |
106 | + DEFINE(SIZEOF_SYSENTER_stack, sizeof(struct SYSENTER_stack)); | |
107 | ||
108 | /* Layout info for cpu_entry_area */ | |
109 | OFFSET(CPU_ENTRY_AREA_tss, cpu_entry_area, tss); | |
110 | diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c | |
111 | index f487766855d3..f9541c48c290 100644 | |
112 | --- a/arch/x86/kernel/cpu/common.c | |
113 | +++ b/arch/x86/kernel/cpu/common.c | |
114 | @@ -1306,12 +1306,7 @@ void enable_sep_cpu(void) | |
115 | ||
116 | tss->x86_tss.ss1 = __KERNEL_CS; | |
117 | wrmsr(MSR_IA32_SYSENTER_CS, tss->x86_tss.ss1, 0); | |
118 | - | |
119 | - wrmsr(MSR_IA32_SYSENTER_ESP, | |
120 | - (unsigned long)&get_cpu_entry_area(cpu)->tss + | |
121 | - offsetofend(struct tss_struct, SYSENTER_stack), | |
122 | - 0); | |
123 | - | |
124 | + wrmsr(MSR_IA32_SYSENTER_ESP, (unsigned long)(cpu_SYSENTER_stack(cpu) + 1), 0); | |
125 | wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long)entry_SYSENTER_32, 0); | |
126 | ||
127 | put_cpu(); | |
128 | @@ -1437,9 +1432,7 @@ void syscall_init(void) | |
129 | * AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit). | |
130 | */ | |
131 | wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS); | |
132 | - wrmsrl_safe(MSR_IA32_SYSENTER_ESP, | |
133 | - (unsigned long)&get_cpu_entry_area(cpu)->tss + | |
134 | - offsetofend(struct tss_struct, SYSENTER_stack)); | |
135 | + wrmsrl_safe(MSR_IA32_SYSENTER_ESP, (unsigned long)(cpu_SYSENTER_stack(cpu) + 1)); | |
136 | wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat); | |
137 | #else | |
138 | wrmsrl(MSR_CSTAR, (unsigned long)ignore_sysret); | |
139 | @@ -1653,8 +1646,7 @@ void cpu_init(void) | |
140 | */ | |
141 | set_tss_desc(cpu, &get_cpu_entry_area(cpu)->tss.x86_tss); | |
142 | load_TR_desc(); | |
143 | - load_sp0((unsigned long)&get_cpu_entry_area(cpu)->tss + | |
144 | - offsetofend(struct tss_struct, SYSENTER_stack)); | |
145 | + load_sp0((unsigned long)(cpu_SYSENTER_stack(cpu) + 1)); | |
146 | ||
147 | load_mm_ldt(&init_mm); | |
148 | ||
149 | diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c | |
150 | index c32c6cce9dcc..b005e5ef6738 100644 | |
151 | --- a/arch/x86/kernel/dumpstack.c | |
152 | +++ b/arch/x86/kernel/dumpstack.c | |
153 | @@ -45,11 +45,10 @@ bool in_task_stack(unsigned long *stack, struct task_struct *task, | |
154 | ||
155 | bool in_sysenter_stack(unsigned long *stack, struct stack_info *info) | |
156 | { | |
157 | - int cpu = smp_processor_id(); | |
158 | - struct tss_struct *tss = &get_cpu_entry_area(cpu)->tss; | |
159 | + struct SYSENTER_stack *ss = cpu_SYSENTER_stack(smp_processor_id()); | |
160 | ||
161 | - void *begin = &tss->SYSENTER_stack; | |
162 | - void *end = (void *)&tss->SYSENTER_stack + sizeof(tss->SYSENTER_stack); | |
163 | + void *begin = ss; | |
164 | + void *end = ss + 1; | |
165 | ||
166 | if ((void *)stack < begin || (void *)stack >= end) | |
167 | return false; | |
168 | diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S | |
169 | index 41e0e103f090..04abcd3f8e2d 100644 | |
170 | --- a/arch/x86/entry/entry_32.S | |
171 | +++ b/arch/x86/entry/entry_32.S | |
172 | @@ -949,7 +949,7 @@ ENTRY(debug) | |
173 | ||
174 | /* Are we currently on the SYSENTER stack? */ | |
175 | movl PER_CPU_VAR(cpu_entry_area), %ecx | |
176 | - addl $CPU_ENTRY_AREA_tss + CPU_TSS_SYSENTER_stack + SIZEOF_SYSENTER_stack, %ecx | |
177 | + addl $CPU_ENTRY_AREA_tss + TSS_STRUCT_SYSENTER_stack + SIZEOF_SYSENTER_stack, %ecx | |
178 | subl %eax, %ecx /* ecx = (end of SYSENTER_stack) - esp */ | |
179 | cmpl $SIZEOF_SYSENTER_stack, %ecx | |
180 | jb .Ldebug_from_sysenter_stack | |
181 | @@ -993,7 +993,7 @@ ENTRY(nmi) | |
182 | ||
183 | /* Are we currently on the SYSENTER stack? */ | |
184 | movl PER_CPU_VAR(cpu_entry_area), %ecx | |
185 | - addl $CPU_ENTRY_AREA_tss + CPU_TSS_SYSENTER_stack + SIZEOF_SYSENTER_stack, %ecx | |
186 | + addl $CPU_ENTRY_AREA_tss + TSS_STRUCT_SYSENTER_stack + SIZEOF_SYSENTER_stack, %ecx | |
187 | subl %eax, %ecx /* ecx = (end of SYSENTER_stack) - esp */ | |
188 | cmpl $SIZEOF_SYSENTER_stack, %ecx | |
189 | jb .Lnmi_from_sysenter_stack | |
190 | diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S | |
191 | index dc100a7052ee..7a5e9edcdaf4 100644 | |
192 | --- a/arch/x86/entry/entry_64.S | |
193 | +++ b/arch/x86/entry/entry_64.S | |
194 | @@ -153,7 +153,7 @@ END(native_usergs_sysret64) | |
195 | _entry_trampoline - CPU_ENTRY_AREA_entry_trampoline(%rip) | |
196 | ||
197 | /* The top word of the SYSENTER stack is hot and is usable as scratch space. */ | |
198 | -#define RSP_SCRATCH CPU_ENTRY_AREA_tss + CPU_TSS_SYSENTER_stack + \ | |
199 | +#define RSP_SCRATCH CPU_ENTRY_AREA_tss + TSS_STRUCT_SYSENTER_stack + \ | |
200 | SIZEOF_SYSENTER_stack - 8 + CPU_ENTRY_AREA | |
201 | ||
202 | ENTRY(entry_SYSCALL_64_trampoline) | |
203 | -- | |
204 | 2.14.2 | |
205 |