x86/stackprotector/32: Make the canary into a regular percpu variable
authorAndy Lutomirski <luto@kernel.org>
Sat, 13 Feb 2021 19:19:44 +0000 (11:19 -0800)
committerBorislav Petkov <bp@suse.de>
Mon, 8 Mar 2021 12:19:05 +0000 (13:19 +0100)
On 32-bit kernels, the stackprotector canary is quite nasty -- it is
stored at %gs:(20), which is nasty because 32-bit kernels use %fs for
percpu storage.  It's even nastier because it means that whether %gs
contains userspace state or kernel state while running kernel code
depends on whether stackprotector is enabled (this is
CONFIG_X86_32_LAZY_GS), and this setting radically changes the way
that segment selectors work.  Supporting both variants is a
maintenance and testing mess.

Merely rearranging so that percpu and the stack canary
share the same segment would be messy as the 32-bit percpu address
layout isn't currently compatible with putting a variable at a fixed
offset.

Fortunately, GCC 8.1 added options that allow the stack canary to be
accessed as %fs:__stack_chk_guard, effectively turning it into an ordinary
percpu variable.  This lets us get rid of all of the code to manage the
stack canary GDT descriptor and the CONFIG_X86_32_LAZY_GS mess.

(That name is special.  We could use any symbol we want for the
 %fs-relative mode, but for CONFIG_SMP=n, gcc refuses to let us use any
 name other than __stack_chk_guard.)

Forcibly disable stackprotector on older compilers that don't support
the new options and turn the stack canary into a percpu variable. The
"lazy GS" approach is now used for all 32-bit configurations.

Also makes load_gs_index() work on 32-bit kernels. On 64-bit kernels,
it loads the GS selector and updates the user GSBASE accordingly. (This
is unchanged.) On 32-bit kernels, it loads the GS selector and updates
GSBASE, which is now always the user base. This means that the overall
effect is the same on 32-bit and 64-bit, which avoids some ifdeffery.

 [ bp: Massage commit message. ]

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/c0ff7dba14041c7e5d1cae5d4df052f03759bef3.1613243844.git.luto@kernel.org
19 files changed:
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/entry/entry_32.S
arch/x86/include/asm/processor.h
arch/x86/include/asm/ptrace.h
arch/x86/include/asm/segment.h
arch/x86/include/asm/stackprotector.h
arch/x86/include/asm/suspend_32.h
arch/x86/kernel/asm-offsets_32.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/doublefault_32.c
arch/x86/kernel/head_32.S
arch/x86/kernel/setup_percpu.c
arch/x86/kernel/tls.c
arch/x86/lib/insn-eval.c
arch/x86/platform/pvh/head.S
arch/x86/power/cpu.c
arch/x86/xen/enlighten_pv.c
scripts/gcc-x86_32-has-stack-protector.sh

index 2792879d398ee41fa0d4858815b33e18664297ae..10cc6199bf674bceb8ccdd5ab8492536bf2c24bb 100644 (file)
@@ -360,10 +360,6 @@ config X86_64_SMP
        def_bool y
        depends on X86_64 && SMP
 
-config X86_32_LAZY_GS
-       def_bool y
-       depends on X86_32 && !STACKPROTECTOR
-
 config ARCH_SUPPORTS_UPROBES
        def_bool y
 
@@ -386,7 +382,8 @@ config CC_HAS_SANE_STACKPROTECTOR
        default $(success,$(srctree)/scripts/gcc-x86_32-has-stack-protector.sh $(CC))
        help
           We have to make sure stack protector is unconditionally disabled if
-          the compiler produces broken code.
+          the compiler produces broken code or if it does not let us control
+          the segment on 32-bit kernels.
 
 menu "Processor type and features"
 
index 2d6d5a28c3bf791b586d50b8bcb18039c0b62ffc..952f534ad7b7a9061ba513738862c656ab6e3953 100644 (file)
@@ -79,6 +79,14 @@ ifeq ($(CONFIG_X86_32),y)
 
         # temporary until string.h is fixed
         KBUILD_CFLAGS += -ffreestanding
