]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-5.10/x86-stackprotector-32-make-the-canary-into-a-regular.patch
5.10-stable patches
[thirdparty/kernel/stable-queue.git] / queue-5.10 / x86-stackprotector-32-make-the-canary-into-a-regular.patch
CommitLineData
b7ca0ba0
SL
1From b701dea6dc812612ab54e2b524182f1eea7dc78a Mon Sep 17 00:00:00 2001
2From: Sasha Levin <sashal@kernel.org>
3Date: Sat, 13 Feb 2021 11:19:44 -0800
4Subject: x86/stackprotector/32: Make the canary into a regular percpu variable
5
6From: Andy Lutomirski <luto@kernel.org>
7
8[ Upstream commit 3fb0fdb3bbe7aed495109b3296b06c2409734023 ]
9
10On 32-bit kernels, the stackprotector canary is quite nasty -- it is
11stored at %gs:(20), which is nasty because 32-bit kernels use %fs for
12percpu storage. It's even nastier because it means that whether %gs
13contains userspace state or kernel state while running kernel code
14depends on whether stackprotector is enabled (this is
15CONFIG_X86_32_LAZY_GS), and this setting radically changes the way
16that segment selectors work. Supporting both variants is a
17maintenance and testing mess.
18
19Merely rearranging so that percpu and the stack canary
20share the same segment would be messy as the 32-bit percpu address
21layout isn't currently compatible with putting a variable at a fixed
22offset.
23
24Fortunately, GCC 8.1 added options that allow the stack canary to be
25accessed as %fs:__stack_chk_guard, effectively turning it into an ordinary
26percpu variable. This lets us get rid of all of the code to manage the
27stack 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
33Forcibly disable stackprotector on older compilers that don't support
34the 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
37Also makes load_gs_index() work on 32-bit kernels. On 64-bit kernels,
38it loads the GS selector and updates the user GSBASE accordingly. (This
39is unchanged.) On 32-bit kernels, it loads the GS selector and updates
40GSBASE, which is now always the user base. This means that the overall
41effect is the same on 32-bit and 64-bit, which avoids some ifdeffery.
42
43 [ bp: Massage commit message. ]
44
45Signed-off-by: Andy Lutomirski <luto@kernel.org>
46Signed-off-by: Borislav Petkov <bp@suse.de>
47Link: https://lkml.kernel.org/r/c0ff7dba14041c7e5d1cae5d4df052f03759bef3.1613243844.git.luto@kernel.org
48Stable-dep-of: e3f269ed0acc ("x86/pm: Work around false positive kmemleak report in msr_build_context()")
49Signed-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
72diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
73index 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
97diff --git a/arch/x86/Makefile b/arch/x86/Makefile
98index 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
116diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
117index 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 /*
205diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
206index 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);
238diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
239index 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. */
254diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
255index 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__ */
318diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h
319index 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 */
441diff --git a/arch/x86/include/asm/suspend_32.h b/arch/x86/include/asm/suspend_32.h
442index 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;
460diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
461index 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 }
476diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
477index 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 */
506diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c
507index 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 },
521diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
522index 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
557diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
558index 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
569diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
570index 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)
592diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
593index 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:
607diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S
608index 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
648diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
649index 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
681diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
682index 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;
693diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh
694index 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--
7082.43.0
709