+++ /dev/null
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Thomas Gleixner <tglx@linutronix.de>
-Date: Wed, 20 Dec 2017 18:28:54 +0100
-Subject: [PATCH] x86/cpu_entry_area: Move it to a separate unit
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-CVE-2017-5754
-
-Separate the cpu_entry_area code out of cpu/common.c and the fixmap.
-
-Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-Cc: Andy Lutomirski <luto@kernel.org>
-Cc: Borislav Petkov <bp@alien8.de>
-Cc: Dave Hansen <dave.hansen@linux.intel.com>
-Cc: H. Peter Anvin <hpa@zytor.com>
-Cc: Josh Poimboeuf <jpoimboe@redhat.com>
-Cc: Juergen Gross <jgross@suse.com>
-Cc: Linus Torvalds <torvalds@linux-foundation.org>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Signed-off-by: Ingo Molnar <mingo@kernel.org>
-(cherry picked from commit ed1bbc40a0d10e0c5c74fe7bdc6298295cf40255)
-Signed-off-by: Andy Whitcroft <apw@canonical.com>
-Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
-(cherry picked from commit 0fa11d2cd3d67af676aa2762ade282ba6d09cbe5)
-Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
----
- arch/x86/mm/Makefile | 2 +-
- arch/x86/include/asm/cpu_entry_area.h | 52 +++++++++++++++++
- arch/x86/include/asm/fixmap.h | 41 +-------------
- arch/x86/kernel/cpu/common.c | 94 ------------------------------
- arch/x86/kernel/traps.c | 1 +
- arch/x86/mm/cpu_entry_area.c | 104 ++++++++++++++++++++++++++++++++++
- 6 files changed, 159 insertions(+), 135 deletions(-)
- create mode 100644 arch/x86/include/asm/cpu_entry_area.h
- create mode 100644 arch/x86/mm/cpu_entry_area.c
-
-diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
-index 0fbdcb64f9f8..76f5399a8356 100644
---- a/arch/x86/mm/Makefile
-+++ b/arch/x86/mm/Makefile
-@@ -2,7 +2,7 @@
- KCOV_INSTRUMENT_tlb.o := n
-
- obj-y := init.o init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \
-- pat.o pgtable.o physaddr.o setup_nx.o tlb.o
-+ pat.o pgtable.o physaddr.o setup_nx.o tlb.o cpu_entry_area.o
-
- # Make sure __phys_addr has no stackprotector
- nostackp := $(call cc-option, -fno-stack-protector)
-diff --git a/arch/x86/include/asm/cpu_entry_area.h b/arch/x86/include/asm/cpu_entry_area.h
-new file mode 100644
-index 000000000000..5471826803af
---- /dev/null
-+++ b/arch/x86/include/asm/cpu_entry_area.h
-@@ -0,0 +1,52 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+#ifndef _ASM_X86_CPU_ENTRY_AREA_H
-+#define _ASM_X86_CPU_ENTRY_AREA_H
-+
-+#include <linux/percpu-defs.h>
-+#include <asm/processor.h>
-+
-+/*
-+ * cpu_entry_area is a percpu region that contains things needed by the CPU
-+ * and early entry/exit code. Real types aren't used for all fields here
-+ * to avoid circular header dependencies.
-+ *
-+ * Every field is a virtual alias of some other allocated backing store.
-+ * There is no direct allocation of a struct cpu_entry_area.
-+ */
-+struct cpu_entry_area {
-+ char gdt[PAGE_SIZE];
-+
-+ /*
-+ * The GDT is just below entry_stack and thus serves (on x86_64) as
-+ * a a read-only guard page.
-+ */
-+ struct entry_stack_page entry_stack_page;
-+
-+ /*
-+ * On x86_64, the TSS is mapped RO. On x86_32, it's mapped RW because
-+ * we need task switches to work, and task switches write to the TSS.
-+ */
-+ struct tss_struct tss;
-+
-+ char entry_trampoline[PAGE_SIZE];
-+
-+#ifdef CONFIG_X86_64
-+ /*
-+ * Exception stacks used for IST entries.
-+ *
-+ * In the future, this should have a separate slot for each stack
-+ * with guard pages between them.
-+ */
-+ char exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ];
-+#endif
-+};
-+
-+#define CPU_ENTRY_AREA_SIZE (sizeof(struct cpu_entry_area))
-+#define CPU_ENTRY_AREA_PAGES (CPU_ENTRY_AREA_SIZE / PAGE_SIZE)
-+
-+DECLARE_PER_CPU(struct cpu_entry_area *, cpu_entry_area);
-+
-+extern void setup_cpu_entry_areas(void);
-+
-+#endif
-diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
-index a7fb137ad964..1b2521473480 100644
---- a/arch/x86/include/asm/fixmap.h
-+++ b/arch/x86/include/asm/fixmap.h
-@@ -25,6 +25,7 @@
- #else
- #include <uapi/asm/vsyscall.h>
- #endif
-+#include <asm/cpu_entry_area.h>
-
- /*
- * We can't declare FIXADDR_TOP as variable for x86_64 because vsyscall
-@@ -44,46 +45,6 @@ extern unsigned long __FIXADDR_TOP;
- PAGE_SIZE)
- #endif
-
--/*
-- * cpu_entry_area is a percpu region in the fixmap that contains things
-- * needed by the CPU and early entry/exit code. Real types aren't used
-- * for all fields here to avoid circular header dependencies.
-- *
-- * Every field is a virtual alias of some other allocated backing store.
-- * There is no direct allocation of a struct cpu_entry_area.
-- */
--struct cpu_entry_area {
-- char gdt[PAGE_SIZE];
--
-- /*
-- * The GDT is just below entry_stack and thus serves (on x86_64) as
-- * a a read-only guard page.
-- */
-- struct entry_stack_page entry_stack_page;
--
-- /*
-- * On x86_64, the TSS is mapped RO. On x86_32, it's mapped RW because
-- * we need task switches to work, and task switches write to the TSS.
-- */
-- struct tss_struct tss;
--
-- char entry_trampoline[PAGE_SIZE];
--
--#ifdef CONFIG_X86_64
-- /*
-- * Exception stacks used for IST entries.
-- *
-- * In the future, this should have a separate slot for each stack
-- * with guard pages between them.
-- */
-- char exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ];
--#endif
--};
--
--#define CPU_ENTRY_AREA_PAGES (sizeof(struct cpu_entry_area) / PAGE_SIZE)
--
--extern void setup_cpu_entry_areas(void);
--
- /*
- * Here we define all the compile-time 'special' virtual
- * addresses. The point is to have a constant address at
-diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
-index 7a8a5d436566..96171ce46d61 100644
---- a/arch/x86/kernel/cpu/common.c
-+++ b/arch/x86/kernel/cpu/common.c
-@@ -482,102 +482,8 @@ static const unsigned int exception_stack_sizes[N_EXCEPTION_STACKS] = {
- [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STKSZ,
- [DEBUG_STACK - 1] = DEBUG_STKSZ
- };
--
--static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
-- [(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]);
--#endif
--
--static DEFINE_PER_CPU_PAGE_ALIGNED(struct entry_stack_page,
-- entry_stack_storage);
--
--static void __init
--set_percpu_fixmap_pages(int idx, void *ptr, int pages, pgprot_t prot)
--{
-- for ( ; pages; pages--, idx--, ptr += PAGE_SIZE)
-- __set_fixmap(idx, per_cpu_ptr_to_phys(ptr), prot);
--}
--
--/* Setup the fixmap mappings only once per-processor */
--static void __init setup_cpu_entry_area(int cpu)
--{
--#ifdef CONFIG_X86_64
-- extern char _entry_trampoline[];
--
-- /* On 64-bit systems, we use a read-only fixmap GDT and TSS. */
-- pgprot_t gdt_prot = PAGE_KERNEL_RO;
-- pgprot_t tss_prot = PAGE_KERNEL_RO;
--#else
-- /*
-- * On native 32-bit systems, the GDT cannot be read-only because
-- * our double fault handler uses a task gate, and entering through
-- * a task gate needs to change an available TSS to busy. If the
-- * GDT is read-only, that will triple fault. The TSS cannot be
-- * read-only because the CPU writes to it on task switches.
-- *
-- * On Xen PV, the GDT must be read-only because the hypervisor
-- * requires it.
-- */
-- pgprot_t gdt_prot = boot_cpu_has(X86_FEATURE_XENPV) ?
-- PAGE_KERNEL_RO : PAGE_KERNEL;
-- pgprot_t tss_prot = PAGE_KERNEL;
--#endif
--
-- __set_fixmap(get_cpu_entry_area_index(cpu, gdt), get_cpu_gdt_paddr(cpu), gdt_prot);
-- set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, entry_stack_page),
-- per_cpu_ptr(&entry_stack_storage, cpu), 1,
-- PAGE_KERNEL);
--
-- /*
-- * The Intel SDM says (Volume 3, 7.2.1):
-- *
-- * Avoid placing a page boundary in the part of the TSS that the
-- * processor reads during a task switch (the first 104 bytes). The
-- * processor may not correctly perform address translations if a
-- * boundary occurs in this area. During a task switch, the processor
-- * reads and writes into the first 104 bytes of each TSS (using
-- * contiguous physical addresses beginning with the physical address
-- * of the first byte of the TSS). So, after TSS access begins, if
-- * part of the 104 bytes is not physically contiguous, the processor
-- * will access incorrect information without generating a page-fault
-- * exception.
-- *
-- * There are also a lot of errata involving the TSS spanning a page
-- * boundary. Assert that we're not doing that.
-- */
-- BUILD_BUG_ON((offsetof(struct tss_struct, x86_tss) ^
-- offsetofend(struct tss_struct, x86_tss)) & PAGE_MASK);
-- BUILD_BUG_ON(sizeof(struct tss_struct) % PAGE_SIZE != 0);
-- set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, tss),
-- &per_cpu(cpu_tss_rw, cpu),
-- sizeof(struct tss_struct) / PAGE_SIZE,
-- tss_prot);
--
--#ifdef CONFIG_X86_32
-- per_cpu(cpu_entry_area, cpu) = get_cpu_entry_area(cpu);
- #endif
-
--#ifdef CONFIG_X86_64
-- BUILD_BUG_ON(sizeof(exception_stacks) % PAGE_SIZE != 0);
-- BUILD_BUG_ON(sizeof(exception_stacks) !=
-- sizeof(((struct cpu_entry_area *)0)->exception_stacks));
-- set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, exception_stacks),
-- &per_cpu(exception_stacks, cpu),
-- sizeof(exception_stacks) / PAGE_SIZE,
-- PAGE_KERNEL);
--
-- __set_fixmap(get_cpu_entry_area_index(cpu, entry_trampoline),
-- __pa_symbol(_entry_trampoline), PAGE_KERNEL_RX);
--#endif
--}
--
--void __init setup_cpu_entry_areas(void)
--{
-- unsigned int cpu;
--
-- for_each_possible_cpu(cpu)
-- setup_cpu_entry_area(cpu);
--}
--
- /* Load the original GDT from the per-cpu structure */
- void load_direct_gdt(int cpu)
- {
-diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
-index 14b462eefa17..ef2d1b8a0516 100644
---- a/arch/x86/kernel/traps.c
-+++ b/arch/x86/kernel/traps.c
-@@ -57,6 +57,7 @@
- #include <asm/traps.h>
- #include <asm/desc.h>
- #include <asm/fpu/internal.h>
-+#include <asm/cpu_entry_area.h>
- #include <asm/mce.h>
- #include <asm/fixmap.h>
- #include <asm/mach_traps.h>
-diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c
-new file mode 100644
-index 000000000000..235ff9cfaaf4
---- /dev/null
-+++ b/arch/x86/mm/cpu_entry_area.c
-@@ -0,0 +1,104 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+#include <linux/spinlock.h>
-+#include <linux/percpu.h>
-+
-+#include <asm/cpu_entry_area.h>
-+#include <asm/pgtable.h>
-+#include <asm/fixmap.h>
-+#include <asm/desc.h>
-+
-+static DEFINE_PER_CPU_PAGE_ALIGNED(struct entry_stack_page, entry_stack_storage);
-+
-+#ifdef CONFIG_X86_64
-+static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
-+ [(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]);
-+#endif
-+
-+static void __init
-+set_percpu_fixmap_pages(int idx, void *ptr, int pages, pgprot_t prot)
-+{
-+ for ( ; pages; pages--, idx--, ptr += PAGE_SIZE)
-+ __set_fixmap(idx, per_cpu_ptr_to_phys(ptr), prot);
-+}
-+
-+/* Setup the fixmap mappings only once per-processor */
-+static void __init setup_cpu_entry_area(int cpu)
-+{
-+#ifdef CONFIG_X86_64
-+ extern char _entry_trampoline[];
-+
-+ /* On 64-bit systems, we use a read-only fixmap GDT and TSS. */
-+ pgprot_t gdt_prot = PAGE_KERNEL_RO;
-+ pgprot_t tss_prot = PAGE_KERNEL_RO;
-+#else
-+ /*
-+ * On native 32-bit systems, the GDT cannot be read-only because
-+ * our double fault handler uses a task gate, and entering through
-+ * a task gate needs to change an available TSS to busy. If the
-+ * GDT is read-only, that will triple fault. The TSS cannot be
-+ * read-only because the CPU writes to it on task switches.
-+ *
-+ * On Xen PV, the GDT must be read-only because the hypervisor
-+ * requires it.
-+ */
-+ pgprot_t gdt_prot = boot_cpu_has(X86_FEATURE_XENPV) ?
-+ PAGE_KERNEL_RO : PAGE_KERNEL;
-+ pgprot_t tss_prot = PAGE_KERNEL;
-+#endif
-+
-+ __set_fixmap(get_cpu_entry_area_index(cpu, gdt), get_cpu_gdt_paddr(cpu), gdt_prot);
-+ set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, entry_stack_page),
-+ per_cpu_ptr(&entry_stack_storage, cpu), 1,
-+ PAGE_KERNEL);
-+
-+ /*
-+ * The Intel SDM says (Volume 3, 7.2.1):
-+ *
-+ * Avoid placing a page boundary in the part of the TSS that the
-+ * processor reads during a task switch (the first 104 bytes). The
-+ * processor may not correctly perform address translations if a
-+ * boundary occurs in this area. During a task switch, the processor
-+ * reads and writes into the first 104 bytes of each TSS (using
-+ * contiguous physical addresses beginning with the physical address
-+ * of the first byte of the TSS). So, after TSS access begins, if
-+ * part of the 104 bytes is not physically contiguous, the processor
-+ * will access incorrect information without generating a page-fault
-+ * exception.
-+ *
-+ * There are also a lot of errata involving the TSS spanning a page
-+ * boundary. Assert that we're not doing that.
-+ */
-+ BUILD_BUG_ON((offsetof(struct tss_struct, x86_tss) ^
-+ offsetofend(struct tss_struct, x86_tss)) & PAGE_MASK);
-+ BUILD_BUG_ON(sizeof(struct tss_struct) % PAGE_SIZE != 0);
-+ set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, tss),
-+ &per_cpu(cpu_tss_rw, cpu),
-+ sizeof(struct tss_struct) / PAGE_SIZE,
-+ tss_prot);
-+
-+#ifdef CONFIG_X86_32
-+ per_cpu(cpu_entry_area, cpu) = get_cpu_entry_area(cpu);
-+#endif
-+
-+#ifdef CONFIG_X86_64
-+ BUILD_BUG_ON(sizeof(exception_stacks) % PAGE_SIZE != 0);
-+ BUILD_BUG_ON(sizeof(exception_stacks) !=
-+ sizeof(((struct cpu_entry_area *)0)->exception_stacks));
-+ set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, exception_stacks),
-+ &per_cpu(exception_stacks, cpu),
-+ sizeof(exception_stacks) / PAGE_SIZE,
-+ PAGE_KERNEL);
-+
-+ __set_fixmap(get_cpu_entry_area_index(cpu, entry_trampoline),
-+ __pa_symbol(_entry_trampoline), PAGE_KERNEL_RX);
-+#endif
-+}
-+
-+void __init setup_cpu_entry_areas(void)
-+{
-+ unsigned int cpu;
-+
-+ for_each_possible_cpu(cpu)
-+ setup_cpu_entry_area(cpu);
-+}
---
-2.14.2
-