+
+       ifeq ($(CONFIG_STACKPROTECTOR),y)
+               ifeq ($(CONFIG_SMP),y)
+                       KBUILD_CFLAGS += -mstack-protector-guard-reg=fs -mstack-protector-guard-symbol=__stack_chk_guard
+               else
+                       KBUILD_CFLAGS += -mstack-protector-guard=global
+               endif
+       endif
 else
         BITS := 64
         UTS_MACHINE := x86_64
index df8c017e616119850d7df71a72a7021bdf715241..eb0cb662bca5dfef8bac81afb3ce8c114e0ed759 100644 (file)
@@ -20,7 +20,7 @@
  *     1C(%esp) - %ds
  *     20(%esp) - %es
  *     24(%esp) - %fs
- *     28(%esp) - %gs          saved iff !CONFIG_X86_32_LAZY_GS
+ *     28(%esp) - unused -- was %gs on old stackprotector kernels
  *     2C(%esp) - orig_eax
  *     30(%esp) - %eip
  *     34(%esp) - %cs
 /*
  * User gs save/restore
  *
- * %gs is used for userland TLS and kernel only uses it for stack
- * canary which is required to be at %gs:20 by gcc.  Read the comment
- * at the top of stackprotector.h for more info.
- *
- * Local labels 98 and 99 are used.
+ * This is leftover junk from CONFIG_X86_32_LAZY_GS.  A subsequent patch
+ * will remove it entirely.
  */
-#ifdef CONFIG_X86_32_LAZY_GS
-
  /* unfortunately push/pop can't be no-op */
 .macro PUSH_GS
        pushl   $0
 .macro SET_KERNEL_GS reg
 .endm
 
-#else  /* CONFIG_X86_32_LAZY_GS */
-
-.macro PUSH_GS
-       pushl   %gs
-.endm
-
-.macro POP_GS pop=0
-98:    popl    %gs
-  .if \pop <> 0
-       add     $\pop, %esp
-  .endif
-.endm
-.macro POP_GS_EX
-.pushsection .fixup, "ax"
-99:    movl    $0, (%esp)
-       jmp     98b
-.popsection
-       _ASM_EXTABLE(98b, 99b)
-.endm
-
-.macro PTGS_TO_GS
-98:    mov     PT_GS(%esp), %gs
-.endm
-.macro PTGS_TO_GS_EX
-.pushsection .fixup, "ax"
-99:    movl    $0, PT_GS(%esp)
-       jmp     98b
-.popsection
-       _ASM_EXTABLE(98b, 99b)
-.endm
-
-.macro GS_TO_REG reg
-       movl    %gs, \reg
-.endm
-.macro REG_TO_PTGS reg
-       movl    \reg, PT_GS(%esp)
-.endm
-.macro SET_KERNEL_GS reg
-       movl    $(__KERNEL_STACK_CANARY), \reg
-       movl    \reg, %gs
-.endm
-
-#endif /* CONFIG_X86_32_LAZY_GS */
 
 /* Unconditionally switch to user cr3 */
 .macro SWITCH_TO_USER_CR3 scratch_reg:req
@@ -779,7 +731,7 @@ SYM_CODE_START(__switch_to_asm)
 
 #ifdef CONFIG_STACKPROTECTOR
        movl    TASK_stack_canary(%edx), %ebx
-       movl    %ebx, PER_CPU_VAR(stack_canary)+stack_canary_offset
+       movl    %ebx, PER_CPU_VAR(__stack_chk_guard)
 #endif
 
 #ifdef CONFIG_RETPOLINE
