| From foo@baz Thu Apr 5 21:39:28 CEST 2018 |
| From: Mark Rutland <mark.rutland@arm.com> |
| Date: Tue, 3 Apr 2018 12:09:10 +0100 |
| Subject: arm64: kaslr: Put kernel vectors address in separate data page |
| To: stable@vger.kernel.org |
| Cc: mark.brown@linaro.org, ard.biesheuvel@linaro.org, marc.zyngier@arm.com, will.deacon@arm.com |
| Message-ID: <20180403110923.43575-15-mark.rutland@arm.com> |
| |
| From: Will Deacon <will.deacon@arm.com> |
| |
| commit 6c27c4082f4f upstream. |
| |
| The literal pool entry for identifying the vectors base is the only piece |
| of information in the trampoline page that identifies the true location |
| of the kernel. |
| |
| This patch moves it into a page-aligned region of the .rodata section |
| and maps this adjacent to the trampoline text via an additional fixmap |
| entry, which protects against any accidental leakage of the trampoline |
| contents. |
| |
| Suggested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> |
| Tested-by: Laura Abbott <labbott@redhat.com> |
| Tested-by: Shanker Donthineni <shankerd@codeaurora.org> |
| Signed-off-by: Will Deacon <will.deacon@arm.com> |
| [Alex: avoid ARM64_WORKAROUND_QCOM_FALKOR_E1003 dependency] |
| Signed-off-by: Alex Shi <alex.shi@linaro.org> [v4.9 backport] |
| Signed-off-by: Mark Rutland <mark.rutland@arm.com> [v4.9 backport] |
| Tested-by: Will Deacon <will.deacon@arm.com> |
| Tested-by: Greg Hackmann <ghackmann@google.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/arm64/include/asm/fixmap.h | 1 + |
| arch/arm64/kernel/entry.S | 14 ++++++++++++++ |
| arch/arm64/kernel/vmlinux.lds.S | 5 ++++- |
| arch/arm64/mm/mmu.c | 10 +++++++++- |
| 4 files changed, 28 insertions(+), 2 deletions(-) |
| |
| --- a/arch/arm64/include/asm/fixmap.h |
| +++ b/arch/arm64/include/asm/fixmap.h |
| @@ -53,6 +53,7 @@ enum fixed_addresses { |
| FIX_TEXT_POKE0, |
| |
| #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
| + FIX_ENTRY_TRAMP_DATA, |
| FIX_ENTRY_TRAMP_TEXT, |
| #define TRAMP_VALIAS (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT)) |
| #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ |
| --- a/arch/arm64/kernel/entry.S |
| +++ b/arch/arm64/kernel/entry.S |
| @@ -881,7 +881,13 @@ __ni_sys_trace: |
| msr tpidrro_el0, x30 // Restored in kernel_ventry |
| .endif |
| tramp_map_kernel x30 |
| +#ifdef CONFIG_RANDOMIZE_BASE |
| + adr x30, tramp_vectors + PAGE_SIZE |
| + isb |
| + ldr x30, [x30] |
| +#else |
| ldr x30, =vectors |
| +#endif |
| prfm plil1strm, [x30, #(1b - tramp_vectors)] |
| msr vbar_el1, x30 |
| add x30, x30, #(1b - tramp_vectors) |
| @@ -924,6 +930,14 @@ END(tramp_exit_compat) |
| |
| .ltorg |
| .popsection // .entry.tramp.text |
| +#ifdef CONFIG_RANDOMIZE_BASE |
| + .pushsection ".rodata", "a" |
| + .align PAGE_SHIFT |
| + .globl __entry_tramp_data_start |
| +__entry_tramp_data_start: |
| + .quad vectors |
| + .popsection // .rodata |
| +#endif /* CONFIG_RANDOMIZE_BASE */ |
| #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ |
| |
| /* |
| --- a/arch/arm64/kernel/vmlinux.lds.S |
| +++ b/arch/arm64/kernel/vmlinux.lds.S |
| @@ -252,7 +252,10 @@ ASSERT(__idmap_text_end - (__idmap_text_ |
| ASSERT(__hibernate_exit_text_end - (__hibernate_exit_text_start & ~(SZ_4K - 1)) |
| <= SZ_4K, "Hibernate exit text too big or misaligned") |
| #endif |
| - |
| +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
| +ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE, |
| + "Entry trampoline text too big") |
| +#endif |
| /* |
| * If padding is applied before .head.text, virt<->phys conversions will fail. |
| */ |
| --- a/arch/arm64/mm/mmu.c |
| +++ b/arch/arm64/mm/mmu.c |
| @@ -435,8 +435,16 @@ static int __init map_entry_trampoline(v |
| __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE, |
| prot, pgd_pgtable_alloc, 0); |
| |
| - /* ...as well as the kernel page table */ |
| + /* Map both the text and data into the kernel page table */ |
| __set_fixmap(FIX_ENTRY_TRAMP_TEXT, pa_start, prot); |
| + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { |
| + extern char __entry_tramp_data_start[]; |
| + |
| + __set_fixmap(FIX_ENTRY_TRAMP_DATA, |
| + __pa_symbol(__entry_tramp_data_start), |
| + PAGE_KERNEL_RO); |
| + } |
| + |
| return 0; |
| } |
| core_initcall(map_entry_trampoline); |