0145-x86-mm-fixmap-Generalize-the-GDT-fixmap-mechanism-in.patch 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. From 2566b1447443f0dfaf167f43142facebf687c327 Mon Sep 17 00:00:00 2001
  2. From: Andy Lutomirski <[email protected]>
  3. Date: Mon, 4 Dec 2017 15:07:15 +0100
  4. Subject: [PATCH 145/231] x86/mm/fixmap: Generalize the GDT fixmap mechanism,
  5. introduce struct cpu_entry_area
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. CVE-2017-5754
  10. Currently, the GDT is an ad-hoc array of pages, one per CPU, in the
  11. fixmap. Generalize it to be an array of a new 'struct cpu_entry_area'
  12. so that we can cleanly add new things to it.
  13. Signed-off-by: Andy Lutomirski <[email protected]>
  14. Signed-off-by: Thomas Gleixner <[email protected]>
  15. Reviewed-by: Thomas Gleixner <[email protected]>
  16. Reviewed-by: Borislav Petkov <[email protected]>
  17. Cc: Boris Ostrovsky <[email protected]>
  18. Cc: Borislav Petkov <[email protected]>
  19. Cc: Borislav Petkov <[email protected]>
  20. Cc: Brian Gerst <[email protected]>
  21. Cc: Dave Hansen <[email protected]>
  22. Cc: Dave Hansen <[email protected]>
  23. Cc: David Laight <[email protected]>
  24. Cc: Denys Vlasenko <[email protected]>
  25. Cc: Eduardo Valentin <[email protected]>
  26. Cc: Greg KH <[email protected]>
  27. Cc: H. Peter Anvin <[email protected]>
  28. Cc: Josh Poimboeuf <[email protected]>
  29. Cc: Juergen Gross <[email protected]>
  30. Cc: Linus Torvalds <[email protected]>
  31. Cc: Peter Zijlstra <[email protected]>
  32. Cc: Rik van Riel <[email protected]>
  33. Cc: Will Deacon <[email protected]>
  34. Cc: [email protected]
  35. Cc: [email protected]
  36. Cc: [email protected]
  37. Cc: [email protected]
  38. Link: https://lkml.kernel.org/r/[email protected]
  39. Signed-off-by: Ingo Molnar <[email protected]>
  40. (cherry picked from commit ef8813ab280507972bb57e4b1b502811ad4411e9)
  41. Signed-off-by: Andy Whitcroft <[email protected]>
  42. Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
  43. (cherry picked from commit b17894f1ac91491ce29946ed946a129620b7f7ac)
  44. Signed-off-by: Fabian Grünbichler <[email protected]>
  45. ---
  46. arch/x86/include/asm/desc.h | 9 +--------
  47. arch/x86/include/asm/fixmap.h | 37 +++++++++++++++++++++++++++++++++++--
  48. arch/x86/kernel/cpu/common.c | 14 +++++++-------
  49. arch/x86/xen/mmu_pv.c | 2 +-
  50. 4 files changed, 44 insertions(+), 18 deletions(-)
  51. diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
  52. index 22ee0a93b4f7..81c9b1e8cae9 100644
  53. --- a/arch/x86/include/asm/desc.h
  54. +++ b/arch/x86/include/asm/desc.h
  55. @@ -58,17 +58,10 @@ static inline struct desc_struct *get_current_gdt_rw(void)
  56. return this_cpu_ptr(&gdt_page)->gdt;
  57. }
  58. -/* Get the fixmap index for a specific processor */
  59. -static inline unsigned int get_cpu_gdt_ro_index(int cpu)
  60. -{
  61. - return FIX_GDT_REMAP_END - cpu;
  62. -}
  63. -
  64. /* Provide the fixmap address of the remapped GDT */
  65. static inline struct desc_struct *get_cpu_gdt_ro(int cpu)
  66. {
  67. - unsigned int idx = get_cpu_gdt_ro_index(cpu);
  68. - return (struct desc_struct *)__fix_to_virt(idx);
  69. + return (struct desc_struct *)&get_cpu_entry_area(cpu)->gdt;
  70. }
  71. /* Provide the current read-only GDT */
  72. diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
  73. index 81c2b11f50a6..8c6ed66fe957 100644
  74. --- a/arch/x86/include/asm/fixmap.h
  75. +++ b/arch/x86/include/asm/fixmap.h
  76. @@ -44,6 +44,19 @@ extern unsigned long __FIXADDR_TOP;
  77. PAGE_SIZE)
  78. #endif
  79. +/*
  80. + * cpu_entry_area is a percpu region in the fixmap that contains things
  81. + * needed by the CPU and early entry/exit code. Real types aren't used
  82. + * for all fields here to avoid circular header dependencies.
  83. + *
  84. + * Every field is a virtual alias of some other allocated backing store.
  85. + * There is no direct allocation of a struct cpu_entry_area.
  86. + */
  87. +struct cpu_entry_area {
  88. + char gdt[PAGE_SIZE];
  89. +};
  90. +
  91. +#define CPU_ENTRY_AREA_PAGES (sizeof(struct cpu_entry_area) / PAGE_SIZE)
  92. /*
  93. * Here we define all the compile-time 'special' virtual
  94. @@ -101,8 +114,8 @@ enum fixed_addresses {
  95. FIX_LNW_VRTC,
  96. #endif
  97. /* Fixmap entries to remap the GDTs, one per processor. */
  98. - FIX_GDT_REMAP_BEGIN,
  99. - FIX_GDT_REMAP_END = FIX_GDT_REMAP_BEGIN + NR_CPUS - 1,
  100. + FIX_CPU_ENTRY_AREA_TOP,
  101. + FIX_CPU_ENTRY_AREA_BOTTOM = FIX_CPU_ENTRY_AREA_TOP + (CPU_ENTRY_AREA_PAGES * NR_CPUS) - 1,
  102. #ifdef CONFIG_ACPI_APEI_GHES
  103. /* Used for GHES mapping from assorted contexts */
  104. @@ -171,5 +184,25 @@ static inline void __set_fixmap(enum fixed_addresses idx,
  105. void __early_set_fixmap(enum fixed_addresses idx,
  106. phys_addr_t phys, pgprot_t flags);
  107. +static inline unsigned int __get_cpu_entry_area_page_index(int cpu, int page)
  108. +{
  109. + BUILD_BUG_ON(sizeof(struct cpu_entry_area) % PAGE_SIZE != 0);
  110. +
  111. + return FIX_CPU_ENTRY_AREA_BOTTOM - cpu*CPU_ENTRY_AREA_PAGES - page;
  112. +}
  113. +
  114. +#define __get_cpu_entry_area_offset_index(cpu, offset) ({ \
  115. + BUILD_BUG_ON(offset % PAGE_SIZE != 0); \
  116. + __get_cpu_entry_area_page_index(cpu, offset / PAGE_SIZE); \
  117. + })
  118. +
  119. +#define get_cpu_entry_area_index(cpu, field) \
  120. + __get_cpu_entry_area_offset_index((cpu), offsetof(struct cpu_entry_area, field))
  121. +
  122. +static inline struct cpu_entry_area *get_cpu_entry_area(int cpu)
  123. +{
  124. + return (struct cpu_entry_area *)__fix_to_virt(__get_cpu_entry_area_page_index(cpu, 0));
  125. +}
  126. +
  127. #endif /* !__ASSEMBLY__ */
  128. #endif /* _ASM_X86_FIXMAP_H */
  129. diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
  130. index aa97e4cd3a33..ffee73ec1af1 100644
  131. --- a/arch/x86/kernel/cpu/common.c
  132. +++ b/arch/x86/kernel/cpu/common.c
  133. @@ -466,12 +466,12 @@ void load_percpu_segment(int cpu)
  134. load_stack_canary_segment();
  135. }
  136. -/* Setup the fixmap mapping only once per-processor */
  137. -static inline void setup_fixmap_gdt(int cpu)
  138. +/* Setup the fixmap mappings only once per-processor */
  139. +static inline void setup_cpu_entry_area(int cpu)
  140. {
  141. #ifdef CONFIG_X86_64
  142. /* On 64-bit systems, we use a read-only fixmap GDT. */
  143. - pgprot_t prot = PAGE_KERNEL_RO;
  144. + pgprot_t gdt_prot = PAGE_KERNEL_RO;
  145. #else
  146. /*
  147. * On native 32-bit systems, the GDT cannot be read-only because
  148. @@ -482,11 +482,11 @@ static inline void setup_fixmap_gdt(int cpu)
  149. * On Xen PV, the GDT must be read-only because the hypervisor requires
  150. * it.
  151. */
  152. - pgprot_t prot = boot_cpu_has(X86_FEATURE_XENPV) ?
  153. + pgprot_t gdt_prot = boot_cpu_has(X86_FEATURE_XENPV) ?
  154. PAGE_KERNEL_RO : PAGE_KERNEL;
  155. #endif
  156. - __set_fixmap(get_cpu_gdt_ro_index(cpu), get_cpu_gdt_paddr(cpu), prot);
  157. + __set_fixmap(get_cpu_entry_area_index(cpu, gdt), get_cpu_gdt_paddr(cpu), gdt_prot);
  158. }
  159. /* Load the original GDT from the per-cpu structure */
  160. @@ -1589,7 +1589,7 @@ void cpu_init(void)
  161. if (is_uv_system())
  162. uv_cpu_init();
  163. - setup_fixmap_gdt(cpu);
  164. + setup_cpu_entry_area(cpu);
  165. load_fixmap_gdt(cpu);
  166. }
  167. @@ -1650,7 +1650,7 @@ void cpu_init(void)
  168. fpu__init_cpu();
  169. - setup_fixmap_gdt(cpu);
  170. + setup_cpu_entry_area(cpu);
  171. load_fixmap_gdt(cpu);
  172. }
  173. #endif
  174. diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
  175. index 45bb2d462e44..53e65f605bdd 100644
  176. --- a/arch/x86/xen/mmu_pv.c
  177. +++ b/arch/x86/xen/mmu_pv.c
  178. @@ -2297,7 +2297,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
  179. #endif
  180. case FIX_TEXT_POKE0:
  181. case FIX_TEXT_POKE1:
  182. - case FIX_GDT_REMAP_BEGIN ... FIX_GDT_REMAP_END:
  183. + case FIX_CPU_ENTRY_AREA_TOP ... FIX_CPU_ENTRY_AREA_BOTTOM:
  184. /* All local page mappings */
  185. pte = pfn_pte(phys, prot);
  186. break;
  187. --
  188. 2.14.2