index dc6d149bf851fa911c7c7915fbe68e39f1016b4c..bac2a42796c41a793c7fe276a8d49f8490049afd 100644 (file)
@@ -439,6 +439,9 @@ struct fixed_percpu_data {
         * GCC hardcodes the stack canary as %gs:40.  Since the
         * irq_stack is the object at %gs:0, we reserve the bottom
         * 48 bytes of the irq stack for the canary.
+        *
+        * Once we are willing to require -mstack-protector-guard-symbol=
+        * support for x86_64 stackprotector, we can get rid of this.
         */
        char            gs_base[40];
        unsigned long   stack_canary;
@@ -460,17 +463,7 @@ extern asmlinkage void ignore_sysret(void);
 void current_save_fsgs(void);
 #else  /* X86_64 */
 #ifdef CONFIG_STACKPROTECTOR
-/*
- * Make sure stack canary segment base is cached-aligned:
- *   "For Intel Atom processors, avoid non zero segment base address
- *    that is not aligned to cache line boundary at all cost."
- * (Optim Ref Manual Assembly/Compiler Coding Rule 15.)
- */
-struct stack_canary {
-       char __pad[20];         /* canary at %gs:20 */
-       unsigned long canary;
-};
-DECLARE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
+DECLARE_PER_CPU(unsigned long, __stack_chk_guard);
 #endif
 DECLARE_PER_CPU(struct irq_stack *, hardirq_stack_ptr);
 DECLARE_PER_CPU(struct irq_stack *, softirq_stack_ptr);
index d8324a23669610e379078543e3cbed3855aaae3e..b2c4c12d237c639a22452e97a6a2d1c19952ba9c 100644 (file)
@@ -37,7 +37,10 @@ struct pt_regs {
        unsigned short __esh;
        unsigned short fs;
        unsigned short __fsh;
-       /* On interrupt, gs and __gsh store the vector number. */
+       /*
+        * On interrupt, gs and __gsh store the vector number.  They never
+        * store gs any more.
+        */
        unsigned short gs;
        unsigned short __gsh;
        /* On interrupt, this is the error code. */
index 7fdd4facfce714193146518f14655a20523adb08..72044026eb3c2c182a8edc094b333a624c9228d0 100644 (file)
@@ -95,7 +95,7 @@
  *
  *  26 - ESPFIX small SS
  *  27 - per-cpu                       [ offset to per-cpu data area ]
- *  28 - stack_canary-20               [ for stack protector ]         <=== cacheline #8
+ *  28 - unused
  *  29 - unused
  *  30 - unused
  *  31 - TSS for double fault handler
 
 #define GDT_ENTRY_ESPFIX_SS            26
 #define GDT_ENTRY_PERCPU               27
-#define GDT_ENTRY_STACK_CANARY         28
 
 #define GDT_ENTRY_DOUBLEFAULT_TSS      31
 
 # define __KERNEL_PERCPU               0
 #endif
 
-#ifdef CONFIG_STACKPROTECTOR
-# define __KERNEL_STACK_CANARY         (GDT_ENTRY_STACK_CANARY*8)
-#else
-# define __KERNEL_STACK_CANARY         0
-#endif
-
 #else /* 64-bit: */
 
 #include <asm/cache.h>
@@ -364,22 +357,15 @@ static inline void __loadsegment_fs(unsigned short value)
        asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
 
 /*
- * x86-32 user GS accessors:
+ * x86-32 user GS accessors.  This is ugly and could do with some cleaning up.
  */
 #ifdef CONFIG_X86_32
-# ifdef CONFIG_X86_32_LAZY_GS
-#  define get_user_gs(regs)            (u16)({ unsigned long v; savesegment(gs, v); v; })
-#  define set_user_gs(regs, v)         loadsegment(gs, (unsigned long)(v))
-#  define task_user_gs(tsk)            ((tsk)->thread.gs)
-#  define lazy_save_gs(v)              savesegment(gs, (v))
-#  define lazy_load_gs(v)              loadsegment(gs, (v))
-# else /* X86_32_LAZY_GS */
-#  define get_user_gs(regs)            (u16)((regs)->gs)
-#  define set_user_gs(regs, v)         do { (regs)->gs = (v); } while (0)
-#  define task_user_gs(tsk)            (task_pt_regs(tsk)->gs)
-#  define lazy_save_gs(v)              do { } while (0)
-#  define lazy_load_gs(v)              do { } while (0)
-# endif        /* X86_32_LAZY_GS */
+# define get_user_gs(regs)             (u16)({ unsigned long v; savesegment(gs, v); v; })
+# define set_user_gs(regs, v)          loadsegment(gs, (unsigned long)(v))
+# define task_user_gs(tsk)             ((tsk)->thread.gs)
+# define lazy_save_gs(v)               savesegment(gs, (v))
+# define lazy_load_gs(v)               loadsegment(gs, (v))
+# define load_gs_index(v)              loadsegment(gs, (v))
 #endif /* X86_32 */
 
 #endif /* !__ASSEMBLY__ */
index 7fb482f0f25b062c073294ef72fd6936bf36c41c..b6ffe58c70fab8bc5ff27098d9a77f25f2a89999 100644 (file)
@@ -5,30 +5,23 @@
  * Stack protector works by putting predefined pattern at the start of
  * the stack frame and verifying that it hasn't been overwritten when
  * returning from the function.  The pattern is called stack canary
- * and unfortunately gcc requires it to be at a fixed offset from %gs.
- * On x86_64, the offset is 40 bytes and on x86_32 20 bytes.  x86_64
- * and x86_32 use segment registers differently and thus handles this
- * requirement differently.
+ * and unfortunately gcc historically required it to be at a fixed offset
+ * from the percpu segment base.  On x86_64, the offset is 40 bytes.
  *
- * On x86_64, %gs is shared by percpu area and stack canary.  All
- * percpu symbols are zero based and %gs points to the base of percpu
- * area.  The first occupant of the percpu area is always
- * fixed_percpu_data which contains stack_canary at offset 40.  Userland
- * %gs is always saved and restored on kernel entry and exit using
- * swapgs, so stack protector doesn't add any complexity there.
+ * The same segment is shared by percpu area and stack canary.  On
+ * x86_64, percpu symbols are zero based and %gs (64-bit) points to the
+ * base of percpu area.  The first occupant of the percpu area is always
+ * fixed_percpu_data which contains stack_canary at the approproate
+ * offset.  On x86_32, the stack canary is just a regular percpu
+ * variable.
  *
- * On x86_32, it's slightly more complicated.  As in x86_64, %gs is
- * used for userland TLS.  Unfortunately, some processors are much
- * slower at loading segment registers with different value when
- * entering and leaving the kernel, so the kernel uses %fs for percpu
- * area and manages %gs lazily so that %gs is switched only when
- * necessary, usually during task switch.
+ * Putting percpu data in %fs on 32-bit is a minor optimization compared to
+ * using %gs.  Since 32-bit userspace normally has %fs == 0, we are likely
+ * to load 0 into %fs on exit to usermode, whereas with percpu data in
+ * %gs, we are likely to load a non-null %gs on return to user mode.
  *
- * As gcc requires the stack canary at %gs:20, %gs can't be managed
- * lazily if stack protector is enabled, so the kernel saves and
- * restores userland %gs on kernel entry and exit.  This behavior is
- * controlled by CONFIG_X86_32_LAZY_GS and accessors are defined in
- * system.h to hide the details.
+ * Once we are willing to require GCC 8.1 or better for 64-bit stackprotector
+ * support, we can remove some of this complexity.
  */
 
 #ifndef _ASM_STACKPROTECTOR_H
 #include <linux/random.h>
 #include <linux/sched.h>
 
-/*
- * 24 byte read-only segment initializer for stack canary.  Linker
- * can't handle the address bit shifting.  Address will be set in
- * head_32 for boot CPU and setup_per_cpu_areas() for others.
- */
-#define GDT_STACK_CANARY_INIT                                          \
-       [GDT_ENTRY_STACK_CANARY] = GDT_ENTRY_INIT(0x4090, 0, 0x18),
-
 /*
  * Initialize the stackprotector canary value.
  *
@@ -86,7 +71,7 @@ static __always_inline void boot_init_stack_canary(void)
 #ifdef CONFIG_X86_64
        this_cpu_write(fixed_percpu_data.stack_canary, canary);
 #else
-       this_cpu_write(stack_canary.canary, canary);
+       this_cpu_write(__stack_chk_guard, canary);
 #endif
 }
 
@@ -95,48 +80,16 @@ static inline void cpu_init_stack_canary(int cpu, struct task_struct *idle)
 #ifdef CONFIG_X86_64
        per_cpu(fixed_percpu_data.stack_canary, cpu) = idle->stack_canary;
 #else
-       per_cpu(stack_canary.canary, cpu) = idle->stack_canary;
-#endif
-}
-
-static inline void setup_stack_canary_segment(int cpu)
-{
-#ifdef CONFIG_X86_32
-       unsigned long canary = (unsigned long)&per_cpu(stack_canary, cpu);
-       struct desc_struct *gdt_table = get_cpu_gdt_rw(cpu);
-       struct desc_struct desc;
-
-       desc = gdt_table[GDT_ENTRY_STACK_CANARY];
-       set_desc_base(&desc, canary);
-       write_gdt_entry(gdt_table, GDT_ENTRY_STACK_CANARY, &desc, DESCTYPE_S);
-#endif
-}
-
-static inline void load_stack_canary_segment(void)
-{
-#ifdef CONFIG_X86_32
-       asm("mov %0, %%gs" : : "r" (__KERNEL_STACK_CANARY) : "memory");
+       per_cpu(__stack_chk_guard, cpu) = idle->stack_canary;
 #endif
 }
 
 #else  /* STACKPROTECTOR */
 
-#define GDT_STACK_CANARY_INIT
-
 /* dummy boot_init_stack_canary() is defined in linux/stackprotector.h */
 
-static inline void setup_stack_canary_segment(int cpu)
-{ }
-
 static inline void cpu_init_stack_canary(int cpu, struct task_struct *idle)
 { }
 
-static inline void load_stack_canary_segment(void)
-{
-#ifdef CONFIG_X86_32
-       asm volatile ("mov %0, %%gs" : : "r" (0));
-#endif
-}
-
 #endif /* STACKPROTECTOR */
 #endif /* _ASM_STACKPROTECTOR_H */
index fdbd9d7b7bca13a44e115b5f8cc13f44a03eebc9..7b132d0312ebfa914507a2d365e0bc59ce952d2b 100644 (file)
 /* image of the saved processor state */
 struct saved_context {
        /*
-        * On x86_32, all segment registers, with the possible exception of
-        * gs, are saved at kernel entry in pt_regs.
+        * On x86_32, all segment registers except gs are saved at kernel
+        * entry in pt_regs.
         */
-#ifdef CONFIG_X86_32_LAZY_GS
        u16 gs;
-#endif
        unsigned long cr0, cr2, cr3, cr4;
        u64 misc_enable;
        bool misc_enable_saved;
index 6e043f295a6053a1d24a0dc9bde0abbceca06eef..2b411cd00a4e285a9e5b3ae8f56a7a715ac4269d 100644 (file)
@@ -53,11 +53,6 @@ void foo(void)
               offsetof(struct cpu_entry_area, tss.x86_tss.sp1) -
               offsetofend(struct cpu_entry_area, entry_stack_page.stack));
 
-#ifdef CONFIG_STACKPROTECTOR
-       BLANK();
-       OFFSET(stack_canary_offset, stack_canary, canary);
-#endif
-
        BLANK();
        DEFINE(EFI_svam, offsetof(efi_runtime_services_t, set_virtual_address_map));
 }
index ab640abe26b686a57e89f95dafa6b7a158db1fd9..23cb9d68a56d66f4d0b9d3c005ff1da0d5a5ff3b 100644 (file)
@@ -161,7 +161,6 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
 
        [GDT_ENTRY_ESPFIX_SS]           = GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
        [GDT_ENTRY_PERCPU]              = GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
-       GDT_STACK_CANARY_INIT
 #endif
 } };
 EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
