x86, boot: KASLR memory implementation
Subsystems (3)
v2 cover x86, boot: KASLR memory implementation
This is PATCH v2 for KASLR memory implementation for x86_64. Edit commit based on recents testing against the KASLR bypass exploits & rebase on next-20160502.
***Background:
The current implementation of KASLR randomizes only the base address of the kernel and its modules. Research was published showing that static memory can be overwitten to elevate privileges bypassing KASLR.
In more details:
The physical memory mapping holds most allocations from boot and heap allocators. Knowning the base address and physical memory size, an attacker can deduce the PDE virtual address for the vDSO memory page. This attack was demonstrated at CanSecWest 2016, in the "Getting Physical Extreme Abuse of Intel Based Paged Systems"
https://goo.gl/ANpWdV (see second part of the presentation). Similar research was done at Google leading to this patch proposal. Variants exists to overwrite /proc or /sys objects ACLs leading to elevation of privileges. These variants were tested against 4.6+.
This set of patches randomizes base address and padding of three major memory sections (physical memory mapping, vmalloc & vmemmap). It mitigates exploits relying on predictable kernel addresses. This feature can be enabled with the CONFIG_RANDOMIZE_MEMORY option.
Padding for the memory hotplug support is managed by CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING. The default value is 10 terabytes.
The patches were tested on qemu & physical machines. Xen compatibility was also verified. Multiple reboots were used to verify entropy for each memory section.
***Problems that needed solving:
- The three target memory sections are never at the same place between boots.
- The physical memory mapping can use a virtual address not aligned on the PGD page table.
- Have good entropy early at boot before get_random_bytes is available.
- Add optional padding for memory hotplug compatibility.
***Parts:
- The first part prepares for the KASLR memory randomization by refactoring entropy functions used by the current implementation and support PUD level virtual addresses for physical mapping. (Patches 01-02)
- The second part implements the KASLR memory randomization for all sections mentioned.
(Patch 03)
- The third part adds support for memory hotplug by adding an option to define the padding used between the physical memory mapping section and the others.
(Patch 04)
Thanks!
PATCH v2 1/4 x86, boot: Refactor KASLR entropy functions
Move the KASLR entropy functions in x86/libray to be used in early kernel boot for KASLR memory randomization.
---
Based on next-20160502
--- arch/x86/boot/compressed/kaslr.c | 76 +++----------------------------------- arch/x86/include/asm/kaslr.h | 6 +++ arch/x86/lib/Makefile | 1 + arch/x86/lib/kaslr.c | 79 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 71 deletions(-) create mode 100644 arch/x86/include/asm/kaslr.h create mode 100644 arch/x86/lib/kaslr.c
arch/x86/boot/compressed/kaslr.c +5 -71
@@ -11,10 +11,6 @@*/ #include "misc.h" -#include <asm/msr.h> -#include <asm/archrandom.h> -#include <asm/e820.h> -#include <generated/compile.h> #include <linux/module.h> #include <linux/uts.h>
@@ -25,26 +21,6 @@static const char build_str[] =UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION ; -#define I8254_PORT_CONTROL 0x43 -#define I8254_PORT_COUNTER0 0x40 -#define I8254_CMD_READBACK 0xC0 -#define I8254_SELECT_COUNTER0 0x02 -#define I8254_STATUS_NOTREADY 0x40 -static inline u16 i8254 (void ) -{ -u16 status, timer; - -do { -outb (I8254_PORT_CONTROL , -I8254_CMD_READBACK |I8254_SELECT_COUNTER0 ); - status =inb (I8254_PORT_COUNTER0 ); - timer =inb (I8254_PORT_COUNTER0 ); - timer |=inb (I8254_PORT_COUNTER0 ) <<8 ; - }while (status &I8254_STATUS_NOTREADY ); - -return timer; -} -static unsigned long rotate_xor (unsigned long hash,const void *area,size_t size) {
@@ -61,7 +37,7 @@ static unsigned long rotate_xor(unsigned long hash, const void *area, }/* Attempt to create a simple but unpredictable starting entropy. */ -static unsigned long get_random_boot (void ) +static unsigned long get_boot_seed (void ) {unsigned long hash =0 ;
@@ -71,50 +47,6 @@ static unsigned long get_random_boot(void)return hash; } -static unsigned long get_random_long (void ) -{ -#ifdef CONFIG_X86_64 -const unsigned long mix_const =0x5d6008cbf3848dd3UL ; -#else -const unsigned long mix_const =0x3f39e593UL ; -#endif -unsigned long raw, random =get_random_boot (); -bool use_i8254 = true; - -debug_putstr ("KASLR using" ); - -if (has_cpuflag (X86_FEATURE_RDRAND )) { -debug_putstr (" RDRAND" ); -if (rdrand_long (&raw)) { - random ^= raw; - use_i8254 = false; - } - } - -if (has_cpuflag (X86_FEATURE_TSC )) { -debug_putstr (" RDTSC" ); - raw =rdtsc (); - - random ^= raw; - use_i8254 = false; - } - -if (use_i8254) { -debug_putstr (" i8254" ); - random ^=i8254 (); - } - -/* Circular multiply for better bit diffusion */ - asm("mul %3" - :"=a" (random),"=d" (raw) - :"a" (random),"rm" (mix_const)); - random += raw; - -debug_putstr ("...\n" ); - -return random; -} -struct mem_vector {unsigned long start;unsigned long size;
@@ -122,7 +54,6 @@ struct mem_vector {#define MEM_AVOID_MAX 5static struct mem_vector mem_avoid[MEM_AVOID_MAX ]; -static bool mem_contains (struct mem_vector *region,struct mem_vector *item) {/* Item at least partially before region. */
@@ -229,13 +160,16 @@ static void slots_append(unsigned long addr) slots[slot_max++] = addr; } +#define KASLR_COMPRESSED_BOOT +#include "../../lib/kaslr.c" +static unsigned long slots_fetch_random (void ) {/* Handle case of no slots stored. */ if (slot_max ==0 )return 0 ; -return slots[get_random_long () % slot_max]; +return slots[kaslr_get_random_boot_long () % slot_max]; } static void process_e820_entry(struct e820entry *entry,
arch/x86/include/asm/kaslr.h new file +6 -0
@@ -0,0 +1,6 @@ +#ifndef _ASM_KASLR_H_ +#define _ASM_KASLR_H_ + +unsigned long kaslr_get_random_boot_long (void ); + +#endif
arch/x86/lib/Makefile +1 -0
@@ -24,6 +24,7 @@ lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o lib-y += memcpy_$(BITS).o lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o +lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o obj-y += msr.o msr-reg.o msr-reg-export.o
arch/x86/lib/kaslr.c new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
2.8.0.rc3.226.g39d4020
PATCH v2 2/4 x86, boot: PUD VA support for physical mapping (x86_64)
In reply to Thomas GarnierMinor change that allows early boot physical mapping of PUD level virtual addresses. This change prepares usage of different virtual addresses for KASLR memory randomization. It has no impact on default usage.
---
Based on next-20160502
--- arch/x86/mm/init_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/mm/init_64.c +2 -2
@@ -526,10 +526,10 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, {unsigned long pages =0 , next;unsigned long last_map_addr = end; -int i =pud_index (addr); +int i =pud_index ((unsigned long )__va (addr));for (; i <PTRS_PER_PUD ; i++, addr = next) { -pud_t *pud = pud_page +pud_index (addr); +pud_t *pud = pud_page +pud_index ((unsigned long )__va (addr));pmd_t *pmd;pgprot_t prot =PAGE_KERNEL ;
Signature · 1 line
2.8.0.rc3.226.g39d4020
Dave Hansen
maintainerRe: [PATCH v2 2/4] x86, boot: PUD VA support for physical mapping (x86_64)
Quoted 3 lines · Thomas Garnier
Minor change that allows early boot physical mapping of PUD level virtual addresses. This change prepares usage of different virtual addresses for KASLR memory randomization. It has no impact on default usage.
...
Quoted 6 lines
arch/x86/mm/init_64.c +0
-0@@ -526,10 +526,10 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, {
arch/x86/mm/init_64.c phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, · line 534
Quoted 10 lines
arch/x86/mm/init_64.c +2
-2unsigned long pages =0 , next;unsigned long last_map_addr = end; -int i =pud_index (addr); +int i =pud_index ((unsigned long )__va (addr));for (; i <PTRS_PER_PUD ; i++, addr = next) { -pud_t *pud = pud_page +pud_index (addr); +pud_t *pud = pud_page +pud_index ((unsigned long )__va (addr));pmd_t *pmd;pgprot_t prot =PAGE_KERNEL ;
pud_index() is supposed to take a virtual address. We were passing a physical address in here, and it all just worked because PAGE_OFFSET is PUD-aligned. Now that you are moving PAGE_OFFSET around a bit and not PUD-aligning it, this breaks. Right?
Could you spell this out a bit more the changelog?
Re: [PATCH v2 2/4] x86, boot: PUD VA support for physical mapping (x86_64)
Quoted 16 lines · Dave Hansen
Quoted 3 lines · Thomas Garnier
Minor change that allows early boot physical mapping of PUD level virtual addresses. This change prepares usage of different virtual addresses for KASLR memory randomization. It has no impact on default usage.
...
Quoted 11 lines
arch/x86/mm/init_64.c +1
-1@@ -526,10 +526,10 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, {unsigned long pages =0 , next;unsigned long last_map_addr = end; -int i =pud_index (addr); +int i =pud_index ((unsigned long )__va (addr));
Quoted 10 lines
arch/x86/mm/init_64.c phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, · line 534
Quoted 5 lines
arch/x86/mm/init_64.c +1
-1for (; i <PTRS_PER_PUD ; i++, addr = next) { -pud_t *pud = pud_page +pud_index (addr); +pud_t *pud = pud_page +pud_index ((unsigned long )__va (addr));pmd_t *pmd;pgprot_t prot =PAGE_KERNEL ;
pud_index()is supposed to take a virtual address. We were passing a physical address in here, and it all just worked becausePAGE_OFFSETis PUD-aligned. Now that you are movingPAGE_OFFSETaround a bit and not PUD-aligning it, this breaks. Right?
Yes. Acutally here code is tricky since PAGE_OFFSET is PUD-aligned or . Usually we setup memory mapping with physical addr and the corresponding virtual addr, here for less parameter we only pass in physical addr. X86 people need to make it clear about this. Of course explaining it in patch log is also helpful.
I have a tiny concern about phys_pmd_init(), both phys_pud_init and phys_pte_init name 2nd parameter as 'addr', phys_pmd_init use 'address'. If this can be changed to make them look consistent completist would have a good sleep from now on.
Thanks
Baoquan
Dave Hansen
maintainerRe: [PATCH v2 2/4] x86, boot: PUD VA support for physical mapping (x86_64)
Quoted 4 lines · Baoquan He
I have a tiny concern about
phys_pmd_init(), bothphys_pud_initandphys_pte_initname 2nd parameter as 'addr',phys_pmd_inituse 'address'. If this can be changed to make them look consistent completist would have a good sleep from now on.
Yes, consistency would be nice. Even better would be to call them all 'phys_addr'.
Re: [PATCH v2 2/4] x86, boot: PUD VA support for physical mapping (x86_64)
In reply to Dave HansenQuoted 27 lines · Dave Hansen
Quoted 3 lines · Thomas Garnier
Minor change that allows early boot physical mapping of PUD level virtual addresses. This change prepares usage of different virtual addresses for KASLR memory randomization. It has no impact on default usage.
...
Quoted 6 lines
arch/x86/mm/init_64.c +0
-0@@ -526,10 +526,10 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, {arch/x86/mm/init_64.c phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, · line 534
Quoted 10 lines
arch/x86/mm/init_64.c +2
-2unsigned long pages =0 , next;unsigned long last_map_addr = end; -int i =pud_index (addr); +int i =pud_index ((unsigned long )__va (addr));for (; i <PTRS_PER_PUD ; i++, addr = next) { -pud_t *pud = pud_page +pud_index (addr); +pud_t *pud = pud_page +pud_index ((unsigned long )__va (addr));pmd_t *pmd;pgprot_t prot =PAGE_KERNEL ;
pud_index()is supposed to take a virtual address. We were passing a physical address in here, and it all just worked becausePAGE_OFFSETis PUD-aligned. Now that you are movingPAGE_OFFSETaround a bit and not PUD-aligning it, this breaks. Right?
Quoted 1 line
Could you spell this out a bit more the changelog?
Sure, will do on next iteration.
Thanks,
Thomas
PATCH v2 3/4 x86, boot: Implement ASLR for kernel memory sections (x86_64)
In reply to Thomas GarnierRandomizes the virtual address space of kernel memory sections (physical memory mapping, vmalloc & vmemmap) for x86_64. This security feature mitigates exploits relying on predictable kernel addresses. These addresses can be used to disclose the kernel modules base addresses or corrupt specific structures to elevate privileges bypassing the current implementation of KASLR. This feature can be enabled with the CONFIG_RANDOMIZE_MEMORY option.
The physical memory mapping holds most allocations from boot and heap allocators. Knowning the base address and physical memory size, an attacker can deduce the PDE virtual address for the vDSO memory page. This attack was demonstrated at CanSecWest 2016, in the "Getting Physical Extreme Abuse of Intel Based Paged Systems"
https://goo.gl/ANpWdV (see second part of the presentation). The exploits used against Linux worked successfuly against 4.6+ but fail with KASLR memory enabled (https://goo.gl/iTtXMJ). Similar research was done at Google leading to this patch proposal. Variants exists to overwrite /proc or /sys objects ACLs leading to elevation of privileges. These variants were testeda against 4.6+.
The vmalloc memory section contains the allocation made through the vmalloc api. The allocations are done sequentially to prevent fragmentation and each allocation address can easily be deduced especially from boot.
The vmemmap section holds a representation of the physical memory (through a struct page array). An attacker could use this section to disclose the kernel memory layout (walking the page linked list).
The order of each memory section is not changed. The feature looks at the available space for the sections based on different configuration options and randomizes the base and space between each. The size of the physical memory mapping is the available physical memory. No performance impact was detected while testing the feature.
Entropy is generated using the KASLR early boot functions now shared in the lib directory (originally written by Kees Cook). Randomization is done on PGD & PUD page table levels to increase possible addresses. The physical memory mapping code was adapted to support PUD level virtual addresses. An additional low memory page is used to ensure each CPU can start with a PGD aligned virtual address (for realmode).
x86/dump_pagetable was updated to correctly display each section.
Updated documentation on x86_64 memory layout accordingly.
---
Based on next-20160502
--- Documentation/x86/x86_64/mm.txt | 4 + arch/x86/Kconfig | 15 ++++ arch/x86/include/asm/kaslr.h | 12 +++ arch/x86/include/asm/page_64_types.h | 11 ++- arch/x86/include/asm/pgtable_64.h | 1 + arch/x86/include/asm/pgtable_64_types.h | 15 +++- arch/x86/kernel/head_64.S | 2 +- arch/x86/kernel/setup.c | 3 + arch/x86/mm/Makefile | 1 + arch/x86/mm/dump_pagetables.c | 11 ++- arch/x86/mm/init.c | 4 + arch/x86/mm/kaslr.c | 136 ++++++++++++++++++++++++++++++++ arch/x86/realmode/init.c | 4 + 13 files changed, 211 insertions(+), 8 deletions(-) create mode 100644 arch/x86/mm/kaslr.c
Documentation/x86/x86_64/mm.txt +4 -0
@@ -39,4 +39,8 @@ memory window (this size is arbitrary, it can be raised later if needed). The mappings are not part of any other kernel PGD and are only available during EFI runtime calls. +Note that if CONFIG_RANDOMIZE_MEMORY is enabled, the direct mapping of all +physical memory, vmalloc/ioremap space and virtual memory map are randomized. +Their order is preserved but their base will be changed early at boot time. + -Andi Kleen, Jul 2004
arch/x86/Kconfig +15 -0
@@ -1988,6 +1988,21 @@ config PHYSICAL_ALIGN Don't change this unless you know what you are doing. +config RANDOMIZE_MEMORY + bool "Randomize the kernel memory sections" + depends on X86_64 + depends on RANDOMIZE_BASE + default n + ---help--- + Randomizes the virtual address of memory sections (physical memory + mapping, vmalloc & vmemmap). This security feature mitigates exploits + relying on predictable memory locations. + + Base and padding between memory section is randomized. Their order is + not. Entropy is generated in the same way as RANDOMIZE_BASE. + + If unsure, say N. + config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" depends on SMP
arch/x86/include/asm/kaslr.h +12 -0
@@ -3,4 +3,16 @@unsigned long kaslr_get_random_boot_long (void ); +#ifdef CONFIG_RANDOMIZE_MEMORY +extern unsigned long page_offset_base; +extern unsigned long vmalloc_base; +extern unsigned long vmemmap_base; + +void kernel_randomize_memory (void ); +void kaslr_trampoline_init (void ); +#else +static inline void kernel_randomize_memory (void ) { } +static inline void kaslr_trampoline_init (void ) { } +#endif /* CONFIG_RANDOMIZE_MEMORY */ +#endif
arch/x86/include/asm/page_64_types.h +10 -1
@@ -1,6 +1,10 @@#ifndef _ASM_X86_PAGE_64_DEFS_H#define _ASM_X86_PAGE_64_DEFS_H +#ifndef __ASSEMBLY__ +#include <asm/kaslr.h> +#endif +#ifdef CONFIG_KASAN #define KASAN_STACK_ORDER 1#else
@@ -32,7 +36,12 @@* hypervisor to fit. Choosing 16 slots here is arbitrary, but it's * what Xen requires. */ -#define __PAGE_OFFSET _AC(0xffff880000000000, UL) +#define __PAGE_OFFSET_BASE _AC(0xffff880000000000, UL) +#ifdef CONFIG_RANDOMIZE_MEMORY +#define __PAGE_OFFSET page_offset_base +#else +#define __PAGE_OFFSET __PAGE_OFFSET_BASE +#endif /* CONFIG_RANDOMIZE_MEMORY */ #define __START_KERNEL_map _AC(0xffffffff80000000, UL)
arch/x86/include/asm/pgtable_64.h +1 -0
@@ -21,6 +21,7 @@ extern pmd_t level2_fixmap_pgt[512];extern pmd_t level2_ident_pgt[512 ];extern pte_t level1_fixmap_pgt[512 ];extern pgd_t init_level4_pgt[]; +extern pgd_t trampoline_pgd_entry;#define swapper_pg_dir init_level4_pgt
arch/x86/include/asm/pgtable_64_types.h +12 -3
@@ -5,6 +5,7 @@#ifndef __ASSEMBLY__#include <linux/types.h> +#include <asm/kaslr.h> /* * These are used to make use of C type-checking..
@@ -54,9 +55,17 @@ typedef struct { pteval_t pte; } pte_t;/* See Documentation/x86/x86_64/mm.txt for a description of the memory map. */ #define MAXMEM _AC(__AC(1, UL) << MAX_PHYSMEM_BITS, UL) -#define VMALLOC_START _AC(0xffffc90000000000, UL) -#define VMALLOC_END _AC(0xffffe8ffffffffff, UL) -#define VMEMMAP_START _AC(0xffffea0000000000, UL) +#define VMALLOC_SIZE_TB _AC(32, UL) +#define __VMALLOC_BASE _AC(0xffffc90000000000, UL) +#define __VMEMMAP_BASE _AC(0xffffea0000000000, UL) +#ifdef CONFIG_RANDOMIZE_MEMORY +#define VMALLOC_START vmalloc_base +#define VMEMMAP_START vmemmap_base +#else +#define VMALLOC_START __VMALLOC_BASE +#define VMEMMAP_START __VMEMMAP_BASE +#endif /* CONFIG_RANDOMIZE_MEMORY */ +#define VMALLOC_END (VMALLOC_START + _AC((VMALLOC_SIZE_TB << 40) - 1, UL))#define MODULES_VADDR (__START_KERNEL_map + KERNEL_IMAGE_SIZE)#define MODULES_END _AC(0xffffffffff000000, UL)#define MODULES_LEN (MODULES_END - MODULES_VADDR)
arch/x86/kernel/head_64.S +1 -1
@@ -38,7 +38,7 @@ #define pud_index(x) (((x) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) -L4_PAGE_OFFSET = pgd_index(__PAGE_OFFSET) +L4_PAGE_OFFSET = pgd_index(__PAGE_OFFSET_BASE) L4_START_KERNEL = pgd_index(__START_KERNEL_map) L3_START_KERNEL = pud_index(__START_KERNEL_map)
arch/x86/kernel/setup.c +3 -0
@@ -113,6 +113,7 @@#include <asm/prom.h> #include <asm/microcode.h> #include <asm/mmu_context.h> +#include <asm/kaslr.h> /* * max_low_pfn_mapped: highest direct mapped pfn under 4GB
@@ -942,6 +943,8 @@ void __init setup_arch(char **cmdline_p) x86_init.oem.arch_setup (); +kernel_randomize_memory (); + iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) -1 ;setup_memory_map ();parse_setup_data ();
arch/x86/mm/Makefile +1 -0
@@ -37,4 +37,5 @@ obj-$(CONFIG_NUMA_EMU) += numa_emulation.o obj-$(CONFIG_X86_INTEL_MPX) += mpx.o obj-$(CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) += pkeys.o +obj-$(CONFIG_RANDOMIZE_MEMORY) += kaslr.o
arch/x86/mm/dump_pagetables.c +8 -3
@@ -72,9 +72,9 @@ static struct addr_marker address_markers[] = { { 0, "User Space" }, #ifdef CONFIG_X86_64 { 0x8000000000000000UL, "Kernel Space" }, - { PAGE_OFFSET, "Low Kernel Mapping" }, - { VMALLOC_START, "vmalloc() Area" }, - { VMEMMAP_START, "Vmemmap" }, + { 0/* PAGE_OFFSET */, "Low Kernel Mapping" }, + { 0/* VMALLOC_START */, "vmalloc() Area" }, + { 0/* VMEMMAP_START */, "Vmemmap" }, # ifdef CONFIG_X86_ESPFIX64 { ESPFIX_BASE_ADDR, "ESPfix Area", 16 }, # endif
@@ -434,6 +434,11 @@ void ptdump_walk_pgd_level_checkwx(void)static int __init pt_dump_init (void ) { +#ifdef CONFIG_X86_64 + address_markers[LOW_KERNEL_NR ].start_address =PAGE_OFFSET ; + address_markers[VMALLOC_START_NR ].start_address =VMALLOC_START ; + address_markers[VMEMMAP_START_NR ].start_address =VMEMMAP_START ; +#endif #ifdef CONFIG_X86_32 /* Not a compile-time constant on x86-32 */ address_markers[VMALLOC_START_NR ].start_address =VMALLOC_START ;
arch/x86/mm/init.c +4 -0
@@ -17,6 +17,7 @@#include <asm/proto.h> #include <asm/dma.h> /* for MAX_DMA_PFN */ #include <asm/microcode.h> +#include <asm/kaslr.h> /* * We need to define the tracepoints somewhere, and tlb.c
@@ -590,6 +591,9 @@ void __init init_mem_mapping(void)/* the ISA range is always mapped regardless of memory holes */ init_memory_mapping (0 ,ISA_END_ADDRESS ); +/* Init the trampoline page table if needed for KASLR memory */ +kaslr_trampoline_init (); +/* * If the allocation is in bottom-up direction, we setup direct mapping * in bottom-up, otherwise we setup direct mapping in top-down.
arch/x86/mm/kaslr.c new file +136 -0
136 lines not on this page · raw message
arch/x86/realmode/init.c +4 -0
@@ -84,7 +84,11 @@ void __init setup_real_mode(void) *trampoline_cr4_features =__read_cr4 (); trampoline_pgd = (u64 *)__va (real_mode_header->trampoline_pgd); +#ifdef CONFIG_RANDOMIZE_MEMORY + trampoline_pgd[0 ] = trampoline_pgd_entry.pgd; +#else trampoline_pgd[0 ] = init_level4_pgt[pgd_index (__PAGE_OFFSET)].pgd; +#endif trampoline_pgd[511 ] = init_level4_pgt[511 ].pgd;#endif }
Signature · 1 line
2.8.0.rc3.226.g39d4020
Dave Hansen
maintainerRe: [PATCH v2 3/4] x86, boot: Implement ASLR for kernel memory sections (x86_64)
arch/x86/include/asm/page_64_types.h line 44
Quoted 7 lines · Thomas Garnier
arch/x86/include/asm/page_64_types.h +6
-1-#define __PAGE_OFFSET _AC(0xffff880000000000, UL) +#define __PAGE_OFFSET_BASE _AC(0xffff880000000000, UL) +#ifdef CONFIG_RANDOMIZE_MEMORY +#define __PAGE_OFFSET page_offset_base +#else +#define __PAGE_OFFSET __PAGE_OFFSET_BASE +#endif /* CONFIG_RANDOMIZE_MEMORY */
Do you have any data about the performance impact of this change? It's not necessary to have it to merge something like this, I'm just curious how bad it is.
Re: [PATCH v2 3/4] x86, boot: Implement ASLR for kernel memory sections (x86_64)
I don't see much difference. I will update the commits on next iteration with the following:
Kernbench shows almost no difference (-+ less than 1%):
Before:
Average Optimal load -j 12 Run (std deviation):
Elapsed Time 102.63 (1.2695)
User Time 1034.89 (1.18115)
System Time 87.056 (0.456416)
Percent CPU 1092.9 (13.892)
Context Switches 199805 (3455.33)
Sleeps 97907.8 (900.636)
After:
Average Optimal load -j 12 Run (std deviation):
Elapsed Time 102.489 (1.10636)
User Time 1034.86 (1.36053)
System Time 87.764 (0.49345)
Percent CPU 1095 (12.7715)
Context Switches 199036 (4298.1)
Sleeps 97681.6 (1031.11)
Hackbench shows 0% difference on average (hackbench 90 repeated 10 times)
attemp,before,after 1,0.076,0.069 2,0.072,0.069 3,0.066,0.066 4,0.066,0.068 5,0.066,0.067 6,0.066,0.069 7,0.067,0.066 8,0.063,0.067 9,0.067,0.065 10,0.068,0.071 average,0.0677,0.0677
Thanks,
Thomas
Quoted 12 lines · Dave Hansen
arch/x86/include/asm/page_64_types.h line 44
Quoted 7 lines · Thomas Garnier
arch/x86/include/asm/page_64_types.h +6
-1-#define __PAGE_OFFSET _AC(0xffff880000000000, UL) +#define __PAGE_OFFSET_BASE _AC(0xffff880000000000, UL) +#ifdef CONFIG_RANDOMIZE_MEMORY +#define __PAGE_OFFSET page_offset_base +#else +#define __PAGE_OFFSET __PAGE_OFFSET_BASE +#endif /* CONFIG_RANDOMIZE_MEMORY */ Do you have any data about the performance impact of this change? It's not necessary to have it to merge something like this, I'm just curious how bad it is.
PATCH v2 4/4 x86, boot: Memory hotplug support for KASLR memory randomization
In reply to Thomas GarnierAdd a new option (CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING) to define the padding used for the physical memory mapping section when KASLR memory is enabled. It ensures there is enough virtual address space when CONFIG_MEMORY_HOTPLUG is used. The default value is 10 terabytes. If CONFIG_MEMORY_HOTPLUG is not used, no space is reserved increasing the entropy available.
---
Based on next-20160502
--- arch/x86/Kconfig | 15 +++++++++++++++ arch/x86/mm/kaslr.c | 14 ++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-)
arch/x86/Kconfig +15 -0
@@ -2003,6 +2003,21 @@ config RANDOMIZE_MEMORY If unsure, say N. +config RANDOMIZE_MEMORY_PHYSICAL_PADDING + hex "Physical memory mapping padding" if EXPERT + depends on RANDOMIZE_MEMORY + default "0xa" if MEMORY_HOTPLUG + default "0x0" + range 0x1 0x40 if MEMORY_HOTPLUG + range 0x0 0x40 + ---help--- + Define the padding in terabyte added to the existing physical memory + size during kernel memory randomization. It is useful for memory + hotplug support but reduces the entropy available for address + randomization. + + If unsure, leave at the default value. + config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" depends on SMP
arch/x86/mm/kaslr.c +12 -2
@@ -68,15 +68,25 @@ void __init kernel_randomize_memory(void) {size_t i;unsigned long addr = memory_rand_start; -unsigned long padding, rand, mem_tb; +unsigned long padding, rand, mem_tb, page_offset_padding;struct rnd_state rnd_st;unsigned long remain_padding = memory_rand_end - memory_rand_start;if (!kaslr_enabled ())return ; +/* +* Update Physical memory mapping to available and +* add padding if needed (especially for memory hotplug support). +*/ + page_offset_padding =CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING ; + +#ifdef CONFIG_MEMORY_HOTPLUG + page_offset_padding =max (1UL , page_offset_padding); +#endif +BUG_ON (kaslr_regions[0 ].base != &page_offset_base); - mem_tb = ((max_pfn <<PAGE_SHIFT ) >>TB_SHIFT ); + mem_tb = ((max_pfn <<PAGE_SHIFT ) >>TB_SHIFT ) + page_offset_padding;if (mem_tb < kaslr_regions[0 ].size_tb) kaslr_regions[0 ].size_tb = mem_tb;
Signature · 1 line
2.8.0.rc3.226.g39d4020