]>
Commit | Line | Data |
---|---|---|
b7ca0ba0 SL |
1 | From b701dea6dc812612ab54e2b524182f1eea7dc78a Mon Sep 17 00:00:00 2001 |
2 | From: Sasha Levin <sashal@kernel.org> | |
3 | Date: Sat, 13 Feb 2021 11:19:44 -0800 | |
4 | Subject: x86/stackprotector/32: Make the canary into a regular percpu variable | |
5 | ||
6 | From: Andy Lutomirski <luto@kernel.org> | |
7 | ||
8 | [ Upstream commit 3fb0fdb3bbe7aed495109b3296b06c2409734023 ] | |
9 | ||
10 | On 32-bit kernels, the stackprotector canary is quite nasty -- it is | |
11 | stored at %gs:(20), which is nasty because 32-bit kernels use %fs for | |
12 | percpu storage. It's even nastier because it means that whether %gs | |
13 | contains userspace state or kernel state while running kernel code | |
14 | depends on whether stackprotector is enabled (this is | |
15 | CONFIG_X86_32_LAZY_GS), and this setting radically changes the way | |
16 | that segment selectors work. Supporting both variants is a | |
17 | maintenance and testing mess. | |
18 | ||
19 | Merely rearranging so that percpu and the stack canary | |
20 | share the same segment would be messy as the 32-bit percpu address | |
21 | layout isn't currently compatible with putting a variable at a fixed | |
22 | offset. | |
23 | ||
24 | Fortunately, GCC 8.1 added options that allow the stack canary to be | |
25 | accessed as %fs:__stack_chk_guard, effectively turning it into an ordinary | |
26 | percpu variable. This lets us get rid of all of the code to manage the | |
27 | stack canary GDT descriptor and the CONFIG_X86_32_LAZY_GS mess. | |
28 | ||
29 | (That name is special. We could use any symbol we want for the | |
30 | %fs-relative mode, but for CONFIG_SMP=n, gcc refuses to let us use any | |
31 | name other than __stack_chk_guard.) | |
32 | ||
33 | Forcibly disable stackprotector on older compilers that don't support | |
34 | the new options and turn the stack canary into a percpu variable. The | |
35 | "lazy GS" approach is now used for all 32-bit configurations. | |
36 | ||
37 | Also makes load_gs_index() work on 32-bit kernels. On 64-bit kernels, | |
38 | it loads the GS selector and updates the user GSBASE accordingly. (This | |
39 | is unchanged.) On 32-bit kernels, it loads the GS selector and updates | |
40 | GSBASE, which is now always the user base. This means that the overall | |
41 | effect is the same on 32-bit and 64-bit, which avoids some ifdeffery. | |
42 | ||
43 | [ bp: Massage commit message. ] | |
44 | ||
45 | Signed-off-by: Andy Lutomirski <luto@kernel.org> | |
46 | Signed-off-by: Borislav Petkov <bp@suse.de> | |
47 | Link: https://lkml.kernel.org/r/c0ff7dba14041c7e5d1cae5d4df052f03759bef3.1613243844.git.luto@kernel.org | |
48 | Stable-dep-of: e3f269ed0acc ("x86/pm: Work around false positive kmemleak report in msr_build_context()") | |
49 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
50 | --- | |
51 | arch/x86/Kconfig | 7 +- | |
52 | arch/x86/Makefile | 8 +++ | |
53 | arch/x86/entry/entry_32.S | 56 ++-------------- | |
54 | arch/x86/include/asm/processor.h | 15 ++--- | |
55 | arch/x86/include/asm/ptrace.h | 5 +- | |
56 | arch/x86/include/asm/segment.h | 30 +++------ | |
57 | arch/x86/include/asm/stackprotector.h | 79 +++++------------------ | |
58 | arch/x86/include/asm/suspend_32.h | 6 +- | |
59 | arch/x86/kernel/asm-offsets_32.c | 5 -- | |
60 | arch/x86/kernel/cpu/common.c | 5 +- | |
61 | arch/x86/kernel/doublefault_32.c | 4 +- | |
62 | arch/x86/kernel/head_32.S | 18 +----- | |
63 | arch/x86/kernel/setup_percpu.c | 1 - | |
64 | arch/x86/kernel/tls.c | 8 +-- | |
65 | arch/x86/lib/insn-eval.c | 4 -- | |
66 | arch/x86/platform/pvh/head.S | 14 ---- | |
67 | arch/x86/power/cpu.c | 6 +- | |
68 | arch/x86/xen/enlighten_pv.c | 1 - | |
69 | scripts/gcc-x86_32-has-stack-protector.sh | 6 +- | |
70 | 19 files changed, 60 insertions(+), 218 deletions(-) | |
71 | ||
72 | diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig | |
73 | index 6dc670e363939..47c94e9de03e4 100644 | |
74 | --- a/arch/x86/Kconfig | |
75 | +++ b/arch/x86/Kconfig | |
76 | @@ -352,10 +352,6 @@ config X86_64_SMP | |
77 | def_bool y | |
78 | depends on X86_64 && SMP | |
79 | ||
80 | -config X86_32_LAZY_GS | |
81 | - def_bool y | |
82 | - depends on X86_32 && !STACKPROTECTOR | |
83 | - | |
84 | config ARCH_SUPPORTS_UPROBES | |
85 | def_bool y | |
86 | ||
87 | @@ -378,7 +374,8 @@ config CC_HAS_SANE_STACKPROTECTOR | |
88 | default $(success,$(srctree)/scripts/gcc-x86_32-has-stack-protector.sh $(CC)) | |
89 | help | |
90 | We have to make sure stack protector is unconditionally disabled if | |
91 | - the compiler produces broken code. | |
92 | + the compiler produces broken code or if it does not let us control | |
93 | + the segment on 32-bit kernels. | |
94 | ||
95 | menu "Processor type and features" | |
96 | ||
97 | diff --git a/arch/x86/Makefile b/arch/x86/Makefile | |
98 | index 1f796050c6dde..8b9fa777f513b 100644 | |
99 | --- a/arch/x86/Makefile | |
100 | +++ b/arch/x86/Makefile | |
101 | @@ -87,6 +87,14 @@ ifeq ($(CONFIG_X86_32),y) | |
102 | ||
103 | # temporary until string.h is fixed | |
104 | KBUILD_CFLAGS += -ffreestanding | |
105 | + | |
106 | + ifeq ($(CONFIG_STACKPROTECTOR),y) | |
107 | + ifeq ($(CONFIG_SMP),y) | |
108 | + KBUILD_CFLAGS += -mstack-protector-guard-reg=fs -mstack-protector-guard-symbol=__stack_chk_guard | |
109 | + else | |
110 | + KBUILD_CFLAGS += -mstack-protector-guard=global | |
111 | + endif | |
112 | + endif | |
113 | else | |
114 | BITS := 64 | |
115 | UTS_MACHINE := x86_64 | |
116 | diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S | |
117 | index 70bd81b6c612e..10b7c62a3e97a 100644 | |
118 | --- a/arch/x86/entry/entry_32.S | |
119 | +++ b/arch/x86/entry/entry_32.S | |
120 | @@ -20,7 +20,7 @@ | |
121 | * 1C(%esp) - %ds | |
122 | * 20(%esp) - %es | |
123 | * 24(%esp) - %fs | |
124 | - * 28(%esp) - %gs saved iff !CONFIG_X86_32_LAZY_GS | |
125 | + * 28(%esp) - unused -- was %gs on old stackprotector kernels | |
126 | * 2C(%esp) - orig_eax | |
127 | * 30(%esp) - %eip | |
128 | * 34(%esp) - %cs | |
129 | @@ -56,14 +56,9 @@ | |
130 | /* | |
131 | * User gs save/restore | |
132 | * | |
133 | - * %gs is used for userland TLS and kernel only uses it for stack | |
134 | - * canary which is required to be at %gs:20 by gcc. Read the comment | |
135 | - * at the top of stackprotector.h for more info. | |
136 | - * | |
137 | - * Local labels 98 and 99 are used. | |
138 | + * This is leftover junk from CONFIG_X86_32_LAZY_GS. A subsequent patch | |
139 | + * will remove it entirely. | |
140 | */ | |
141 | -#ifdef CONFIG_X86_32_LAZY_GS | |
142 | - | |
143 | /* unfortunately push/pop can't be no-op */ | |
144 | .macro PUSH_GS | |
145 | pushl $0 | |
146 | @@ -86,49 +81,6 @@ | |
147 | .macro SET_KERNEL_GS reg | |
148 | .endm | |
149 | ||
150 | -#else /* CONFIG_X86_32_LAZY_GS */ | |
151 | - | |
152 | -.macro PUSH_GS | |
153 | - pushl %gs | |
154 | -.endm | |
155 | - | |
156 | -.macro POP_GS pop=0 | |
157 | -98: popl %gs | |
158 | - .if \pop <> 0 | |
159 | - add $\pop, %esp | |
160 | - .endif | |
161 | -.endm | |
162 | -.macro POP_GS_EX | |
163 | -.pushsection .fixup, "ax" | |
164 | -99: movl $0, (%esp) | |
165 | - jmp 98b | |
166 | -.popsection | |
167 | - _ASM_EXTABLE(98b, 99b) | |
168 | -.endm | |
169 | - | |
170 | -.macro PTGS_TO_GS | |
171 | -98: mov PT_GS(%esp), %gs | |
172 | -.endm | |
173 | -.macro PTGS_TO_GS_EX | |
174 | -.pushsection .fixup, "ax" | |
175 | -99: movl $0, PT_GS(%esp) | |
176 | - jmp 98b | |
177 | -.popsection | |
178 | - _ASM_EXTABLE(98b, 99b) | |
179 | -.endm | |
180 | - | |
181 | -.macro GS_TO_REG reg | |
182 | - movl %gs, \reg | |
183 | -.endm | |
184 | -.macro REG_TO_PTGS reg | |
185 | - movl \reg, PT_GS(%esp) | |
186 | -.endm | |
187 | -.macro SET_KERNEL_GS reg | |
188 | - movl $(__KERNEL_STACK_CANARY), \reg | |
189 | - movl \reg, %gs | |
190 | -.endm | |
191 | - | |
192 | -#endif /* CONFIG_X86_32_LAZY_GS */ | |
193 | ||
194 | /* Unconditionally switch to user cr3 */ | |
195 | .macro SWITCH_TO_USER_CR3 scratch_reg:req | |
196 | @@ -779,7 +731,7 @@ SYM_CODE_START(__switch_to_asm) | |
197 | ||
198 | #ifdef CONFIG_STACKPROTECTOR | |
199 | movl TASK_stack_canary(%edx), %ebx | |
200 | - movl %ebx, PER_CPU_VAR(stack_canary)+stack_canary_offset | |
201 | + movl %ebx, PER_CPU_VAR(__stack_chk_guard) | |
202 | #endif | |
203 | ||
204 | /* | |
205 | diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h | |
206 | index d7e017b0b4c3b..6dc3c5f0be076 100644 | |
207 | --- a/arch/x86/include/asm/processor.h | |
208 | +++ b/arch/x86/include/asm/processor.h | |
209 | @@ -441,6 +441,9 @@ struct fixed_percpu_data { | |
210 | * GCC hardcodes the stack canary as %gs:40. Since the | |
211 | * irq_stack is the object at %gs:0, we reserve the bottom | |
212 | * 48 bytes of the irq stack for the canary. | |
213 | + * | |
214 | + * Once we are willing to require -mstack-protector-guard-symbol= | |
215 | + * support for x86_64 stackprotector, we can get rid of this. | |
216 | */ | |
217 | char gs_base[40]; | |
218 | unsigned long stack_canary; | |
219 | @@ -461,17 +464,7 @@ extern asmlinkage void ignore_sysret(void); | |
220 | void current_save_fsgs(void); | |
221 | #else /* X86_64 */ | |
222 | #ifdef CONFIG_STACKPROTECTOR | |
223 | -/* | |
224 | - * Make sure stack canary segment base is cached-aligned: | |
225 | - * "For Intel Atom processors, avoid non zero segment base address | |
226 | - * that is not aligned to cache line boundary at all cost." | |
227 | - * (Optim Ref Manual Assembly/Compiler Coding Rule 15.) | |
228 | - */ | |
229 | -struct stack_canary { | |
230 | - char __pad[20]; /* canary at %gs:20 */ | |
231 | - unsigned long canary; | |
232 | -}; | |
233 | -DECLARE_PER_CPU_ALIGNED(struct stack_canary, stack_canary); | |
234 | +DECLARE_PER_CPU(unsigned long, __stack_chk_guard); | |
235 | #endif | |
236 | /* Per CPU softirq stack pointer */ | |
237 | DECLARE_PER_CPU(struct irq_stack *, softirq_stack_ptr); | |
238 | diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h | |
239 | index 409f661481e11..b94f615600d57 100644 | |
240 | --- a/arch/x86/include/asm/ptrace.h | |
241 | +++ b/arch/x86/include/asm/ptrace.h | |
242 | @@ -37,7 +37,10 @@ struct pt_regs { | |
243 | unsigned short __esh; | |
244 | unsigned short fs; | |
245 | unsigned short __fsh; | |
246 | - /* On interrupt, gs and __gsh store the vector number. */ | |
247 | + /* | |
248 | + * On interrupt, gs and __gsh store the vector number. They never | |
249 | + * store gs any more. | |
250 | + */ | |
251 | unsigned short gs; | |
252 | unsigned short __gsh; | |
253 | /* On interrupt, this is the error code. */ | |
254 | diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h | |
255 | index 7fdd4facfce71..72044026eb3c2 100644 | |
256 | --- a/arch/x86/include/asm/segment.h | |
257 | +++ b/arch/x86/include/asm/segment.h | |
258 | @@ -95,7 +95,7 @@ | |
259 | * | |
260 | * 26 - ESPFIX small SS | |
261 | * 27 - per-cpu [ offset to per-cpu data area ] | |
262 | - * 28 - stack_canary-20 [ for stack protector ] <=== cacheline #8 | |
263 | + * 28 - unused | |
264 | * 29 - unused | |
265 | * 30 - unused | |
266 | * 31 - TSS for double fault handler | |
267 | @@ -118,7 +118,6 @@ | |
268 | ||
269 | #define GDT_ENTRY_ESPFIX_SS 26 | |
270 | #define GDT_ENTRY_PERCPU 27 | |
271 | -#define GDT_ENTRY_STACK_CANARY 28 | |
272 | ||
273 | #define GDT_ENTRY_DOUBLEFAULT_TSS 31 | |
274 | ||
275 | @@ -158,12 +157,6 @@ | |
276 | # define __KERNEL_PERCPU 0 | |
277 | #endif | |
278 | ||
279 | -#ifdef CONFIG_STACKPROTECTOR | |
280 | -# define __KERNEL_STACK_CANARY (GDT_ENTRY_STACK_CANARY*8) | |
281 | -#else | |
282 | -# define __KERNEL_STACK_CANARY 0 | |
283 | -#endif | |
284 | - | |
285 | #else /* 64-bit: */ | |
286 | ||
287 | #include <asm/cache.h> | |
288 | @@ -364,22 +357,15 @@ static inline void __loadsegment_fs(unsigned short value) | |
289 | asm("mov %%" #seg ",%0":"=r" (value) : : "memory") | |
290 | ||
291 | /* | |
292 | - * x86-32 user GS accessors: | |
293 | + * x86-32 user GS accessors. This is ugly and could do with some cleaning up. | |
294 | */ | |
295 | #ifdef CONFIG_X86_32 | |
296 | -# ifdef CONFIG_X86_32_LAZY_GS | |
297 | -# define get_user_gs(regs) (u16)({ unsigned long v; savesegment(gs, v); v; }) | |
298 | -# define set_user_gs(regs, v) loadsegment(gs, (unsigned long)(v)) | |
299 | -# define task_user_gs(tsk) ((tsk)->thread.gs) | |
300 | -# define lazy_save_gs(v) savesegment(gs, (v)) | |
301 | -# define lazy_load_gs(v) loadsegment(gs, (v)) | |
302 | -# else /* X86_32_LAZY_GS */ | |
303 | -# define get_user_gs(regs) (u16)((regs)->gs) | |
304 | -# define set_user_gs(regs, v) do { (regs)->gs = (v); } while (0) | |
305 | -# define task_user_gs(tsk) (task_pt_regs(tsk)->gs) | |
306 | -# define lazy_save_gs(v) do { } while (0) | |
307 | -# define lazy_load_gs(v) do { } while (0) | |
308 | -# endif /* X86_32_LAZY_GS */ | |
309 | +# define get_user_gs(regs) (u16)({ unsigned long v; savesegment(gs, v); v; }) | |
310 | +# define set_user_gs(regs, v) loadsegment(gs, (unsigned long)(v)) | |
311 | +# define task_user_gs(tsk) ((tsk)->thread.gs) | |
312 | +# define lazy_save_gs(v) savesegment(gs, (v)) | |
313 | +# define lazy_load_gs(v) loadsegment(gs, (v)) | |
314 | +# define load_gs_index(v) loadsegment(gs, (v)) | |
315 | #endif /* X86_32 */ | |
316 | ||
317 | #endif /* !__ASSEMBLY__ */ | |
318 | diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h | |
319 | index 7fb482f0f25b0..b6ffe58c70fab 100644 | |
320 | --- a/arch/x86/include/asm/stackprotector.h | |
321 | +++ b/arch/x86/include/asm/stackprotector.h | |
322 | @@ -5,30 +5,23 @@ | |
323 | * Stack protector works by putting predefined pattern at the start of | |
324 | * the stack frame and verifying that it hasn't been overwritten when | |
325 | * returning from the function. The pattern is called stack canary | |
326 | - * and unfortunately gcc requires it to be at a fixed offset from %gs. | |
327 | - * On x86_64, the offset is 40 bytes and on x86_32 20 bytes. x86_64 | |
328 | - * and x86_32 use segment registers differently and thus handles this | |
329 | - * requirement differently. | |
330 | + * and unfortunately gcc historically required it to be at a fixed offset | |
331 | + * from the percpu segment base. On x86_64, the offset is 40 bytes. | |
332 | * | |
333 | - * On x86_64, %gs is shared by percpu area and stack canary. All | |
334 | - * percpu symbols are zero based and %gs points to the base of percpu | |
335 | - * area. The first occupant of the percpu area is always | |
336 | - * fixed_percpu_data which contains stack_canary at offset 40. Userland | |
337 | - * %gs is always saved and restored on kernel entry and exit using | |
338 | - * swapgs, so stack protector doesn't add any complexity there. | |
339 | + * The same segment is shared by percpu area and stack canary. On | |
340 | + * x86_64, percpu symbols are zero based and %gs (64-bit) points to the | |
341 | + * base of percpu area. The first occupant of the percpu area is always | |
342 | + * fixed_percpu_data which contains stack_canary at the approproate | |
343 | + * offset. On x86_32, the stack canary is just a regular percpu | |
344 | + * variable. | |
345 | * | |
346 | - * On x86_32, it's slightly more complicated. As in x86_64, %gs is | |
347 | - * used for userland TLS. Unfortunately, some processors are much | |
348 | - * slower at loading segment registers with different value when | |
349 | - * entering and leaving the kernel, so the kernel uses %fs for percpu | |
350 | - * area and manages %gs lazily so that %gs is switched only when | |
351 | - * necessary, usually during task switch. | |
352 | + * Putting percpu data in %fs on 32-bit is a minor optimization compared to | |
353 | + * using %gs. Since 32-bit userspace normally has %fs == 0, we are likely | |
354 | + * to load 0 into %fs on exit to usermode, whereas with percpu data in | |
355 | + * %gs, we are likely to load a non-null %gs on return to user mode. | |
356 | * | |
357 | - * As gcc requires the stack canary at %gs:20, %gs can't be managed | |
358 | - * lazily if stack protector is enabled, so the kernel saves and | |
359 | - * restores userland %gs on kernel entry and exit. This behavior is | |
360 | - * controlled by CONFIG_X86_32_LAZY_GS and accessors are defined in | |
361 | - * system.h to hide the details. | |
362 | + * Once we are willing to require GCC 8.1 or better for 64-bit stackprotector | |
363 | + * support, we can remove some of this complexity. | |
364 | */ | |
365 | ||
366 | #ifndef _ASM_STACKPROTECTOR_H | |
367 | @@ -44,14 +37,6 @@ | |
368 | #include <linux/random.h> | |
369 | #include <linux/sched.h> | |
370 | ||
371 | -/* | |
372 | - * 24 byte read-only segment initializer for stack canary. Linker | |
373 | - * can't handle the address bit shifting. Address will be set in | |
374 | - * head_32 for boot CPU and setup_per_cpu_areas() for others. | |
375 | - */ | |
376 | -#define GDT_STACK_CANARY_INIT \ | |
377 | - [GDT_ENTRY_STACK_CANARY] = GDT_ENTRY_INIT(0x4090, 0, 0x18), | |
378 | - | |
379 | /* | |
380 | * Initialize the stackprotector canary value. | |
381 | * | |
382 | @@ -86,7 +71,7 @@ static __always_inline void boot_init_stack_canary(void) | |
383 | #ifdef CONFIG_X86_64 | |
384 | this_cpu_write(fixed_percpu_data.stack_canary, canary); | |
385 | #else | |
386 | - this_cpu_write(stack_canary.canary, canary); | |
387 | + this_cpu_write(__stack_chk_guard, canary); | |
388 | #endif | |
389 | } | |
390 | ||
391 | @@ -95,48 +80,16 @@ static inline void cpu_init_stack_canary(int cpu, struct task_struct *idle) | |
392 | #ifdef CONFIG_X86_64 | |
393 | per_cpu(fixed_percpu_data.stack_canary, cpu) = idle->stack_canary; | |
394 | #else | |
395 | - per_cpu(stack_canary.canary, cpu) = idle->stack_canary; | |
396 | -#endif | |
397 | -} | |
398 | - | |
399 | -static inline void setup_stack_canary_segment(int cpu) | |
400 | -{ | |
401 | -#ifdef CONFIG_X86_32 | |
402 | - unsigned long canary = (unsigned long)&per_cpu(stack_canary, cpu); | |
403 | - struct desc_struct *gdt_table = get_cpu_gdt_rw(cpu); | |
404 | - struct desc_struct desc; | |
405 | - | |
406 | - desc = gdt_table[GDT_ENTRY_STACK_CANARY]; | |
407 | - set_desc_base(&desc, canary); | |
408 | - write_gdt_entry(gdt_table, GDT_ENTRY_STACK_CANARY, &desc, DESCTYPE_S); | |
409 | -#endif | |
410 | -} | |
411 | - | |
412 | -static inline void load_stack_canary_segment(void) | |
413 | -{ | |
414 | -#ifdef CONFIG_X86_32 | |
415 | - asm("mov %0, %%gs" : : "r" (__KERNEL_STACK_CANARY) : "memory"); | |
416 | + per_cpu(__stack_chk_guard, cpu) = idle->stack_canary; | |
417 | #endif | |
418 | } | |
419 | ||
420 | #else /* STACKPROTECTOR */ | |
421 | ||
422 | -#define GDT_STACK_CANARY_INIT | |
423 | - | |
424 | /* dummy boot_init_stack_canary() is defined in linux/stackprotector.h */ | |
425 | ||
426 | -static inline void setup_stack_canary_segment(int cpu) | |
427 | -{ } | |
428 | - | |
429 | static inline void cpu_init_stack_canary(int cpu, struct task_struct *idle) | |
430 | { } | |
431 | ||
432 | -static inline void load_stack_canary_segment(void) | |
433 | -{ | |
434 | -#ifdef CONFIG_X86_32 | |
435 | - asm volatile ("mov %0, %%gs" : : "r" (0)); | |
436 | -#endif | |
437 | -} | |
438 | - | |
439 | #endif /* STACKPROTECTOR */ | |
440 | #endif /* _ASM_STACKPROTECTOR_H */ | |
441 | diff --git a/arch/x86/include/asm/suspend_32.h b/arch/x86/include/asm/suspend_32.h | |
442 | index 3b97aa9215430..a800abb1a9925 100644 | |
443 | --- a/arch/x86/include/asm/suspend_32.h | |
444 | +++ b/arch/x86/include/asm/suspend_32.h | |
445 | @@ -13,12 +13,10 @@ | |
446 | /* image of the saved processor state */ | |
447 | struct saved_context { | |
448 | /* | |
449 | - * On x86_32, all segment registers, with the possible exception of | |
450 | - * gs, are saved at kernel entry in pt_regs. | |
451 | + * On x86_32, all segment registers except gs are saved at kernel | |
452 | + * entry in pt_regs. | |
453 | */ | |
454 | -#ifdef CONFIG_X86_32_LAZY_GS | |
455 | u16 gs; | |
456 | -#endif | |
457 | unsigned long cr0, cr2, cr3, cr4; | |
458 | u64 misc_enable; | |
459 | struct saved_msrs saved_msrs; | |
460 | diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c | |
461 | index 6e043f295a605..2b411cd00a4e2 100644 | |
462 | --- a/arch/x86/kernel/asm-offsets_32.c | |
463 | +++ b/arch/x86/kernel/asm-offsets_32.c | |
464 | @@ -53,11 +53,6 @@ void foo(void) | |
465 | offsetof(struct cpu_entry_area, tss.x86_tss.sp1) - | |
466 | offsetofend(struct cpu_entry_area, entry_stack_page.stack)); | |
467 | ||
468 | -#ifdef CONFIG_STACKPROTECTOR | |
469 | - BLANK(); | |
470 | - OFFSET(stack_canary_offset, stack_canary, canary); | |
471 | -#endif | |
472 | - | |
473 | BLANK(); | |
474 | DEFINE(EFI_svam, offsetof(efi_runtime_services_t, set_virtual_address_map)); | |
475 | } | |
476 | diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c | |
477 | index 0c72ff732aa08..33002cb5a1c62 100644 | |
478 | --- a/arch/x86/kernel/cpu/common.c | |
479 | +++ b/arch/x86/kernel/cpu/common.c | |
480 | @@ -166,7 +166,6 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { | |
481 | ||
482 | [GDT_ENTRY_ESPFIX_SS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff), | |
483 | [GDT_ENTRY_PERCPU] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff), | |
484 | - GDT_STACK_CANARY_INIT | |
485 | #endif | |
486 | } }; | |
487 | EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); | |
488 | @@ -600,7 +599,6 @@ void load_percpu_segment(int cpu) | |
489 | __loadsegment_simple(gs, 0); | |
490 | wrmsrl(MSR_GS_BASE, cpu_kernelmode_gs_base(cpu)); | |
491 | #endif | |
492 | - load_stack_canary_segment(); | |
493 | } | |
494 | ||
495 | #ifdef CONFIG_X86_32 | |
496 | @@ -1940,7 +1938,8 @@ DEFINE_PER_CPU(unsigned long, cpu_current_top_of_stack) = | |
497 | EXPORT_PER_CPU_SYMBOL(cpu_current_top_of_stack); | |
498 | ||
499 | #ifdef CONFIG_STACKPROTECTOR | |
500 | -DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary); | |
501 | +DEFINE_PER_CPU(unsigned long, __stack_chk_guard); | |
502 | +EXPORT_PER_CPU_SYMBOL(__stack_chk_guard); | |
503 | #endif | |
504 | ||
505 | #endif /* CONFIG_X86_64 */ | |
506 | diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c | |
507 | index 759d392cbe9f0..d1d49e3d536b8 100644 | |
508 | --- a/arch/x86/kernel/doublefault_32.c | |
509 | +++ b/arch/x86/kernel/doublefault_32.c | |
510 | @@ -100,9 +100,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct doublefault_stack, doublefault_stack) = { | |
511 | .ss = __KERNEL_DS, | |
512 | .ds = __USER_DS, | |
513 | .fs = __KERNEL_PERCPU, | |
514 | -#ifndef CONFIG_X86_32_LAZY_GS | |
515 | - .gs = __KERNEL_STACK_CANARY, | |
516 | -#endif | |
517 | + .gs = 0, | |
518 | ||
519 | .__cr3 = __pa_nodebug(swapper_pg_dir), | |
520 | }, | |
521 | diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S | |
522 | index 3f1691b89231f..0359333f6bdee 100644 | |
523 | --- a/arch/x86/kernel/head_32.S | |
524 | +++ b/arch/x86/kernel/head_32.S | |
525 | @@ -319,8 +319,8 @@ SYM_FUNC_START(startup_32_smp) | |
526 | movl $(__KERNEL_PERCPU), %eax | |
527 | movl %eax,%fs # set this cpu's percpu | |
528 | ||
529 | - movl $(__KERNEL_STACK_CANARY),%eax | |
530 | - movl %eax,%gs | |
531 | + xorl %eax,%eax | |
532 | + movl %eax,%gs # clear possible garbage in %gs | |
533 | ||
534 | xorl %eax,%eax # Clear LDT | |
535 | lldt %ax | |
536 | @@ -340,20 +340,6 @@ SYM_FUNC_END(startup_32_smp) | |
537 | */ | |
538 | __INIT | |
539 | setup_once: | |
540 | -#ifdef CONFIG_STACKPROTECTOR | |
541 | - /* | |
542 | - * Configure the stack canary. The linker can't handle this by | |
543 | - * relocation. Manually set base address in stack canary | |
544 | - * segment descriptor. | |
545 | - */ | |
546 | - movl $gdt_page,%eax | |
547 | - movl $stack_canary,%ecx | |
548 | - movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax) | |
549 | - shrl $16, %ecx | |
550 | - movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax) | |
551 | - movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax) | |
552 | -#endif | |
553 | - | |
554 | andl $0,setup_once_ref /* Once is enough, thanks */ | |
555 | RET | |
556 | ||
557 | diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c | |
558 | index fd945ce78554e..0941d2f44f2a2 100644 | |
559 | --- a/arch/x86/kernel/setup_percpu.c | |
560 | +++ b/arch/x86/kernel/setup_percpu.c | |
561 | @@ -224,7 +224,6 @@ void __init setup_per_cpu_areas(void) | |
562 | per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); | |
563 | per_cpu(cpu_number, cpu) = cpu; | |
564 | setup_percpu_segment(cpu); | |
565 | - setup_stack_canary_segment(cpu); | |
566 | /* | |
567 | * Copy data used in early init routines from the | |
568 | * initial arrays to the per cpu data areas. These | |
569 | diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c | |
570 | index 64a496a0687f6..3c883e0642424 100644 | |
571 | --- a/arch/x86/kernel/tls.c | |
572 | +++ b/arch/x86/kernel/tls.c | |
573 | @@ -164,17 +164,11 @@ int do_set_thread_area(struct task_struct *p, int idx, | |
574 | savesegment(fs, sel); | |
575 | if (sel == modified_sel) | |
576 | loadsegment(fs, sel); | |
577 | - | |
578 | - savesegment(gs, sel); | |
579 | - if (sel == modified_sel) | |
580 | - load_gs_index(sel); | |
581 | #endif | |
582 | ||
583 | -#ifdef CONFIG_X86_32_LAZY_GS | |
584 | savesegment(gs, sel); | |
585 | if (sel == modified_sel) | |
586 | - loadsegment(gs, sel); | |
587 | -#endif | |
588 | + load_gs_index(sel); | |
589 | } else { | |
590 | #ifdef CONFIG_X86_64 | |
591 | if (p->thread.fsindex == modified_sel) | |
592 | diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c | |
593 | index ffc8b7dcf1feb..6ed542e310adc 100644 | |
594 | --- a/arch/x86/lib/insn-eval.c | |
595 | +++ b/arch/x86/lib/insn-eval.c | |
596 | @@ -404,10 +404,6 @@ static short get_segment_selector(struct pt_regs *regs, int seg_reg_idx) | |
597 | case INAT_SEG_REG_FS: | |
598 | return (unsigned short)(regs->fs & 0xffff); | |
599 | case INAT_SEG_REG_GS: | |
600 | - /* | |
601 | - * GS may or may not be in regs as per CONFIG_X86_32_LAZY_GS. | |
602 | - * The macro below takes care of both cases. | |
603 | - */ | |
604 | return get_user_gs(regs); | |
605 | case INAT_SEG_REG_IGNORE: | |
606 | default: | |
607 | diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S | |
608 | index 43b4d864817ec..afbf0bb252da5 100644 | |
609 | --- a/arch/x86/platform/pvh/head.S | |
610 | +++ b/arch/x86/platform/pvh/head.S | |
611 | @@ -45,10 +45,8 @@ | |
612 | ||
613 | #define PVH_GDT_ENTRY_CS 1 | |
614 | #define PVH_GDT_ENTRY_DS 2 | |
615 | -#define PVH_GDT_ENTRY_CANARY 3 | |
616 | #define PVH_CS_SEL (PVH_GDT_ENTRY_CS * 8) | |
617 | #define PVH_DS_SEL (PVH_GDT_ENTRY_DS * 8) | |
618 | -#define PVH_CANARY_SEL (PVH_GDT_ENTRY_CANARY * 8) | |
619 | ||
620 | SYM_CODE_START_LOCAL(pvh_start_xen) | |
621 | cld | |
622 | @@ -109,17 +107,6 @@ SYM_CODE_START_LOCAL(pvh_start_xen) | |
623 | ||
624 | #else /* CONFIG_X86_64 */ | |
625 | ||
626 | - /* Set base address in stack canary descriptor. */ | |
627 | - movl $_pa(gdt_start),%eax | |
628 | - movl $_pa(canary),%ecx | |
629 | - movw %cx, (PVH_GDT_ENTRY_CANARY * 8) + 2(%eax) | |
630 | - shrl $16, %ecx | |
631 | - movb %cl, (PVH_GDT_ENTRY_CANARY * 8) + 4(%eax) | |
632 | - movb %ch, (PVH_GDT_ENTRY_CANARY * 8) + 7(%eax) | |
633 | - | |
634 | - mov $PVH_CANARY_SEL,%eax | |
635 | - mov %eax,%gs | |
636 | - | |
637 | call mk_early_pgtbl_32 | |
638 | ||
639 | mov $_pa(initial_page_table), %eax | |
640 | @@ -163,7 +150,6 @@ SYM_DATA_START_LOCAL(gdt_start) | |
641 | .quad GDT_ENTRY(0xc09a, 0, 0xfffff) /* PVH_CS_SEL */ | |
642 | #endif | |
643 | .quad GDT_ENTRY(0xc092, 0, 0xfffff) /* PVH_DS_SEL */ | |
644 | - .quad GDT_ENTRY(0x4090, 0, 0x18) /* PVH_CANARY_SEL */ | |
645 | SYM_DATA_END_LABEL(gdt_start, SYM_L_LOCAL, gdt_end) | |
646 | ||
647 | .balign 16 | |
648 | diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c | |
649 | index 4e4e76ecd3ecd..84c7b2312ea9e 100644 | |
650 | --- a/arch/x86/power/cpu.c | |
651 | +++ b/arch/x86/power/cpu.c | |
652 | @@ -101,11 +101,8 @@ static void __save_processor_state(struct saved_context *ctxt) | |
653 | /* | |
654 | * segment registers | |
655 | */ | |
656 | -#ifdef CONFIG_X86_32_LAZY_GS | |
657 | savesegment(gs, ctxt->gs); | |
658 | -#endif | |
659 | #ifdef CONFIG_X86_64 | |
660 | - savesegment(gs, ctxt->gs); | |
661 | savesegment(fs, ctxt->fs); | |
662 | savesegment(ds, ctxt->ds); | |
663 | savesegment(es, ctxt->es); | |
664 | @@ -234,7 +231,6 @@ static void notrace __restore_processor_state(struct saved_context *ctxt) | |
665 | wrmsrl(MSR_GS_BASE, ctxt->kernelmode_gs_base); | |
666 | #else | |
667 | loadsegment(fs, __KERNEL_PERCPU); | |
668 | - loadsegment(gs, __KERNEL_STACK_CANARY); | |
669 | #endif | |
670 | ||
671 | /* Restore the TSS, RO GDT, LDT, and usermode-relevant MSRs. */ | |
672 | @@ -257,7 +253,7 @@ static void notrace __restore_processor_state(struct saved_context *ctxt) | |
673 | */ | |
674 | wrmsrl(MSR_FS_BASE, ctxt->fs_base); | |
675 | wrmsrl(MSR_KERNEL_GS_BASE, ctxt->usermode_gs_base); | |
676 | -#elif defined(CONFIG_X86_32_LAZY_GS) | |
677 | +#else | |
678 | loadsegment(gs, ctxt->gs); | |
679 | #endif | |
680 | ||
681 | diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c | |
682 | index 815030b7f6fa8..94804670caab8 100644 | |
683 | --- a/arch/x86/xen/enlighten_pv.c | |
684 | +++ b/arch/x86/xen/enlighten_pv.c | |
685 | @@ -1193,7 +1193,6 @@ static void __init xen_setup_gdt(int cpu) | |
686 | pv_ops.cpu.write_gdt_entry = xen_write_gdt_entry_boot; | |
687 | pv_ops.cpu.load_gdt = xen_load_gdt_boot; | |
688 | ||
689 | - setup_stack_canary_segment(cpu); | |
690 | switch_to_new_gdt(cpu); | |
691 | ||
692 | pv_ops.cpu.write_gdt_entry = xen_write_gdt_entry; | |
693 | diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh | |
694 | index f5c1194952540..825c75c5b7150 100755 | |
695 | --- a/scripts/gcc-x86_32-has-stack-protector.sh | |
696 | +++ b/scripts/gcc-x86_32-has-stack-protector.sh | |
697 | @@ -1,4 +1,8 @@ | |
698 | #!/bin/sh | |
699 | # SPDX-License-Identifier: GPL-2.0 | |
700 | ||
701 | -echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -m32 -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" | |
702 | +# This requires GCC 8.1 or better. Specifically, we require | |
703 | +# -mstack-protector-guard-reg, added by | |
704 | +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81708 | |
705 | + | |
706 | +echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -m32 -O0 -fstack-protector -mstack-protector-guard-reg=fs -mstack-protector-guard-symbol=__stack_chk_guard - -o - 2> /dev/null | grep -q "%fs" | |
707 | -- | |
708 | 2.43.0 | |
709 |