@@ -599,7 +598,6 @@ void load_percpu_segment(int cpu)
        __loadsegment_simple(gs, 0);
        wrmsrl(MSR_GS_BASE, cpu_kernelmode_gs_base(cpu));
 #endif
-       load_stack_canary_segment();
 }
 
 #ifdef CONFIG_X86_32
@@ -1796,7 +1794,8 @@ DEFINE_PER_CPU(unsigned long, cpu_current_top_of_stack) =
 EXPORT_PER_CPU_SYMBOL(cpu_current_top_of_stack);
 
 #ifdef CONFIG_STACKPROTECTOR
-DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
+DEFINE_PER_CPU(unsigned long, __stack_chk_guard);
+EXPORT_PER_CPU_SYMBOL(__stack_chk_guard);
 #endif
 
 #endif /* CONFIG_X86_64 */
index 759d392cbe9f0ea562a202991f344e06846d52e5..d1d49e3d536b84f1c4b7a75f8c7aeb2d365c6121 100644 (file)
@@ -100,9 +100,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct doublefault_stack, doublefault_stack) = {
                .ss             = __KERNEL_DS,
                .ds             = __USER_DS,
                .fs             = __KERNEL_PERCPU,
-#ifndef CONFIG_X86_32_LAZY_GS
-               .gs             = __KERNEL_STACK_CANARY,
-#endif
+               .gs             = 0,
 
                .__cr3          = __pa_nodebug(swapper_pg_dir),
        },
