arm64: relocatable: deal with physically misaligned kernel images
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Mon, 18 Apr 2016 15:09:47 +0000 (17:09 +0200)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Fri, 29 Jul 2016 16:59:49 +0000 (18:59 +0200)
When booting a relocatable kernel image, there is no practical reason
to refuse an image whose load address is not exactly TEXT_OFFSET bytes
above a 2 MB aligned base address, as long as the physical and virtual
misalignment with respect to the swapper block size are equal, and are
both aligned to THREAD_SIZE.

Since the virtual misalignment is under our control when we first enter
the kernel proper, we can simply choose its value to be equal to the
physical misalignment.

So treat the misalignment of the physical load address as the initial
KASLR offset, and fix up the remaining code to deal with that.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
(cherry picked from commit 08cdac619c81b3fa8cd73aeed2330ffe0a0b73ca)
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
arch/arm64/kernel/head.S
arch/arm64/kernel/kaslr.c

index 43484433b3ce6b8655addad0e6651c499a637d2b..491ad4124615903e6ebc98f5e063e5aa395236f2 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/assembler.h>
+#include <asm/boot.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
@@ -211,8 +212,8 @@ efi_header_end:
 ENTRY(stext)
        bl      preserve_boot_args
        bl      el2_setup                       // Drop to EL1, w20=cpu_boot_mode
-       mov     x23, xzr                        // KASLR offset, defaults to 0
        adrp    x24, __PHYS_OFFSET
+       and     x23, x24, MIN_KIMG_ALIGN - 1    // KASLR offset, defaults to 0
        bl      set_cpu_boot_mode_flag
        bl      __create_page_tables            // x25=TTBR0, x26=TTBR1
        /*
@@ -447,11 +448,13 @@ __primary_switched:
        bl      kasan_early_init
 #endif
 #ifdef CONFIG_RANDOMIZE_BASE
-       cbnz    x23, 0f                         // already running randomized?
+       tst     x23, ~(MIN_KIMG_ALIGN - 1)      // already running randomized?
+       b.ne    0f
        mov     x0, x21                         // pass FDT address in x0
+       mov     x1, x23                         // pass modulo offset in x1
        bl      kaslr_early_init                // parse FDT for KASLR options
        cbz     x0, 0f                          // KASLR disabled? just proceed
-       mov     x23, x0                         // record KASLR offset
+       orr     x23, x23, x0                    // record KASLR offset
        ret     x28                             // we must enable KASLR, return
                                                // to __enable_mmu()
 0:
index 582983920054716916e4a4a0159d040f4555a2aa..b05469173ba523c77f7cf74dc78aeacffee385ee 100644 (file)
@@ -74,7 +74,7 @@ extern void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size,
  * containing function pointers) to be reinitialized, and zero-initialized
  * .bss variables will be reset to 0.
  */
-u64 __init kaslr_early_init(u64 dt_phys)
+u64 __init kaslr_early_init(u64 dt_phys, u64 modulo_offset)
 {
        void *fdt;
        u64 seed, offset, mask, module_range;
@@ -132,8 +132,8 @@ u64 __init kaslr_early_init(u64 dt_phys)
         * boundary (for 4KB/16KB/64KB granule kernels, respectively). If this
         * happens, increase the KASLR offset by the size of the kernel image.
         */
-       if ((((u64)_text + offset) >> SWAPPER_TABLE_SHIFT) !=
-           (((u64)_end + offset) >> SWAPPER_TABLE_SHIFT))
+       if ((((u64)_text + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT) !=
+           (((u64)_end + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT))
                offset = (offset + (u64)(_end - _text)) & mask;
 
        if (IS_ENABLED(CONFIG_KASAN))