| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- From 01e4ee94acbd960e302c23481529a5f5323d9969 Mon Sep 17 00:00:00 2001
- From: Andy Lutomirski <[email protected]>
- Date: Mon, 4 Dec 2017 15:07:17 +0100
- Subject: [PATCH 147/242] x86/entry: Fix assumptions that the HW TSS is at the
- beginning of cpu_tss
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- CVE-2017-5754
- A future patch will move SYSENTER_stack to the beginning of cpu_tss
- to help detect overflow. Before this can happen, fix several code
- paths that hardcode assumptions about the old layout.
- Signed-off-by: Andy Lutomirski <[email protected]>
- Signed-off-by: Thomas Gleixner <[email protected]>
- Reviewed-by: Borislav Petkov <[email protected]>
- Reviewed-by: Dave Hansen <[email protected]>
- Reviewed-by: Thomas Gleixner <[email protected]>
- Cc: Boris Ostrovsky <[email protected]>
- Cc: Borislav Petkov <[email protected]>
- Cc: Borislav Petkov <[email protected]>
- Cc: Brian Gerst <[email protected]>
- Cc: Dave Hansen <[email protected]>
- Cc: David Laight <[email protected]>
- Cc: Denys Vlasenko <[email protected]>
- Cc: Eduardo Valentin <[email protected]>
- Cc: Greg KH <[email protected]>
- Cc: H. Peter Anvin <[email protected]>
- Cc: Josh Poimboeuf <[email protected]>
- Cc: Juergen Gross <[email protected]>
- Cc: Linus Torvalds <[email protected]>
- Cc: Peter Zijlstra <[email protected]>
- Cc: Rik van Riel <[email protected]>
- Cc: Will Deacon <[email protected]>
- Cc: [email protected]
- Cc: [email protected]
- Cc: [email protected]
- Cc: [email protected]
- Link: https://lkml.kernel.org/r/[email protected]
- Signed-off-by: Ingo Molnar <[email protected]>
- (backported from commit 7fb983b4dd569e08564134a850dfd4eb1c63d9b8)
- Signed-off-by: Andy Whitcroft <[email protected]>
- Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
- (cherry picked from commit 7123a5de72dc59dea18ce8886e7db726f7259caf)
- Signed-off-by: Fabian Grünbichler <[email protected]>
- ---
- arch/x86/include/asm/desc.h | 2 +-
- arch/x86/include/asm/processor.h | 9 +++++++--
- arch/x86/kernel/cpu/common.c | 8 ++++----
- arch/x86/kernel/doublefault.c | 36 +++++++++++++++++-------------------
- arch/x86/kvm/vmx.c | 2 +-
- arch/x86/power/cpu.c | 13 +++++++------
- 6 files changed, 37 insertions(+), 33 deletions(-)
- diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
- index 81c9b1e8cae9..b817fe247506 100644
- --- a/arch/x86/include/asm/desc.h
- +++ b/arch/x86/include/asm/desc.h
- @@ -190,7 +190,7 @@ static inline void set_tssldt_descriptor(void *d, unsigned long addr,
- #endif
- }
-
- -static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
- +static inline void __set_tss_desc(unsigned cpu, unsigned int entry, struct x86_hw_tss *addr)
- {
- struct desc_struct *d = get_cpu_gdt_rw(cpu);
- tss_desc tss;
- diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
- index 5225917f9760..78123abdb046 100644
- --- a/arch/x86/include/asm/processor.h
- +++ b/arch/x86/include/asm/processor.h
- @@ -161,7 +161,7 @@ extern struct cpuinfo_x86 new_cpu_data;
-
- #include <linux/thread_info.h>
-
- -extern struct tss_struct doublefault_tss;
- +extern struct x86_hw_tss doublefault_tss;
- extern __u32 cpu_caps_cleared[NCAPINTS];
- extern __u32 cpu_caps_set[NCAPINTS];
-
- @@ -246,6 +246,11 @@ static inline void load_cr3(pgd_t *pgdir)
- write_cr3(__pa(pgdir));
- }
-
- +/*
- + * Note that while the legacy 'TSS' name comes from 'Task State Segment',
- + * on modern x86 CPUs the TSS also holds information important to 64-bit mode,
- + * unrelated to the task-switch mechanism:
- + */
- #ifdef CONFIG_X86_32
- /* This is the TSS defined by the hardware. */
- struct x86_hw_tss {
- @@ -316,7 +321,7 @@ struct x86_hw_tss {
- #define IO_BITMAP_BITS 65536
- #define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
- #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
- -#define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap)
- +#define IO_BITMAP_OFFSET (offsetof(struct tss_struct, io_bitmap) - offsetof(struct tss_struct, x86_tss))
- #define INVALID_IO_BITMAP_OFFSET 0x8000
-
- struct tss_struct {
- diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
- index ffee73ec1af1..e526d82b546c 100644
- --- a/arch/x86/kernel/cpu/common.c
- +++ b/arch/x86/kernel/cpu/common.c
- @@ -1558,7 +1558,7 @@ void cpu_init(void)
- }
- }
-
- - t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
- + t->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
-
- /*
- * <= is required because the CPU will access up to
- @@ -1576,7 +1576,7 @@ void cpu_init(void)
- * Initialize the TSS. Don't bother initializing sp0, as the initial
- * task never enters user mode.
- */
- - set_tss_desc(cpu, t);
- + set_tss_desc(cpu, &t->x86_tss);
- load_TR_desc();
-
- load_mm_ldt(&init_mm);
- @@ -1633,12 +1633,12 @@ void cpu_init(void)
- * Initialize the TSS. Don't bother initializing sp0, as the initial
- * task never enters user mode.
- */
- - set_tss_desc(cpu, t);
- + set_tss_desc(cpu, &t->x86_tss);
- load_TR_desc();
-
- load_mm_ldt(&init_mm);
-
- - t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
- + t->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
-
- #ifdef CONFIG_DOUBLEFAULT
- /* Set up doublefault TSS pointer in the GDT */
- diff --git a/arch/x86/kernel/doublefault.c b/arch/x86/kernel/doublefault.c
- index f9c324e08d85..a9fe79d49d39 100644
- --- a/arch/x86/kernel/doublefault.c
- +++ b/arch/x86/kernel/doublefault.c
- @@ -49,25 +49,23 @@ static void doublefault_fn(void)
- cpu_relax();
- }
-
- -struct tss_struct doublefault_tss __cacheline_aligned = {
- - .x86_tss = {
- - .sp0 = STACK_START,
- - .ss0 = __KERNEL_DS,
- - .ldt = 0,
- - .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
- -
- - .ip = (unsigned long) doublefault_fn,
- - /* 0x2 bit is always set */
- - .flags = X86_EFLAGS_SF | 0x2,
- - .sp = STACK_START,
- - .es = __USER_DS,
- - .cs = __KERNEL_CS,
- - .ss = __KERNEL_DS,
- - .ds = __USER_DS,
- - .fs = __KERNEL_PERCPU,
- -
- - .__cr3 = __pa_nodebug(swapper_pg_dir),
- - }
- +struct x86_hw_tss doublefault_tss __cacheline_aligned = {
- + .sp0 = STACK_START,
- + .ss0 = __KERNEL_DS,
- + .ldt = 0,
- + .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
- +
- + .ip = (unsigned long) doublefault_fn,
- + /* 0x2 bit is always set */
- + .flags = X86_EFLAGS_SF | 0x2,
- + .sp = STACK_START,
- + .es = __USER_DS,
- + .cs = __KERNEL_CS,
- + .ss = __KERNEL_DS,
- + .ds = __USER_DS,
- + .fs = __KERNEL_PERCPU,
- +
- + .__cr3 = __pa_nodebug(swapper_pg_dir),
- };
-
- /* dummy for do_double_fault() call */
- diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
- index dd4996a96c71..a7c5a47beab7 100644
- --- a/arch/x86/kvm/vmx.c
- +++ b/arch/x86/kvm/vmx.c
- @@ -2280,7 +2280,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
- * processors. See 22.2.4.
- */
- vmcs_writel(HOST_TR_BASE,
- - (unsigned long)this_cpu_ptr(&cpu_tss));
- + (unsigned long)this_cpu_ptr(&cpu_tss.x86_tss));
- vmcs_writel(HOST_GDTR_BASE, (unsigned long)gdt); /* 22.2.4 */
-
- /*
- diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
- index 78459a6d455a..48cd87fc7222 100644
- --- a/arch/x86/power/cpu.c
- +++ b/arch/x86/power/cpu.c
- @@ -165,12 +165,13 @@ static void fix_processor_context(void)
- struct desc_struct *desc = get_cpu_gdt_rw(cpu);
- tss_desc tss;
- #endif
- - set_tss_desc(cpu, t); /*
- - * This just modifies memory; should not be
- - * necessary. But... This is necessary, because
- - * 386 hardware has concept of busy TSS or some
- - * similar stupidity.
- - */
- +
- + /*
- + * This just modifies memory; should not be necessary. But... This is
- + * necessary, because 386 hardware has concept of busy TSS or some
- + * similar stupidity.
- + */
- + set_tss_desc(cpu, &t->x86_tss);
-
- #ifdef CONFIG_X86_64
- memcpy(&tss, &desc[GDT_ENTRY_TSS], sizeof(tss_desc));
- --
- 2.14.2
|