index 7ed84c2822332d9be00c4745ee08d93fc33032fa..67f590425d90b783165b4e79fb2b4acc1b01db1d 100644 (file)
@@ -318,8 +318,8 @@ SYM_FUNC_START(startup_32_smp)
        movl $(__KERNEL_PERCPU), %eax
        movl %eax,%fs                   # set this cpu's percpu
 
-       movl $(__KERNEL_STACK_CANARY),%eax
-       movl %eax,%gs
+       xorl %eax,%eax
+       movl %eax,%gs                   # clear possible garbage in %gs
 
        xorl %eax,%eax                  # Clear LDT
        lldt %ax
@@ -339,20 +339,6 @@ SYM_FUNC_END(startup_32_smp)
  */
 __INIT
 setup_once:
-#ifdef CONFIG_STACKPROTECTOR
-       /*
-        * Configure the stack canary. The linker can't handle this by
-        * relocation.  Manually set base address in stack canary
-        * segment descriptor.
-        */
-       movl $gdt_page,%eax
-       movl $stack_canary,%ecx
-       movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax)
-       shrl $16, %ecx
-       movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax)
-       movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax)
-#endif
-
        andl $0,setup_once_ref  /* Once is enough, thanks */
        ret
 
index fd945ce78554ef741ff23e2c11d42623be01b102..0941d2f44f2a2a4ec31c53a425aab3455df2f3b7 100644 (file)
@@ -224,7 +224,6 @@ void __init setup_per_cpu_areas(void)
                per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu);
                per_cpu(cpu_number, cpu) = cpu;
                setup_percpu_segment(cpu);
