| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- From 12f71c3ef98c53a158abec93ef40cd15c9120284 Mon Sep 17 00:00:00 2001
- From: Thomas Gleixner <[email protected]>
- Date: Mon, 28 Aug 2017 08:47:37 +0200
- Subject: [PATCH 027/242] x86/idt: Unify gate_struct handling for 32/64-bit
- kernels
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- CVE-2017-5754
- The first 32 bits of gate struct are the same for 32 and 64 bit kernels.
- The 32-bit version uses desc_struct and no designated data structure,
- so we need different accessors for 32 and 64 bit kernels.
- Aside of that the macros which are necessary to build the 32-bit
- gate descriptor are horrible to read.
- Unify the gate structs and switch all code fiddling with it over.
- Signed-off-by: Thomas Gleixner <[email protected]>
- Cc: Andy Lutomirski <[email protected]>
- Cc: Borislav Petkov <[email protected]>
- Cc: Brian Gerst <[email protected]>
- Cc: Denys Vlasenko <[email protected]>
- Cc: H. Peter Anvin <[email protected]>
- Cc: Josh Poimboeuf <[email protected]>
- Cc: Linus Torvalds <[email protected]>
- Cc: Peter Zijlstra <[email protected]>
- Cc: Steven Rostedt <[email protected]>
- Link: http://lkml.kernel.org/r/[email protected]
- Signed-off-by: Ingo Molnar <[email protected]>
- (cherry picked from commit 64b163fab684e3de47aa8db6cc08ae7d2e194373)
- Signed-off-by: Andy Whitcroft <[email protected]>
- Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
- (cherry picked from commit 587719b1926757eb7531e0631d63fb93cd60d0d3)
- Signed-off-by: Fabian Grünbichler <[email protected]>
- ---
- arch/x86/include/asm/desc.h | 45 ++++++++++++++-----------------
- arch/x86/include/asm/desc_defs.h | 57 ++++++++++++++++++++++++++--------------
- arch/x86/kvm/vmx.c | 2 +-
- arch/x86/xen/enlighten_pv.c | 12 ++++-----
- 4 files changed, 63 insertions(+), 53 deletions(-)
- diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
- index d0a21b12dd58..57e502a4e92f 100644
- --- a/arch/x86/include/asm/desc.h
- +++ b/arch/x86/include/asm/desc.h
- @@ -83,33 +83,25 @@ static inline phys_addr_t get_cpu_gdt_paddr(unsigned int cpu)
- return per_cpu_ptr_to_phys(get_cpu_gdt_rw(cpu));
- }
-
- -#ifdef CONFIG_X86_64
- -
- static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
- unsigned dpl, unsigned ist, unsigned seg)
- {
- - gate->offset_low = PTR_LOW(func);
- + gate->offset_low = (u16) func;
- + gate->bits.p = 1;
- + gate->bits.dpl = dpl;
- + gate->bits.zero = 0;
- + gate->bits.type = type;
- + gate->offset_middle = (u16) (func >> 16);
- +#ifdef CONFIG_X86_64
- gate->segment = __KERNEL_CS;
- - gate->ist = ist;
- - gate->p = 1;
- - gate->dpl = dpl;
- - gate->zero0 = 0;
- - gate->zero1 = 0;
- - gate->type = type;
- - gate->offset_middle = PTR_MIDDLE(func);
- - gate->offset_high = PTR_HIGH(func);
- -}
- -
- + gate->bits.ist = ist;
- + gate->reserved = 0;
- + gate->offset_high = (u32) (func >> 32);
- #else
- -static inline void pack_gate(gate_desc *gate, unsigned char type,
- - unsigned long base, unsigned dpl, unsigned flags,
- - unsigned short seg)
- -{
- - gate->a = (seg << 16) | (base & 0xffff);
- - gate->b = (base & 0xffff0000) | (((0x80 | type | (dpl << 5)) & 0xff) << 8);
- -}
- -
- + gate->segment = seg;
- + gate->bits.ist = 0;
- #endif
- +}
-
- static inline int desc_empty(const void *ptr)
- {
- @@ -185,7 +177,8 @@ static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
- }
-
-
- -static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned type, unsigned size)
- +static inline void set_tssldt_descriptor(void *d, unsigned long addr,
- + unsigned type, unsigned size)
- {
- #ifdef CONFIG_X86_64
- struct ldttss_desc64 *desc = d;
- @@ -193,13 +186,13 @@ static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned t
- memset(desc, 0, sizeof(*desc));
-
- desc->limit0 = size & 0xFFFF;
- - desc->base0 = PTR_LOW(addr);
- - desc->base1 = PTR_MIDDLE(addr) & 0xFF;
- + desc->base0 = (u16) addr;
- + desc->base1 = (addr >> 16) & 0xFF;
- desc->type = type;
- desc->p = 1;
- desc->limit1 = (size >> 16) & 0xF;
- - desc->base2 = (PTR_MIDDLE(addr) >> 8) & 0xFF;
- - desc->base3 = PTR_HIGH(addr);
- + desc->base2 = (addr >> 24) & 0xFF;
- + desc->base3 = (u32) (addr >> 32);
- #else
- pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
- #endif
- diff --git a/arch/x86/include/asm/desc_defs.h b/arch/x86/include/asm/desc_defs.h
- index 49265345d4d2..d684bee8a59a 100644
- --- a/arch/x86/include/asm/desc_defs.h
- +++ b/arch/x86/include/asm/desc_defs.h
- @@ -47,20 +47,6 @@ enum {
- GATE_TASK = 0x5,
- };
-
- -/* 16byte gate */
- -struct gate_struct64 {
- - u16 offset_low;
- - u16 segment;
- - unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
- - u16 offset_middle;
- - u32 offset_high;
- - u32 zero1;
- -} __attribute__((packed));
- -
- -#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
- -#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
- -#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)
- -
- enum {
- DESC_TSS = 0x9,
- DESC_LDT = 0x2,
- @@ -77,20 +63,51 @@ struct ldttss_desc64 {
- u32 zero1;
- } __attribute__((packed));
-
- +
- #ifdef CONFIG_X86_64
- -typedef struct gate_struct64 gate_desc;
- typedef struct ldttss_desc64 ldt_desc;
- typedef struct ldttss_desc64 tss_desc;
- -#define gate_offset(g) ((g).offset_low | ((unsigned long)(g).offset_middle << 16) | ((unsigned long)(g).offset_high << 32))
- -#define gate_segment(g) ((g).segment)
- #else
- -typedef struct desc_struct gate_desc;
- typedef struct desc_struct ldt_desc;
- typedef struct desc_struct tss_desc;
- -#define gate_offset(g) (((g).b & 0xffff0000) | ((g).a & 0x0000ffff))
- -#define gate_segment(g) ((g).a >> 16)
- #endif
-
- +struct idt_bits {
- + u16 ist : 3,
- + zero : 5,
- + type : 5,
- + dpl : 2,
- + p : 1;
- +} __attribute__((packed));
- +
- +struct gate_struct {
- + u16 offset_low;
- + u16 segment;
- + struct idt_bits bits;
- + u16 offset_middle;
- +#ifdef CONFIG_X86_64
- + u32 offset_high;
- + u32 reserved;
- +#endif
- +} __attribute__((packed));
- +
- +typedef struct gate_struct gate_desc;
- +
- +static inline unsigned long gate_offset(const gate_desc *g)
- +{
- +#ifdef CONFIG_X86_64
- + return g->offset_low | ((unsigned long)g->offset_middle << 16) |
- + ((unsigned long) g->offset_high << 32);
- +#else
- + return g->offset_low | ((unsigned long)g->offset_middle << 16);
- +#endif
- +}
- +
- +static inline unsigned long gate_segment(const gate_desc *g)
- +{
- + return g->segment;
- +}
- +
- struct desc_ptr {
- unsigned short size;
- unsigned long address;
- diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
- index a2c95522ac99..7b447d126d17 100644
- --- a/arch/x86/kvm/vmx.c
- +++ b/arch/x86/kvm/vmx.c
- @@ -8838,7 +8838,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
-
- vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
- desc = (gate_desc *)vmx->host_idt_base + vector;
- - entry = gate_offset(*desc);
- + entry = gate_offset(desc);
- asm volatile(
- #ifdef CONFIG_X86_64
- "mov %%" _ASM_SP ", %[sp]\n\t"
- diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
- index 6c279c8f0a0e..49ee3315b9f7 100644
- --- a/arch/x86/xen/enlighten_pv.c
- +++ b/arch/x86/xen/enlighten_pv.c
- @@ -591,12 +591,12 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
- {
- unsigned long addr;
-
- - if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT)
- + if (val->bits.type != GATE_TRAP && val->bits.type != GATE_INTERRUPT)
- return 0;
-
- info->vector = vector;
-
- - addr = gate_offset(*val);
- + addr = gate_offset(val);
- #ifdef CONFIG_X86_64
- /*
- * Look for known traps using IST, and substitute them
- @@ -629,16 +629,16 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
- ;
- else {
- /* Some other trap using IST? */
- - if (WARN_ON(val->ist != 0))
- + if (WARN_ON(val->bits.ist != 0))
- return 0;
- }
- #endif /* CONFIG_X86_64 */
- info->address = addr;
-
- - info->cs = gate_segment(*val);
- - info->flags = val->dpl;
- + info->cs = gate_segment(val);
- + info->flags = val->bits.dpl;
- /* interrupt gates clear IF */
- - if (val->type == GATE_INTERRUPT)
- + if (val->bits.type == GATE_INTERRUPT)
- info->flags |= 1 << 2;
-
- return 1;
- --
- 2.14.2
|