0027-x86-idt-Unify-gate_struct-handling-for-32-64-bit-ker.patch 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. From 12f71c3ef98c53a158abec93ef40cd15c9120284 Mon Sep 17 00:00:00 2001
  2. From: Thomas Gleixner <[email protected]>
  3. Date: Mon, 28 Aug 2017 08:47:37 +0200
  4. Subject: [PATCH 027/242] x86/idt: Unify gate_struct handling for 32/64-bit
  5. kernels
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. CVE-2017-5754
  10. The first 32 bits of gate struct are the same for 32 and 64 bit kernels.
  11. The 32-bit version uses desc_struct and no designated data structure,
  12. so we need different accessors for 32 and 64 bit kernels.
  13. Aside of that the macros which are necessary to build the 32-bit
  14. gate descriptor are horrible to read.
  15. Unify the gate structs and switch all code fiddling with it over.
  16. Signed-off-by: Thomas Gleixner <[email protected]>
  17. Cc: Andy Lutomirski <[email protected]>
  18. Cc: Borislav Petkov <[email protected]>
  19. Cc: Brian Gerst <[email protected]>
  20. Cc: Denys Vlasenko <[email protected]>
  21. Cc: H. Peter Anvin <[email protected]>
  22. Cc: Josh Poimboeuf <[email protected]>
  23. Cc: Linus Torvalds <[email protected]>
  24. Cc: Peter Zijlstra <[email protected]>
  25. Cc: Steven Rostedt <[email protected]>
  26. Link: http://lkml.kernel.org/r/[email protected]
  27. Signed-off-by: Ingo Molnar <[email protected]>
  28. (cherry picked from commit 64b163fab684e3de47aa8db6cc08ae7d2e194373)
  29. Signed-off-by: Andy Whitcroft <[email protected]>
  30. Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
  31. (cherry picked from commit 587719b1926757eb7531e0631d63fb93cd60d0d3)
  32. Signed-off-by: Fabian Grünbichler <[email protected]>
  33. ---
  34. arch/x86/include/asm/desc.h | 45 ++++++++++++++-----------------
  35. arch/x86/include/asm/desc_defs.h | 57 ++++++++++++++++++++++++++--------------
  36. arch/x86/kvm/vmx.c | 2 +-
  37. arch/x86/xen/enlighten_pv.c | 12 ++++-----
  38. 4 files changed, 63 insertions(+), 53 deletions(-)
  39. diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
  40. index d0a21b12dd58..57e502a4e92f 100644
  41. --- a/arch/x86/include/asm/desc.h
  42. +++ b/arch/x86/include/asm/desc.h
  43. @@ -83,33 +83,25 @@ static inline phys_addr_t get_cpu_gdt_paddr(unsigned int cpu)
  44. return per_cpu_ptr_to_phys(get_cpu_gdt_rw(cpu));
  45. }
  46. -#ifdef CONFIG_X86_64
  47. -
  48. static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
  49. unsigned dpl, unsigned ist, unsigned seg)
  50. {
  51. - gate->offset_low = PTR_LOW(func);
  52. + gate->offset_low = (u16) func;
  53. + gate->bits.p = 1;
  54. + gate->bits.dpl = dpl;
  55. + gate->bits.zero = 0;
  56. + gate->bits.type = type;
  57. + gate->offset_middle = (u16) (func >> 16);
  58. +#ifdef CONFIG_X86_64
  59. gate->segment = __KERNEL_CS;
  60. - gate->ist = ist;
  61. - gate->p = 1;
  62. - gate->dpl = dpl;
  63. - gate->zero0 = 0;
  64. - gate->zero1 = 0;
  65. - gate->type = type;
  66. - gate->offset_middle = PTR_MIDDLE(func);
  67. - gate->offset_high = PTR_HIGH(func);
  68. -}
  69. -
  70. + gate->bits.ist = ist;
  71. + gate->reserved = 0;
  72. + gate->offset_high = (u32) (func >> 32);
  73. #else
  74. -static inline void pack_gate(gate_desc *gate, unsigned char type,
  75. - unsigned long base, unsigned dpl, unsigned flags,
  76. - unsigned short seg)
  77. -{
  78. - gate->a = (seg << 16) | (base & 0xffff);
  79. - gate->b = (base & 0xffff0000) | (((0x80 | type | (dpl << 5)) & 0xff) << 8);
  80. -}
  81. -
  82. + gate->segment = seg;
  83. + gate->bits.ist = 0;
  84. #endif
  85. +}
  86. static inline int desc_empty(const void *ptr)
  87. {
  88. @@ -185,7 +177,8 @@ static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
  89. }
  90. -static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned type, unsigned size)
  91. +static inline void set_tssldt_descriptor(void *d, unsigned long addr,
  92. + unsigned type, unsigned size)
  93. {
  94. #ifdef CONFIG_X86_64
  95. struct ldttss_desc64 *desc = d;
  96. @@ -193,13 +186,13 @@ static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned t
  97. memset(desc, 0, sizeof(*desc));
  98. desc->limit0 = size & 0xFFFF;
  99. - desc->base0 = PTR_LOW(addr);
  100. - desc->base1 = PTR_MIDDLE(addr) & 0xFF;
  101. + desc->base0 = (u16) addr;
  102. + desc->base1 = (addr >> 16) & 0xFF;
  103. desc->type = type;
  104. desc->p = 1;
  105. desc->limit1 = (size >> 16) & 0xF;
  106. - desc->base2 = (PTR_MIDDLE(addr) >> 8) & 0xFF;
  107. - desc->base3 = PTR_HIGH(addr);
  108. + desc->base2 = (addr >> 24) & 0xFF;
  109. + desc->base3 = (u32) (addr >> 32);
  110. #else
  111. pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
  112. #endif
  113. diff --git a/arch/x86/include/asm/desc_defs.h b/arch/x86/include/asm/desc_defs.h
  114. index 49265345d4d2..d684bee8a59a 100644
  115. --- a/arch/x86/include/asm/desc_defs.h
  116. +++ b/arch/x86/include/asm/desc_defs.h
  117. @@ -47,20 +47,6 @@ enum {
  118. GATE_TASK = 0x5,
  119. };
  120. -/* 16byte gate */
  121. -struct gate_struct64 {
  122. - u16 offset_low;
  123. - u16 segment;
  124. - unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
  125. - u16 offset_middle;
  126. - u32 offset_high;
  127. - u32 zero1;
  128. -} __attribute__((packed));
  129. -
  130. -#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
  131. -#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
  132. -#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)
  133. -
  134. enum {
  135. DESC_TSS = 0x9,
  136. DESC_LDT = 0x2,
  137. @@ -77,20 +63,51 @@ struct ldttss_desc64 {
  138. u32 zero1;
  139. } __attribute__((packed));
  140. +
  141. #ifdef CONFIG_X86_64
  142. -typedef struct gate_struct64 gate_desc;
  143. typedef struct ldttss_desc64 ldt_desc;
  144. typedef struct ldttss_desc64 tss_desc;
  145. -#define gate_offset(g) ((g).offset_low | ((unsigned long)(g).offset_middle << 16) | ((unsigned long)(g).offset_high << 32))
  146. -#define gate_segment(g) ((g).segment)
  147. #else
  148. -typedef struct desc_struct gate_desc;
  149. typedef struct desc_struct ldt_desc;
  150. typedef struct desc_struct tss_desc;
  151. -#define gate_offset(g) (((g).b & 0xffff0000) | ((g).a & 0x0000ffff))
  152. -#define gate_segment(g) ((g).a >> 16)
  153. #endif
  154. +struct idt_bits {
  155. + u16 ist : 3,
  156. + zero : 5,
  157. + type : 5,
  158. + dpl : 2,
  159. + p : 1;
  160. +} __attribute__((packed));
  161. +
  162. +struct gate_struct {
  163. + u16 offset_low;
  164. + u16 segment;
  165. + struct idt_bits bits;
  166. + u16 offset_middle;
  167. +#ifdef CONFIG_X86_64
  168. + u32 offset_high;
  169. + u32 reserved;
  170. +#endif
  171. +} __attribute__((packed));
  172. +
  173. +typedef struct gate_struct gate_desc;
  174. +
  175. +static inline unsigned long gate_offset(const gate_desc *g)
  176. +{
  177. +#ifdef CONFIG_X86_64
  178. + return g->offset_low | ((unsigned long)g->offset_middle << 16) |
  179. + ((unsigned long) g->offset_high << 32);
  180. +#else
  181. + return g->offset_low | ((unsigned long)g->offset_middle << 16);
  182. +#endif
  183. +}
  184. +
  185. +static inline unsigned long gate_segment(const gate_desc *g)
  186. +{
  187. + return g->segment;
  188. +}
  189. +
  190. struct desc_ptr {
  191. unsigned short size;
  192. unsigned long address;
  193. diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
  194. index a2c95522ac99..7b447d126d17 100644
  195. --- a/arch/x86/kvm/vmx.c
  196. +++ b/arch/x86/kvm/vmx.c
  197. @@ -8838,7 +8838,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
  198. vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
  199. desc = (gate_desc *)vmx->host_idt_base + vector;
  200. - entry = gate_offset(*desc);
  201. + entry = gate_offset(desc);
  202. asm volatile(
  203. #ifdef CONFIG_X86_64
  204. "mov %%" _ASM_SP ", %[sp]\n\t"
  205. diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
  206. index 6c279c8f0a0e..49ee3315b9f7 100644
  207. --- a/arch/x86/xen/enlighten_pv.c
  208. +++ b/arch/x86/xen/enlighten_pv.c
  209. @@ -591,12 +591,12 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
  210. {
  211. unsigned long addr;
  212. - if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT)
  213. + if (val->bits.type != GATE_TRAP && val->bits.type != GATE_INTERRUPT)
  214. return 0;
  215. info->vector = vector;
  216. - addr = gate_offset(*val);
  217. + addr = gate_offset(val);
  218. #ifdef CONFIG_X86_64
  219. /*
  220. * Look for known traps using IST, and substitute them
  221. @@ -629,16 +629,16 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
  222. ;
  223. else {
  224. /* Some other trap using IST? */
  225. - if (WARN_ON(val->ist != 0))
  226. + if (WARN_ON(val->bits.ist != 0))
  227. return 0;
  228. }
  229. #endif /* CONFIG_X86_64 */
  230. info->address = addr;
  231. - info->cs = gate_segment(*val);
  232. - info->flags = val->dpl;
  233. + info->cs = gate_segment(val);
  234. + info->flags = val->bits.dpl;
  235. /* interrupt gates clear IF */
  236. - if (val->type == GATE_INTERRUPT)
  237. + if (val->bits.type == GATE_INTERRUPT)
  238. info->flags |= 1 << 2;
  239. return 1;
  240. --
  241. 2.14.2