-               setup_stack_canary_segment(cpu);
                /*
                 * Copy data used in early init routines from the
                 * initial arrays to the per cpu data areas.  These
index 64a496a0687f60b3ae98fcf4797a786912c08f90..3c883e0642424038e1366e48bc4b6583fa42c06d 100644 (file)
@@ -164,17 +164,11 @@ int do_set_thread_area(struct task_struct *p, int idx,
                savesegment(fs, sel);
                if (sel == modified_sel)
                        loadsegment(fs, sel);
-
-               savesegment(gs, sel);
-               if (sel == modified_sel)
-                       load_gs_index(sel);
 #endif
 
-#ifdef CONFIG_X86_32_LAZY_GS
                savesegment(gs, sel);
                if (sel == modified_sel)
-                       loadsegment(gs, sel);
-#endif
+                       load_gs_index(sel);
        } else {
 #ifdef CONFIG_X86_64
                if (p->thread.fsindex == modified_sel)
index 4229950a5d78c328a38f185119cc85098a36ce66..7f89a091f1fb01a923148f4c1532a266f4a574ae 100644 (file)
@@ -404,10 +404,6 @@ static short get_segment_selector(struct pt_regs *regs, int seg_reg_idx)
        case INAT_SEG_REG_FS:
                return (unsigned short)(regs->fs & 0xffff);
        case INAT_SEG_REG_GS:
-               /*
-                * GS may or may not be in regs as per CONFIG_X86_32_LAZY_GS.
-                * The macro below takes care of both cases.
-                */
                return get_user_gs(regs);
        case INAT_SEG_REG_IGNORE:
        default:
index d2ccadc247e6f9a51abcf09184eafc2c8b59346a..b0490701da2ab596a063304f49a10e76da5b16a1 100644 (file)
 
 #define PVH_GDT_ENTRY_CS       1
 #define PVH_GDT_ENTRY_DS       2
