]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
arm64: mm: Map entry trampoline into trampoline and kernel page tables
authorWill Deacon <will.deacon@arm.com>
Tue, 14 Nov 2017 14:14:17 +0000 (14:14 +0000)
committerKhalid Elmously <khalid.elmously@canonical.com>
Tue, 27 Feb 2018 16:32:42 +0000 (11:32 -0500)
Commit 51a0048beb44 upstream.

The exception entry trampoline needs to be mapped at the same virtual
address in both the trampoline page table (which maps nothing else)
and also the kernel page table, so that we can swizzle TTBR1_EL1 on
exceptions from and return to EL0.

This patch maps the trampoline at a fixed virtual address in the fixmap
area of the kernel virtual address space, which allows the kernel proper
to be randomized with respect to the trampoline when KASLR is enabled.

Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Laura Abbott <labbott@redhat.com>
Tested-by: Shanker Donthineni <shankerd@codeaurora.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 63d13760abd7a819b6e95793c795cdc155bfff44)

CVE-2017-5753
CVE-2017-5715
CVE-2017-5754

Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
Acked-by: Brad Figg <brad.figg@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
arch/arm64/include/asm/fixmap.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/asm-offsets.c
arch/arm64/mm/mmu.c

index 4052ec39e8dbb06feb74e1161dcf26ac94744fb2..8119b49be98dc2edb27b17a1e1b4db842e79f03e 100644 (file)
@@ -58,6 +58,10 @@ enum fixed_addresses {
        FIX_APEI_GHES_NMI,
 #endif /* CONFIG_ACPI_APEI_GHES */
 
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+       FIX_ENTRY_TRAMP_TEXT,
+#define TRAMP_VALIAS           (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT))
+#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
        __end_of_permanent_fixed_addresses,
 
        /*
index b46e54c2399b58b6451ea9dacc5c033115b05c64..2f3b58a1d4344c49c7a07a33e14577c2ffccaa6d 100644 (file)
@@ -667,6 +667,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
+extern pgd_t tramp_pg_dir[PTRS_PER_PGD];
 
 /*
  * Encode and decode a swap entry:
index 71bf088f1e4b2e63062fd1e75320b69c0951b050..af247d10252f5019e8b44361bb4a8a724300d7e1 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/kvm_host.h>
 #include <linux/suspend.h>
 #include <asm/cpufeature.h>
+#include <asm/fixmap.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
 #include <asm/smp_plat.h>
@@ -148,11 +149,14 @@ int main(void)
   DEFINE(ARM_SMCCC_RES_X2_OFFS,                offsetof(struct arm_smccc_res, a2));
   DEFINE(ARM_SMCCC_QUIRK_ID_OFFS,      offsetof(struct arm_smccc_quirk, id));
   DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS,   offsetof(struct arm_smccc_quirk, state));
-
   BLANK();
   DEFINE(HIBERN_PBE_ORIG,      offsetof(struct pbe, orig_address));
   DEFINE(HIBERN_PBE_ADDR,      offsetof(struct pbe, address));
   DEFINE(HIBERN_PBE_NEXT,      offsetof(struct pbe, next));
   DEFINE(ARM64_FTR_SYSVAL,     offsetof(struct arm64_ftr_reg, sys_val));
+  BLANK();
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+  DEFINE(TRAMP_VALIAS,         TRAMP_VALIAS);
+#endif
   return 0;
 }
index f1eb15e0e8642d2a74c7d19d18e8e8d3ae5a7062..3b9af178f791baa946cbd8b899a6f029c1691724 100644 (file)
@@ -525,6 +525,29 @@ static int __init parse_rodata(char *arg)
 }
 early_param("rodata", parse_rodata);
 
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+static int __init map_entry_trampoline(void)
+{
+       extern char __entry_tramp_text_start[];
+
+       pgprot_t prot = rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC;
+       phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start);
+
+       /* The trampoline is always mapped and can therefore be global */
+       pgprot_val(prot) &= ~PTE_NG;
+
+       /* Map only the text into the trampoline page table */
+       memset(tramp_pg_dir, 0, PGD_SIZE);
+       __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE,
+                            prot, pgd_pgtable_alloc, 0);
+
+       /* ...as well as the kernel page table */
+       __set_fixmap(FIX_ENTRY_TRAMP_TEXT, pa_start, prot);
+       return 0;
+}
+core_initcall(map_entry_trampoline);
+#endif
+
 /*
  * Create fine-grained mappings for the kernel.
  */