BACKPORT: arm64: kaslr: randomize the linear region
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Fri, 29 Jan 2016 10:59:03 +0000 (11:59 +0100)
committerJeff Vander Stoep <jeffv@google.com>
Thu, 22 Sep 2016 20:38:22 +0000 (13:38 -0700)
When KASLR is enabled (CONFIG_RANDOMIZE_BASE=y), and entropy has been
provided by the bootloader, randomize the placement of RAM inside the
linear region if sufficient space is available. For instance, on a 4KB
granule/3 levels kernel, the linear region is 256 GB in size, and we can
choose any 1 GB aligned offset that is far enough from the top of the
address space to fit the distance between the start of the lowest memblock
and the top of the highest memblock.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Bug: 30369029
Patchset: kaslr-arm64-4.4

(cherry picked from commit 031a4213c11a5db475f528c182f7b3858df11db)
Signed-off-by: Jeff Vander Stoep <jeffv@google.com>
Change-Id: I272de8ee358351d95eacc7dc5f47600adec3e813

arch/arm64/kernel/kaslr.c
arch/arm64/mm/init.c

index 8b32a1f8f09f3f7fccc04f6f1ae7463d5fe109a1..582983920054716916e4a4a0159d040f4555a2aa 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/sections.h>
 
 u64 __read_mostly module_alloc_base;
+u16 __initdata memstart_offset_seed;
 
 static __init u64 get_kaslr_seed(void *fdt)
 {
@@ -123,6 +124,9 @@ u64 __init kaslr_early_init(u64 dt_phys)
        mask = ((1UL << (VA_BITS - 2)) - 1) & ~(SZ_2M - 1);
        offset = seed & mask;
 
+       /* use the top 16 bits to randomize the linear region */
+       memstart_offset_seed = seed >> 48;
+
        /*
         * The kernel Image should not extend across a 1GB/32MB/512MB alignment
         * boundary (for 4KB/16KB/64KB granule kernels, respectively). If this
index 3d75ff40c5ffe50df13d922acf9f9c1cf9cc5dbc..8e3cf19e4f0091f80fcf7a30c76c7ed2df1aa75b 100644 (file)
@@ -198,6 +198,23 @@ void __init arm64_memblock_init(void)
                memblock_add(__pa(_text), (u64)(_end - _text));
        }
 
+       if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
+               extern u16 memstart_offset_seed;
+               u64 range = linear_region_size -
+                           (memblock_end_of_DRAM() - memblock_start_of_DRAM());
+
+               /*
+                * If the size of the linear region exceeds, by a sufficient
+                * margin, the size of the region that the available physical
+                * memory spans, randomize the linear region as well.
+                */
+               if (memstart_offset_seed > 0 && range >= ARM64_MEMSTART_ALIGN) {
+                       range = range / ARM64_MEMSTART_ALIGN + 1;
+                       memstart_addr -= ARM64_MEMSTART_ALIGN *
+                                        ((range * memstart_offset_seed) >> 16);
+               }
+       }
+
        /*
         * Register the kernel text, kernel data, initrd, and initial
         * pagetables with memblock.
@@ -367,12 +384,13 @@ void __init mem_init(void)
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
                  MLG(VMEMMAP_START,
                      VMEMMAP_START + VMEMMAP_SIZE),
-                 MLM((unsigned long)virt_to_page(PAGE_OFFSET),
+                 MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
                      (unsigned long)virt_to_page(high_memory)),
 #endif
                  MLK(FIXADDR_START, FIXADDR_TOP),
                  MLM(PCI_IO_START, PCI_IO_END),
-                 MLM(PAGE_OFFSET, (unsigned long)high_memory));
+                 MLM(__phys_to_virt(memblock_start_of_DRAM()),
+                     (unsigned long)high_memory));
 
 #undef MLK
 #undef MLM