-#define PVH_GDT_ENTRY_CANARY   3
 #define PVH_CS_SEL             (PVH_GDT_ENTRY_CS * 8)
 #define PVH_DS_SEL             (PVH_GDT_ENTRY_DS * 8)
-#define PVH_CANARY_SEL         (PVH_GDT_ENTRY_CANARY * 8)
 
 SYM_CODE_START_LOCAL(pvh_start_xen)
        cld
@@ -111,17 +109,6 @@ SYM_CODE_START_LOCAL(pvh_start_xen)
 
 #else /* CONFIG_X86_64 */
 
-       /* Set base address in stack canary descriptor. */
-       movl $_pa(gdt_start),%eax
-       movl $_pa(canary),%ecx
-       movw %cx, (PVH_GDT_ENTRY_CANARY * 8) + 2(%eax)
-       shrl $16, %ecx
-       movb %cl, (PVH_GDT_ENTRY_CANARY * 8) + 4(%eax)
-       movb %ch, (PVH_GDT_ENTRY_CANARY * 8) + 7(%eax)
-
-       mov $PVH_CANARY_SEL,%eax
-       mov %eax,%gs
-
        call mk_early_pgtbl_32
 
        mov $_pa(initial_page_table), %eax
@@ -165,7 +152,6 @@ SYM_DATA_START_LOCAL(gdt_start)
        .quad GDT_ENTRY(0xc09a, 0, 0xfffff) /* PVH_CS_SEL */
 #endif
        .quad GDT_ENTRY(0xc092, 0, 0xfffff) /* PVH_DS_SEL */
-       .quad GDT_ENTRY(0x4090, 0, 0x18)    /* PVH_CANARY_SEL */
 SYM_DATA_END_LABEL(gdt_start, SYM_L_LOCAL, gdt_end)
 
        .balign 16
index db1378c6ff2621dcf5b5363424b79d63aea67991..ef4329d67a5f89325a24e69769a548285b107ef8 100644 (file)
@@ -99,11 +99,8 @@ static void __save_processor_state(struct saved_context *ctxt)
        /*
         * segment registers
         */
-#ifdef CONFIG_X86_32_LAZY_GS
        savesegment(gs, ctxt->gs);
-#endif
 #ifdef CONFIG_X86_64
-       savesegment(gs, ctxt->gs);
        savesegment(fs, ctxt->fs);
        savesegment(ds, ctxt->ds);
        savesegment(es, ctxt->es);
@@ -232,7 +229,6 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
        wrmsrl(MSR_GS_BASE, ctxt->kernelmode_gs_base);
 #else
        loadsegment(fs, __KERNEL_PERCPU);
-       loadsegment(gs, __KERNEL_STACK_CANARY);
 #endif
 
        /* Restore the TSS, RO GDT, LDT, and usermode-relevant MSRs. */
@@ -255,7 +251,7 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
         */
        wrmsrl(MSR_FS_BASE, ctxt->fs_base);
        wrmsrl(MSR_KERNEL_GS_BASE, ctxt->usermode_gs_base);
-#elif defined(CONFIG_X86_32_LAZY_GS)
+#else
        loadsegment(gs, ctxt->gs);
 #endif
 
index dc0a337f985b66151efd295b1aeb3973086cb1a0..33e797b48f40d4b182583e17958b629c5c145879 100644 (file)
@@ -1204,7 +1204,6 @@ static void __init xen_setup_gdt(int cpu)
        pv_ops.cpu.write_gdt_entry = xen_write_gdt_entry_boot;
        pv_ops.cpu.load_gdt = xen_load_gdt_boot;
 
-       setup_stack_canary_segment(cpu);
        switch_to_new_gdt(cpu);
 
        pv_ops.cpu.write_gdt_entry = xen_write_gdt_entry;
index f5c11949525404f43a22e6efb14a59207898ff9d..825c75c5b715051405905c599ff0e7b9f19a9106 100755 (executable)
@@ -1,4 +1,8 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 
-echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -m32 -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
+# This requires GCC 8.1 or better.  Specifically, we require
+# -mstack-protector-guard-reg, added by
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81708
+
+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"