Skip to content

Commit

Permalink
arm64: mm: Map entry trampoline into trampoline and kernel page tables
Browse files Browse the repository at this point in the history
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 <[email protected]>
Tested-by: Laura Abbott <[email protected]>
Tested-by: Shanker Donthineni <[email protected]>
Signed-off-by: Will Deacon <[email protected]>
  • Loading branch information
wildea01 committed Dec 11, 2017
1 parent c7b9ada commit 51a0048
Showing 4 changed files with 33 additions and 1 deletion.
4 changes: 4 additions & 0 deletions arch/arm64/include/asm/fixmap.h
Original file line number Diff line number Diff line change
@@ -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,

/*
1 change: 1 addition & 0 deletions arch/arm64/include/asm/pgtable.h
Original file line number Diff line number Diff line change
@@ -680,6 +680,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:
6 changes: 5 additions & 1 deletion arch/arm64/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
@@ -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;
}
23 changes: 23 additions & 0 deletions arch/arm64/mm/mmu.c
Original file line number Diff line number Diff line change
@@ -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.
*/

0 comments on commit 51a0048

Please sign in to comment.