From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 09:52:40
This series implements KASLR for powerpc/fsl_booke/32, as a security
feature that deters exploit attempts relying on knowledge of the location
of kernel internals.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate. Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
Entropy is derived from the banner and timer base, which will change every
build and boot. This not so much safe so additionally the bootloader may
pass entropy via the /chosen/kaslr-seed node in device tree.
We will use the first 512M of the low memory to randomize the kernel
image. The memory will be split in 64M zones. We will use the lower 8
bit of the entropy to decide the index of the 64M zone. Then we chose a
16K aligned offset inside the 64M zone to put the kernel in.
KERNELBASE
|--> 64M <--|
| |
+---------------+ +----------------+---------------+
| |....| |kernel| | |
+---------------+ +----------------+---------------+
| |
|-----> offset <-----|
kernstart_virt_addr
We also check if we will overlap with some areas like the dtb area, the
initrd area or the crashkernel area. If we cannot find a proper area,
kaslr will be disabled and boot from the original kernel.
Changes since v5:
- Rename M_IF_NEEDED to MAS2_M_IF_NEEDED
- Define some global variable as __ro_after_init
- Replace kimage_vaddr with kernstart_virt_addr
- Depend on RELOCATABLE, not select it
- Modify the comment block below the SPDX tag
- Remove some useless headers in kaslr_booke.c and move is_second_reloc
declarationto mmu_decl.h
- Remove DBG() and use pr_debug() and rewrite comment above get_boot_seed().
- Add a patch to document the KASLR implementation.
- Split a patch from patch #10 which exports kaslr offset in VMCOREINFO ELF notes.
- Remove extra logic around finding nokaslr string in cmdline.
- Make regions static global and __initdata
Changes since v4:
- Add Reviewed-by tag from Christophe
- Remove an unnecessary cast
- Remove unnecessary parenthesis
- Fix checkpatch warning
Changes since v3:
- Add Reviewed-by and Tested-by tag from Diana
- Change the comment in fsl_booke_entry_mapping.S to be consistent
with the new code.
Changes since v2:
- Remove unnecessary #ifdef
- Use SZ_64M instead of0x4000000
- Call early_init_dt_scan_chosen() to init boot_command_line
- Rename kaslr_second_init() to kaslr_late_init()
Changes since v1:
- Remove some useless 'extern' keyword.
- Replace EXPORT_SYMBOL with EXPORT_SYMBOL_GPL
- Improve some assembly code
- Use memzero_explicit instead of memset
- Use boot_command_line and remove early_command_line
- Do not print kaslr offset if kaslr is disabled
Jason Yan (12):
powerpc: unify definition of M_IF_NEEDED
powerpc: move memstart_addr and kernstart_addr to init-common.c
powerpc: introduce kernstart_virt_addr to store the kernel base
powerpc/fsl_booke/32: introduce create_tlb_entry() helper
powerpc/fsl_booke/32: introduce reloc_kernel_entry() helper
powerpc/fsl_booke/32: implement KASLR infrastructure
powerpc/fsl_booke/32: randomize the kernel image offset
powerpc/fsl_booke/kaslr: clear the original kernel if randomized
powerpc/fsl_booke/kaslr: support nokaslr cmdline parameter
powerpc/fsl_booke/kaslr: dump out kernel offset information on panic
powerpc/fsl_booke/kaslr: export offset in VMCOREINFO ELF notes
powerpc/fsl_booke/32: Document KASLR implementation
Documentation/powerpc/kaslr-booke32.rst | 42 ++
arch/powerpc/Kconfig | 11 +
arch/powerpc/include/asm/nohash/mmu-book3e.h | 10 +
arch/powerpc/include/asm/page.h | 7 +
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/early_32.c | 2 +-
arch/powerpc/kernel/exceptions-64e.S | 12 +-
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 27 +-
arch/powerpc/kernel/head_fsl_booke.S | 55 ++-
arch/powerpc/kernel/kaslr_booke.c | 393 ++++++++++++++++++
arch/powerpc/kernel/machine_kexec.c | 1 +
arch/powerpc/kernel/misc_64.S | 7 +-
arch/powerpc/kernel/setup-common.c | 20 +
arch/powerpc/mm/init-common.c | 7 +
arch/powerpc/mm/init_32.c | 5 -
arch/powerpc/mm/init_64.c | 5 -
arch/powerpc/mm/mmu_decl.h | 11 +
arch/powerpc/mm/nohash/fsl_booke.c | 8 +-
18 files changed, 572 insertions(+), 52 deletions(-)
create mode 100644 Documentation/powerpc/kaslr-booke32.rst
create mode 100644 arch/powerpc/kernel/kaslr_booke.c
--
2.17.2
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 09:52:02
Now the kernel base is a fixed value - KERNELBASE. To support KASLR, we
need a variable to store the kernel base.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Reviewed-by: Christophe Leroy <redacted>
Reviewed-by: Diana Craciun <redacted>
Tested-by: Diana Craciun <redacted>
---
arch/powerpc/include/asm/page.h | 2 ++
arch/powerpc/mm/init-common.c | 2 ++
2 files changed, 4 insertions(+)
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 09:52:05
These two variables are both defined in init_32.c and init_64.c. Move
them to init-common.c and make them __ro_after_init.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Reviewed-by: Christophe Leroy <redacted>
Reviewed-by: Diana Craciun <redacted>
Tested-by: Diana Craciun <redacted>
---
arch/powerpc/mm/init-common.c | 5 +++++
arch/powerpc/mm/init_32.c | 5 -----
arch/powerpc/mm/init_64.c | 5 -----
3 files changed, 5 insertions(+), 10 deletions(-)
@@ -56,11 +56,6 @@phys_addr_ttotal_memory;phys_addr_ttotal_lowmem;-phys_addr_tmemstart_addr=(phys_addr_t)~0ull;-EXPORT_SYMBOL(memstart_addr);-phys_addr_tkernstart_addr;-EXPORT_SYMBOL(kernstart_addr);-#ifdef CONFIG_RELOCATABLE/* Used in __va()/__pa() */longlongvirt_phys_offset;
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 09:52:10
After we have the basic support of relocate the kernel in some
appropriate place, we can start to randomize the offset now.
Entropy is derived from the banner and timer, which will change every
build and boot. This not so much safe so additionally the bootloader may
pass entropy via the /chosen/kaslr-seed node in device tree.
We will use the first 512M of the low memory to randomize the kernel
image. The memory will be split in 64M zones. We will use the lower 8
bit of the entropy to decide the index of the 64M zone. Then we chose a
16K aligned offset inside the 64M zone to put the kernel in.
We also check if we will overlap with some areas like the dtb area, the
initrd area or the crashkernel area. If we cannot find a proper area,
kaslr will be disabled and boot from the original kernel.
Some pieces of code are derived from arch/x86/boot/compressed/kaslr.c or
arch/arm64/kernel/kaslr.c such as rotate_xor(). Credit goes to Kees and
Ard.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Reviewed-by: Diana Craciun <redacted>
Tested-by: Diana Craciun <redacted>
Reviewed-by: Christophe Leroy <redacted>
---
arch/powerpc/kernel/kaslr_booke.c | 317 +++++++++++++++++++++++++++++-
1 file changed, 315 insertions(+), 2 deletions(-)
@@ -12,15 +12,326 @@#include<linux/init.h>#include<linux/delay.h>#include<linux/memblock.h>+#include<linux/libfdt.h>+#include<linux/crash_core.h>#include<asm/pgalloc.h>#include<asm/prom.h>+#include<asm/kdump.h>#include<mm/mmu_decl.h>+#include<generated/compile.h>+#include<generated/utsrelease.h>++structregions{+unsignedlongpa_start;+unsignedlongpa_end;+unsignedlongkernel_size;+unsignedlongdtb_start;+unsignedlongdtb_end;+unsignedlonginitrd_start;+unsignedlonginitrd_end;+unsignedlongcrash_start;+unsignedlongcrash_end;+intreserved_mem;+intreserved_mem_addr_cells;+intreserved_mem_size_cells;+};++/* Simplified build-specific string for starting entropy. */+staticconstcharbuild_str[]=UTS_RELEASE" ("LINUX_COMPILE_BY"@"+LINUX_COMPILE_HOST") ("LINUX_COMPILER") "UTS_VERSION;++structregions__initdataregions;++static__initvoidkaslr_get_cmdline(void*fdt)+{+intnode=fdt_path_offset(fdt,"/chosen");++early_init_dt_scan_chosen(node,"chosen",1,boot_command_line);+}++staticunsignedlong__initrotate_xor(unsignedlonghash,constvoid*area,+size_tsize)+{+size_ti;+constunsignedlong*ptr=area;++for(i=0;i<size/sizeof(hash);i++){+/* Rotate by odd number of bits and XOR. */+hash=(hash<<((sizeof(hash)*8)-7))|(hash>>7);+hash^=ptr[i];+}++returnhash;+}++/* Attempt to create a simple starting entropy. This can make it defferent for+*everybuildbutitisstillnotenough.Strongerentropyshould+*beaddedtomakeitchangeforeveryboot.+*/+staticunsignedlong__initget_boot_seed(void*fdt)+{+unsignedlonghash=0;++hash=rotate_xor(hash,build_str,sizeof(build_str));+hash=rotate_xor(hash,fdt,fdt_totalsize(fdt));++returnhash;+}++static__initu64get_kaslr_seed(void*fdt)+{+intnode,len;+fdt64_t*prop;+u64ret;++node=fdt_path_offset(fdt,"/chosen");+if(node<0)+return0;++prop=fdt_getprop_w(fdt,node,"kaslr-seed",&len);+if(!prop||len!=sizeof(u64))+return0;++ret=fdt64_to_cpu(*prop);+*prop=0;+returnret;+}++static__initboolregions_overlap(u32s1,u32e1,u32s2,u32e2)+{+returne1>=s2&&e2>=s1;+}++static__initbooloverlaps_reserved_region(constvoid*fdt,u32start,+u32end)+{+intsubnode,len,i;+u64base,size;++/* check for overlap with /memreserve/ entries */+for(i=0;i<fdt_num_mem_rsv(fdt);i++){+if(fdt_get_mem_rsv(fdt,i,&base,&size)<0)+continue;+if(regions_overlap(start,end,base,base+size))+returntrue;+}++if(regions.reserved_mem<0)+returnfalse;++/* check for overlap with static reservations in /reserved-memory */+for(subnode=fdt_first_subnode(fdt,regions.reserved_mem);+subnode>=0;+subnode=fdt_next_subnode(fdt,subnode)){+constfdt32_t*reg;+u64rsv_end;++len=0;+reg=fdt_getprop(fdt,subnode,"reg",&len);+while(len>=(regions.reserved_mem_addr_cells++regions.reserved_mem_size_cells)){+base=fdt32_to_cpu(reg[0]);+if(regions.reserved_mem_addr_cells==2)+base=(base<<32)|fdt32_to_cpu(reg[1]);++reg+=regions.reserved_mem_addr_cells;+len-=4*regions.reserved_mem_addr_cells;++size=fdt32_to_cpu(reg[0]);+if(regions.reserved_mem_size_cells==2)+size=(size<<32)|fdt32_to_cpu(reg[1]);++reg+=regions.reserved_mem_size_cells;+len-=4*regions.reserved_mem_size_cells;++if(base>=regions.pa_end)+continue;++rsv_end=min(base+size,(u64)U32_MAX);++if(regions_overlap(start,end,base,rsv_end))+returntrue;+}+}+returnfalse;+}++static__initbooloverlaps_region(constvoid*fdt,u32start,+u32end)+{+if(regions_overlap(start,end,regions.dtb_start,+regions.dtb_end))+returntrue;++if(regions_overlap(start,end,regions.initrd_start,+regions.initrd_end))+returntrue;++if(regions_overlap(start,end,regions.crash_start,+regions.crash_end))+returntrue;++returnoverlaps_reserved_region(fdt,start,end);+}++staticvoid__initget_crash_kernel(void*fdt,unsignedlongsize)+{+#ifdef CONFIG_CRASH_CORE+unsignedlonglongcrash_size,crash_base;+intret;++ret=parse_crashkernel(boot_command_line,size,&crash_size,+&crash_base);+if(ret!=0||crash_size==0)+return;+if(crash_base==0)+crash_base=KDUMP_KERNELBASE;++regions.crash_start=(unsignedlong)crash_base;+regions.crash_end=(unsignedlong)(crash_base+crash_size);++pr_debug("crash_base=0x%llx crash_size=0x%llx\n",crash_base,crash_size);+#endif+}++staticvoid__initget_initrd_range(void*fdt)+{+u64start,end;+intnode,len;+const__be32*prop;++node=fdt_path_offset(fdt,"/chosen");+if(node<0)+return;++prop=fdt_getprop(fdt,node,"linux,initrd-start",&len);+if(!prop)+return;+start=of_read_number(prop,len/4);++prop=fdt_getprop(fdt,node,"linux,initrd-end",&len);+if(!prop)+return;+end=of_read_number(prop,len/4);++regions.initrd_start=(unsignedlong)start;+regions.initrd_end=(unsignedlong)end;++pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n",start,end);+}++static__initunsignedlongget_usable_offset(constvoid*fdt,+unsignedlongstart)+{+unsignedlongpa;+unsignedlongpa_end;++for(pa=start;pa>regions.pa_start;pa-=SZ_16K){+pa_end=pa+regions.kernel_size;+if(overlaps_region(fdt,pa,pa_end))+continue;++returnpa;+}+return0;+}++static__initvoidget_cell_sizes(constvoid*fdt,intnode,int*addr_cells,+int*size_cells)+{+constint*prop;+intlen;++/*+*Retrievethe#address-cellsand#size-cellsproperties+*fromthe'node',orusethedefaultifnotprovided.+*/+*addr_cells=*size_cells=1;++prop=fdt_getprop(fdt,node,"#address-cells",&len);+if(len==4)+*addr_cells=fdt32_to_cpu(*prop);+prop=fdt_getprop(fdt,node,"#size-cells",&len);+if(len==4)+*size_cells=fdt32_to_cpu(*prop);+}staticunsignedlong__initkaslr_choose_location(void*dt_ptr,phys_addr_tsize,unsignedlongkernel_sz){-/* return a fixed offset of 64M for now */-returnSZ_64M;+unsignedlongoffset,random;+unsignedlongram,linear_sz;+unsignedlongkaslr_offset;+u64seed;+unsignedlongindex;++random=get_boot_seed(dt_ptr);++seed=get_tb()<<32;+seed^=get_tb();+random=rotate_xor(random,&seed,sizeof(seed));++/*+*Retrieve(andwipe)theseedfromtheFDT+*/+seed=get_kaslr_seed(dt_ptr);+if(seed)+random=rotate_xor(random,&seed,sizeof(seed));++ram=min_t(phys_addr_t,__max_low_memory,size);+ram=map_mem_in_cams(ram,CONFIG_LOWMEM_CAM_NUM,true);+linear_sz=min_t(unsignedlong,ram,SZ_512M);++/* If the linear size is smaller than 64M, do not randmize */+if(linear_sz<SZ_64M)+return0;++/* check for a reserved-memory node and record its cell sizes */+regions.reserved_mem=fdt_path_offset(dt_ptr,"/reserved-memory");+if(regions.reserved_mem>=0)+get_cell_sizes(dt_ptr,regions.reserved_mem,+®ions.reserved_mem_addr_cells,+®ions.reserved_mem_size_cells);++regions.pa_start=0;+regions.pa_end=linear_sz;+regions.dtb_start=__pa(dt_ptr);+regions.dtb_end=__pa(dt_ptr)+fdt_totalsize(dt_ptr);+regions.kernel_size=kernel_sz;++get_initrd_range(dt_ptr);+get_crash_kernel(dt_ptr,ram);++/*+*Decidewhich64Mwewanttostart+*Onlyusethelow8bitsoftherandomseed+*/+index=random&0xFF;+index%=linear_sz/SZ_64M;++/* Decide offset inside 64M */+if(index==0){+offset=random%(SZ_64M-round_up(kernel_sz,SZ_16K)*2);+offset+=round_up(kernel_sz,SZ_16K);+offset=round_up(offset,SZ_16K);+}else{+offset=random%(SZ_64M-kernel_sz);+offset=round_down(offset,SZ_16K);+}++while(index>=0){+offset=offset+index*SZ_64M;+kaslr_offset=get_usable_offset(dt_ptr,offset);+if(kaslr_offset)+break;+index--;+}++/* Did not find any usable region? Give up randomize */+if(index<0)+kaslr_offset=0;++returnkaslr_offset;}/*
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 09:52:12
When kaslr is enabled, the kernel offset is different for every boot.
This brings some difficult to debug the kernel. Dump out the kernel
offset when panic so that we can easily debug the kernel.
This code is derived from x86/arm64 which has similar functionality.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Reviewed-by: Christophe Leroy <redacted>
Reviewed-by: Diana Craciun <redacted>
Tested-by: Diana Craciun <redacted>
---
arch/powerpc/include/asm/page.h | 5 +++++
arch/powerpc/kernel/setup-common.c | 20 ++++++++++++++++++++
2 files changed, 25 insertions(+)
@@ -715,8 +715,28 @@ static struct notifier_block ppc_panic_block = {.priority=INT_MIN/* may not return; must be done last */};+/*+*Dumpoutkerneloffsetinformationonpanic.+*/+staticintdump_kernel_offset(structnotifier_block*self,unsignedlongv,+void*p)+{+pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n",+kaslr_offset(),KERNELBASE);++return0;+}++staticstructnotifier_blockkernel_offset_notifier={+.notifier_call=dump_kernel_offset+};+void__initsetup_panic(void){+if(IS_ENABLED(CONFIG_RANDOMIZE_BASE)&&kaslr_offset()>0)+atomic_notifier_chain_register(&panic_notifier_list,+&kernel_offset_notifier);+/* PPC64 always does a hard irq disable in its panic handler */if(!IS_ENABLED(CONFIG_PPC64)&&!ppc_md.panic)return;
@@ -0,0 +1,42 @@+.. SPDX-License-Identifier: GPL-2.0++===========================+KASLR for Freescale BookE32+===========================++The word KASLR stands for Kernel Address Space Layout Randomization.++This document tries to explain the implementation of the KASLR for+Freescale BookE32. KASLR is a security feature that deters exploit+attempts relying on knowledge of the location of kernel internals.++Since CONFIG_RELOCATABLE has already supported, what we need to do is+map or copy kernel to a proper place and relocate. Freescale Book-E+parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1+entries are not suitable to map the kernel directly in a randomized+region, so we chose to copy the kernel to a proper place and restart to+relocate.++Entropy is derived from the banner and timer base, which will change every+build and boot. This not so much safe so additionally the bootloader may+pass entropy via the /chosen/kaslr-seed node in device tree.++We will use the first 512M of the low memory to randomize the kernel+image. The memory will be split in 64M zones. We will use the lower 8+bit of the entropy to decide the index of the 64M zone. Then we chose a+16K aligned offset inside the 64M zone to put the kernel in::++ KERNELBASE++ |--> 64M <--|+| |+ +---------------+ +----------------+---------------++| |....| |kernel| | |+ +---------------+ +----------------+---------------++| |+ |-----> offset <-----|++ kernstart_virt_addr++To enable KASLR, set CONFIG_RANDOMIZE_BASE = y. If KASLR is enable and you+want to disable it at runtime, add "nokaslr" to the kernel cmdline.
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 09:52:18
Add a new helper create_tlb_entry() to create a tlb entry by the virtual
and physical address. This is a preparation to support boot kernel at a
randomized address.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Reviewed-by: Christophe Leroy <redacted>
Reviewed-by: Diana Craciun <redacted>
Tested-by: Diana Craciun <redacted>
---
arch/powerpc/kernel/head_fsl_booke.S | 29 ++++++++++++++++++++++++++++
arch/powerpc/mm/mmu_decl.h | 1 +
2 files changed, 30 insertions(+)
@@ -142,6 +142,7 @@ extern unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,externvoidadjust_total_lowmem(void);externintswitch_to_as1(void);externvoidrestore_to_as0(intesel,intoffset,void*dt_ptr,intbootcpu);+voidcreate_tlb_entry(phys_addr_tphys,unsignedlongvirt,intentry);#endifexternvoidloadcam_entry(unsignedintindex);externvoidloadcam_multi(intfirst_idx,intnum,inttmp_idx);
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 09:52:22
One may want to disable kaslr when boot, so provide a cmdline parameter
'nokaslr' to support this.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Reviewed-by: Diana Craciun <redacted>
Tested-by: Diana Craciun <redacted>
Reviewed-by: Christophe Leroy <redacted>
---
arch/powerpc/kernel/kaslr_booke.c | 7 +++++++
1 file changed, 7 insertions(+)
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 09:52:27
Add a new helper reloc_kernel_entry() to jump back to the start of the
new kernel. After we put the new kernel in a randomized place we can use
this new helper to enter the kernel and begin to relocate again.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Reviewed-by: Christophe Leroy <redacted>
Reviewed-by: Diana Craciun <redacted>
Tested-by: Diana Craciun <redacted>
---
arch/powerpc/kernel/head_fsl_booke.S | 13 +++++++++++++
arch/powerpc/mm/mmu_decl.h | 1 +
2 files changed, 14 insertions(+)
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 09:52:33
This patch add support to boot kernel from places other than KERNELBASE.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate. Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
The offset of the kernel was not randomized yet(a fixed 64M is set). We
will randomize it in the next patch.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Tested-by: Diana Craciun <redacted>
Reviewed-by: Christophe Leroy <redacted>
---
arch/powerpc/Kconfig | 11 ++++
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/early_32.c | 2 +-
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 17 +++--
arch/powerpc/kernel/head_fsl_booke.S | 13 +++-
arch/powerpc/kernel/kaslr_booke.c | 62 +++++++++++++++++++
arch/powerpc/mm/mmu_decl.h | 7 +++
arch/powerpc/mm/nohash/fsl_booke.c | 7 ++-
8 files changed, 105 insertions(+), 15 deletions(-)
create mode 100644 arch/powerpc/kernel/kaslr_booke.c
@@ -0,0 +1,62 @@+// SPDX-License-Identifier: GPL-2.0-only+//+// Copyright (C) 2019 Jason Yan <yanaijie@huawei.com>++#include<linux/kernel.h>+#include<linux/errno.h>+#include<linux/string.h>+#include<linux/types.h>+#include<linux/mm.h>+#include<linux/swap.h>+#include<linux/stddef.h>+#include<linux/init.h>+#include<linux/delay.h>+#include<linux/memblock.h>+#include<asm/pgalloc.h>+#include<asm/prom.h>+#include<mm/mmu_decl.h>++staticunsignedlong__initkaslr_choose_location(void*dt_ptr,phys_addr_tsize,+unsignedlongkernel_sz)+{+/* return a fixed offset of 64M for now */+returnSZ_64M;+}++/*+*Toseeifweneedtorelocatethekerneltoarandomoffset+*void*dt_ptr-addressofthedevicetree+*phys_addr_tsize-sizeofthefirstmemoryblock+*/+notracevoid__initkaslr_early_init(void*dt_ptr,phys_addr_tsize)+{+unsignedlongtlb_virt;+phys_addr_ttlb_phys;+unsignedlongoffset;+unsignedlongkernel_sz;++kernel_sz=(unsignedlong)_end-KERNELBASE;++offset=kaslr_choose_location(dt_ptr,size,kernel_sz);++if(offset==0)+return;++kernstart_virt_addr+=offset;+kernstart_addr+=offset;++is_second_reloc=1;++if(offset>=SZ_64M){+tlb_virt=round_down(kernstart_virt_addr,SZ_64M);+tlb_phys=round_down(kernstart_addr,SZ_64M);++/* Create kernel map to relocate in */+create_tlb_entry(tlb_phys,tlb_virt,1);+}++/* Copy the kernel to it's new location and run */+memcpy((void*)kernstart_virt_addr,(void*)KERNELBASE,kernel_sz);++reloc_kernel_entry(dt_ptr,kernstart_virt_addr);+}
@@ -316,6 +317,8 @@ notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)/* We should never reach here */panic("Relocation error");}++kaslr_early_init(__va(dt_ptr),size);}#endif#endif
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 09:52:36
M_IF_NEEDED is defined too many times. Move it to a common place and
rename it to MAS2_M_IF_NEEDED which is much readable.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Reviewed-by: Christophe Leroy <redacted>
Reviewed-by: Diana Craciun <redacted>
Tested-by: Diana Craciun <redacted>
---
arch/powerpc/include/asm/nohash/mmu-book3e.h | 10 ++++++++++
arch/powerpc/kernel/exceptions-64e.S | 12 +-----------
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 14 ++------------
arch/powerpc/kernel/misc_64.S | 7 +------
4 files changed, 14 insertions(+), 29 deletions(-)
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-09 10:07:54
Like all other architectures such as x86 or arm64, include KASLR offset
in VMCOREINFO ELF notes to assist in debugging. After this, we can use
crash --kaslr option to parse vmcore generated from a kaslr kernel.
Note: The crash tool needs to support --kaslr too.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
---
arch/powerpc/kernel/machine_kexec.c | 1 +
1 file changed, 1 insertion(+)
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-19 06:28:47
Hi Michael,
Is there anything more I should do to get this feature meeting the
requirements of the mainline?
Thanks,
Jason
On 2019/8/9 18:07, Jason Yan wrote:
This series implements KASLR for powerpc/fsl_booke/32, as a security
feature that deters exploit attempts relying on knowledge of the location
of kernel internals.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate. Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
Entropy is derived from the banner and timer base, which will change every
build and boot. This not so much safe so additionally the bootloader may
pass entropy via the /chosen/kaslr-seed node in device tree.
We will use the first 512M of the low memory to randomize the kernel
image. The memory will be split in 64M zones. We will use the lower 8
bit of the entropy to decide the index of the 64M zone. Then we chose a
16K aligned offset inside the 64M zone to put the kernel in.
KERNELBASE
|--> 64M <--|
| |
+---------------+ +----------------+---------------+
| |....| |kernel| | |
+---------------+ +----------------+---------------+
| |
|-----> offset <-----|
kernstart_virt_addr
We also check if we will overlap with some areas like the dtb area, the
initrd area or the crashkernel area. If we cannot find a proper area,
kaslr will be disabled and boot from the original kernel.
Changes since v5:
- Rename M_IF_NEEDED to MAS2_M_IF_NEEDED
- Define some global variable as __ro_after_init
- Replace kimage_vaddr with kernstart_virt_addr
- Depend on RELOCATABLE, not select it
- Modify the comment block below the SPDX tag
- Remove some useless headers in kaslr_booke.c and move is_second_reloc
declarationto mmu_decl.h
- Remove DBG() and use pr_debug() and rewrite comment above get_boot_seed().
- Add a patch to document the KASLR implementation.
- Split a patch from patch #10 which exports kaslr offset in VMCOREINFO ELF notes.
- Remove extra logic around finding nokaslr string in cmdline.
- Make regions static global and __initdata
Changes since v4:
- Add Reviewed-by tag from Christophe
- Remove an unnecessary cast
- Remove unnecessary parenthesis
- Fix checkpatch warning
Changes since v3:
- Add Reviewed-by and Tested-by tag from Diana
- Change the comment in fsl_booke_entry_mapping.S to be consistent
with the new code.
Changes since v2:
- Remove unnecessary #ifdef
- Use SZ_64M instead of0x4000000
- Call early_init_dt_scan_chosen() to init boot_command_line
- Rename kaslr_second_init() to kaslr_late_init()
Changes since v1:
- Remove some useless 'extern' keyword.
- Replace EXPORT_SYMBOL with EXPORT_SYMBOL_GPL
- Improve some assembly code
- Use memzero_explicit instead of memset
- Use boot_command_line and remove early_command_line
- Do not print kaslr offset if kaslr is disabled
Jason Yan (12):
powerpc: unify definition of M_IF_NEEDED
powerpc: move memstart_addr and kernstart_addr to init-common.c
powerpc: introduce kernstart_virt_addr to store the kernel base
powerpc/fsl_booke/32: introduce create_tlb_entry() helper
powerpc/fsl_booke/32: introduce reloc_kernel_entry() helper
powerpc/fsl_booke/32: implement KASLR infrastructure
powerpc/fsl_booke/32: randomize the kernel image offset
powerpc/fsl_booke/kaslr: clear the original kernel if randomized
powerpc/fsl_booke/kaslr: support nokaslr cmdline parameter
powerpc/fsl_booke/kaslr: dump out kernel offset information on panic
powerpc/fsl_booke/kaslr: export offset in VMCOREINFO ELF notes
powerpc/fsl_booke/32: Document KASLR implementation
Documentation/powerpc/kaslr-booke32.rst | 42 ++
arch/powerpc/Kconfig | 11 +
arch/powerpc/include/asm/nohash/mmu-book3e.h | 10 +
arch/powerpc/include/asm/page.h | 7 +
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/early_32.c | 2 +-
arch/powerpc/kernel/exceptions-64e.S | 12 +-
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 27 +-
arch/powerpc/kernel/head_fsl_booke.S | 55 ++-
arch/powerpc/kernel/kaslr_booke.c | 393 ++++++++++++++++++
arch/powerpc/kernel/machine_kexec.c | 1 +
arch/powerpc/kernel/misc_64.S | 7 +-
arch/powerpc/kernel/setup-common.c | 20 +
arch/powerpc/mm/init-common.c | 7 +
arch/powerpc/mm/init_32.c | 5 -
arch/powerpc/mm/init_64.c | 5 -
arch/powerpc/mm/mmu_decl.h | 11 +
arch/powerpc/mm/nohash/fsl_booke.c | 8 +-
18 files changed, 572 insertions(+), 52 deletions(-)
create mode 100644 Documentation/powerpc/kaslr-booke32.rst
create mode 100644 arch/powerpc/kernel/kaslr_booke.c
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-27 00:39:53
A polite ping :)
What else should I do now?
Thanks
On 2019/8/19 14:12, Jason Yan wrote:
Hi Michael,
Is there anything more I should do to get this feature meeting the
requirements of the mainline?
Thanks,
Jason
On 2019/8/9 18:07, Jason Yan wrote:
quoted
This series implements KASLR for powerpc/fsl_booke/32, as a security
feature that deters exploit attempts relying on knowledge of the location
of kernel internals.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate. Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
Entropy is derived from the banner and timer base, which will change
every
build and boot. This not so much safe so additionally the bootloader may
pass entropy via the /chosen/kaslr-seed node in device tree.
We will use the first 512M of the low memory to randomize the kernel
image. The memory will be split in 64M zones. We will use the lower 8
bit of the entropy to decide the index of the 64M zone. Then we chose a
16K aligned offset inside the 64M zone to put the kernel in.
KERNELBASE
|--> 64M <--|
| |
+---------------+ +----------------+---------------+
| |....| |kernel| | |
+---------------+ +----------------+---------------+
| |
|-----> offset <-----|
kernstart_virt_addr
We also check if we will overlap with some areas like the dtb area, the
initrd area or the crashkernel area. If we cannot find a proper area,
kaslr will be disabled and boot from the original kernel.
Changes since v5:
- Rename M_IF_NEEDED to MAS2_M_IF_NEEDED
- Define some global variable as __ro_after_init
- Replace kimage_vaddr with kernstart_virt_addr
- Depend on RELOCATABLE, not select it
- Modify the comment block below the SPDX tag
- Remove some useless headers in kaslr_booke.c and move is_second_reloc
declarationto mmu_decl.h
- Remove DBG() and use pr_debug() and rewrite comment above
get_boot_seed().
- Add a patch to document the KASLR implementation.
- Split a patch from patch #10 which exports kaslr offset in
VMCOREINFO ELF notes.
- Remove extra logic around finding nokaslr string in cmdline.
- Make regions static global and __initdata
Changes since v4:
- Add Reviewed-by tag from Christophe
- Remove an unnecessary cast
- Remove unnecessary parenthesis
- Fix checkpatch warning
Changes since v3:
- Add Reviewed-by and Tested-by tag from Diana
- Change the comment in fsl_booke_entry_mapping.S to be consistent
with the new code.
Changes since v2:
- Remove unnecessary #ifdef
- Use SZ_64M instead of0x4000000
- Call early_init_dt_scan_chosen() to init boot_command_line
- Rename kaslr_second_init() to kaslr_late_init()
Changes since v1:
- Remove some useless 'extern' keyword.
- Replace EXPORT_SYMBOL with EXPORT_SYMBOL_GPL
- Improve some assembly code
- Use memzero_explicit instead of memset
- Use boot_command_line and remove early_command_line
- Do not print kaslr offset if kaslr is disabled
Jason Yan (12):
powerpc: unify definition of M_IF_NEEDED
powerpc: move memstart_addr and kernstart_addr to init-common.c
powerpc: introduce kernstart_virt_addr to store the kernel base
powerpc/fsl_booke/32: introduce create_tlb_entry() helper
powerpc/fsl_booke/32: introduce reloc_kernel_entry() helper
powerpc/fsl_booke/32: implement KASLR infrastructure
powerpc/fsl_booke/32: randomize the kernel image offset
powerpc/fsl_booke/kaslr: clear the original kernel if randomized
powerpc/fsl_booke/kaslr: support nokaslr cmdline parameter
powerpc/fsl_booke/kaslr: dump out kernel offset information on panic
powerpc/fsl_booke/kaslr: export offset in VMCOREINFO ELF notes
powerpc/fsl_booke/32: Document KASLR implementation
Documentation/powerpc/kaslr-booke32.rst | 42 ++
arch/powerpc/Kconfig | 11 +
arch/powerpc/include/asm/nohash/mmu-book3e.h | 10 +
arch/powerpc/include/asm/page.h | 7 +
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/early_32.c | 2 +-
arch/powerpc/kernel/exceptions-64e.S | 12 +-
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 27 +-
arch/powerpc/kernel/head_fsl_booke.S | 55 ++-
arch/powerpc/kernel/kaslr_booke.c | 393 ++++++++++++++++++
arch/powerpc/kernel/machine_kexec.c | 1 +
arch/powerpc/kernel/misc_64.S | 7 +-
arch/powerpc/kernel/setup-common.c | 20 +
arch/powerpc/mm/init-common.c | 7 +
arch/powerpc/mm/init_32.c | 5 -
arch/powerpc/mm/init_64.c | 5 -
arch/powerpc/mm/mmu_decl.h | 11 +
arch/powerpc/mm/nohash/fsl_booke.c | 8 +-
18 files changed, 572 insertions(+), 52 deletions(-)
create mode 100644 Documentation/powerpc/kaslr-booke32.rst
create mode 100644 arch/powerpc/kernel/kaslr_booke.c
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2019-08-27 01:33:58
Jason Yan [off-list ref] writes:
A polite ping :)
What else should I do now?
That's a good question.
Scott, are you still maintaining FSL bits, and if so any comments? Or
should I take this.
cheers
On 2019/8/19 14:12, Jason Yan wrote:
quoted
Hi Michael,
Is there anything more I should do to get this feature meeting the
requirements of the mainline?
Thanks,
Jason
On 2019/8/9 18:07, Jason Yan wrote:
quoted
This series implements KASLR for powerpc/fsl_booke/32, as a security
feature that deters exploit attempts relying on knowledge of the location
of kernel internals.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate. Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
Entropy is derived from the banner and timer base, which will change
every
build and boot. This not so much safe so additionally the bootloader may
pass entropy via the /chosen/kaslr-seed node in device tree.
We will use the first 512M of the low memory to randomize the kernel
image. The memory will be split in 64M zones. We will use the lower 8
bit of the entropy to decide the index of the 64M zone. Then we chose a
16K aligned offset inside the 64M zone to put the kernel in.
KERNELBASE
|--> 64M <--|
| |
+---------------+ +----------------+---------------+
| |....| |kernel| | |
+---------------+ +----------------+---------------+
| |
|-----> offset <-----|
kernstart_virt_addr
We also check if we will overlap with some areas like the dtb area, the
initrd area or the crashkernel area. If we cannot find a proper area,
kaslr will be disabled and boot from the original kernel.
Changes since v5:
- Rename M_IF_NEEDED to MAS2_M_IF_NEEDED
- Define some global variable as __ro_after_init
- Replace kimage_vaddr with kernstart_virt_addr
- Depend on RELOCATABLE, not select it
- Modify the comment block below the SPDX tag
- Remove some useless headers in kaslr_booke.c and move is_second_reloc
declarationto mmu_decl.h
- Remove DBG() and use pr_debug() and rewrite comment above
get_boot_seed().
- Add a patch to document the KASLR implementation.
- Split a patch from patch #10 which exports kaslr offset in
VMCOREINFO ELF notes.
- Remove extra logic around finding nokaslr string in cmdline.
- Make regions static global and __initdata
Changes since v4:
- Add Reviewed-by tag from Christophe
- Remove an unnecessary cast
- Remove unnecessary parenthesis
- Fix checkpatch warning
Changes since v3:
- Add Reviewed-by and Tested-by tag from Diana
- Change the comment in fsl_booke_entry_mapping.S to be consistent
with the new code.
Changes since v2:
- Remove unnecessary #ifdef
- Use SZ_64M instead of0x4000000
- Call early_init_dt_scan_chosen() to init boot_command_line
- Rename kaslr_second_init() to kaslr_late_init()
Changes since v1:
- Remove some useless 'extern' keyword.
- Replace EXPORT_SYMBOL with EXPORT_SYMBOL_GPL
- Improve some assembly code
- Use memzero_explicit instead of memset
- Use boot_command_line and remove early_command_line
- Do not print kaslr offset if kaslr is disabled
Jason Yan (12):
powerpc: unify definition of M_IF_NEEDED
powerpc: move memstart_addr and kernstart_addr to init-common.c
powerpc: introduce kernstart_virt_addr to store the kernel base
powerpc/fsl_booke/32: introduce create_tlb_entry() helper
powerpc/fsl_booke/32: introduce reloc_kernel_entry() helper
powerpc/fsl_booke/32: implement KASLR infrastructure
powerpc/fsl_booke/32: randomize the kernel image offset
powerpc/fsl_booke/kaslr: clear the original kernel if randomized
powerpc/fsl_booke/kaslr: support nokaslr cmdline parameter
powerpc/fsl_booke/kaslr: dump out kernel offset information on panic
powerpc/fsl_booke/kaslr: export offset in VMCOREINFO ELF notes
powerpc/fsl_booke/32: Document KASLR implementation
Documentation/powerpc/kaslr-booke32.rst | 42 ++
arch/powerpc/Kconfig | 11 +
arch/powerpc/include/asm/nohash/mmu-book3e.h | 10 +
arch/powerpc/include/asm/page.h | 7 +
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/early_32.c | 2 +-
arch/powerpc/kernel/exceptions-64e.S | 12 +-
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 27 +-
arch/powerpc/kernel/head_fsl_booke.S | 55 ++-
arch/powerpc/kernel/kaslr_booke.c | 393 ++++++++++++++++++
arch/powerpc/kernel/machine_kexec.c | 1 +
arch/powerpc/kernel/misc_64.S | 7 +-
arch/powerpc/kernel/setup-common.c | 20 +
arch/powerpc/mm/init-common.c | 7 +
arch/powerpc/mm/init_32.c | 5 -
arch/powerpc/mm/init_64.c | 5 -
arch/powerpc/mm/mmu_decl.h | 11 +
arch/powerpc/mm/nohash/fsl_booke.c | 8 +-
18 files changed, 572 insertions(+), 52 deletions(-)
create mode 100644 Documentation/powerpc/kaslr-booke32.rst
create mode 100644 arch/powerpc/kernel/kaslr_booke.c
From: Scott Wood <oss@buserror.net> Date: 2019-08-27 23:05:20
On Fri, Aug 09, 2019 at 06:07:52PM +0800, Jason Yan wrote:
quoted hunk
Add a new helper create_tlb_entry() to create a tlb entry by the virtual
and physical address. This is a preparation to support boot kernel at a
randomized address.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Reviewed-by: Christophe Leroy <redacted>
Reviewed-by: Diana Craciun <redacted>
Tested-by: Diana Craciun <redacted>
---
arch/powerpc/kernel/head_fsl_booke.S | 29 ++++++++++++++++++++++++++++
arch/powerpc/mm/mmu_decl.h | 1 +
2 files changed, 30 insertions(+)
Should set MAS7 under MMU_FTR_BIG_PHYS (or CONFIG_PHYS_64BIT if it's
too early for features) -- even if relocatable kernels over 4GiB aren't
supported (I don't remember if they work or not), MAS7 might be non-zero
on entry. And the function claims to take a 64-bit phys addr as input...
MAS2_M should be MAS2_M_IF_NEEDED to match other kmem tlb entries.
-Scott
From: Scott Wood <oss@buserror.net> Date: 2019-08-28 04:12:24
On Fri, 2019-08-09 at 18:07 +0800, Jason Yan wrote:
This series implements KASLR for powerpc/fsl_booke/32, as a security
feature that deters exploit attempts relying on knowledge of the location
of kernel internals.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate.
Have you tested this with a kernel that was loaded at a non-zero address? I
tried loading a kernel at 0x04000000 (by changing the address in the uImage,
and setting bootm_low to 04000000 in U-Boot), and it works without
CONFIG_RANDOMIZE and fails with.
Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
Entropy is derived from the banner and timer base, which will change every
build and boot. This not so much safe so additionally the bootloader may
pass entropy via the /chosen/kaslr-seed node in device tree.
How complicated would it be to directly access the HW RNG (if present) that
early in the boot? It'd be nice if a U-Boot update weren't required (and
particularly concerning that KASLR would appear to work without a U-Boot
update, but without decent entropy).
-Scott
From: Scott Wood <oss@buserror.net> Date: 2019-08-28 04:57:20
On Fri, Aug 09, 2019 at 06:07:54PM +0800, Jason Yan wrote:
quoted hunk
This patch add support to boot kernel from places other than KERNELBASE.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate. Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
The offset of the kernel was not randomized yet(a fixed 64M is set). We
will randomize it in the next patch.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Tested-by: Diana Craciun <redacted>
Reviewed-by: Christophe Leroy <redacted>
---
arch/powerpc/Kconfig | 11 ++++
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/early_32.c | 2 +-
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 17 +++--
arch/powerpc/kernel/head_fsl_booke.S | 13 +++-
arch/powerpc/kernel/kaslr_booke.c | 62 +++++++++++++++++++
arch/powerpc/mm/mmu_decl.h | 7 +++
arch/powerpc/mm/nohash/fsl_booke.c | 7 ++-
8 files changed, 105 insertions(+), 15 deletions(-)
create mode 100644 arch/powerpc/kernel/kaslr_booke.c
@@ -548,6 +548,17 @@ config RELOCATABLEsettingcanstillbeusefultobootwrappersthatneedtoknowtheloadaddressofthekernel(eg.u-boot/mkimage).+configRANDOMIZE_BASE+bool"Randomize the address of the kernel image"+depends on(FSL_BOOKE&&FLATMEM&&PPC32)+depends onRELOCATABLE+help+Randomizesthevirtualaddressatwhichthekernelimageis+loaded,asasecurityfeaturethatdetersexploitattempts+relyingonknowledgeofthelocationofkernelinternals.++Ifunsure,sayN.+
Why is N the safe default (other than concerns about code maturity,
though arm64 and mips don't seem to have updated this recommendation
after several years)? On x86 this defaults to Y.
+/*
+ * To see if we need to relocate the kernel to a random offset
+ * void *dt_ptr - address of the device tree
+ * phys_addr_t size - size of the first memory block
+ */
+notrace void __init kaslr_early_init(void *dt_ptr, phys_addr_t size)
+{
+ unsigned long tlb_virt;
+ phys_addr_t tlb_phys;
+ unsigned long offset;
+ unsigned long kernel_sz;
+
+ kernel_sz = (unsigned long)_end - KERNELBASE;
@@ -316,6 +317,8 @@ notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)/* We should never reach here */panic("Relocation error");}++kaslr_early_init(__va(dt_ptr),size);
Are you assuming that available memory starts at physical address zero?
This isn't true of some partitioning scenarios, or in a kdump crash
kernel.
-Scott
From: Scott Wood <oss@buserror.net> Date: 2019-08-28 05:00:11
On Tue, 2019-08-27 at 23:05 -0500, Scott Wood wrote:
On Fri, 2019-08-09 at 18:07 +0800, Jason Yan wrote:
quoted
Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
Entropy is derived from the banner and timer base, which will change every
build and boot. This not so much safe so additionally the bootloader may
pass entropy via the /chosen/kaslr-seed node in device tree.
How complicated would it be to directly access the HW RNG (if present) that
early in the boot? It'd be nice if a U-Boot update weren't required (and
particularly concerning that KASLR would appear to work without a U-Boot
update, but without decent entropy).
OK, I see that kaslr-seed is used on some other platforms, though arm64 aborts
KASLR if it doesn't get a seed. I'm not sure if that's better than a loud
warning message (or if it was a conscious choice rather than just not having
an alternative implemented), but silently using poor entropy for something
like this seems bad.
-Scott
From: Scott Wood <oss@buserror.net> Date: 2019-08-28 05:08:43
On Tue, 2019-08-27 at 11:33 +1000, Michael Ellerman wrote:
Jason Yan [off-list ref] writes:
quoted
A polite ping :)
What else should I do now?
That's a good question.
Scott, are you still maintaining FSL bits,
Sort of... now that it's become very low volume, it's easy to forget when
something does show up (or miss it if I'm not CCed). It'd probably help if I
were to just ack patches instead of thinking "I'll do a pull request for this
later" when it's just one or two patches per cycle.
-Scott
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-28 05:34:11
Hi Scott,
Thanks for your reply.
On 2019/8/28 6:07, Scott Wood wrote:
On Fri, Aug 09, 2019 at 06:07:52PM +0800, Jason Yan wrote:
quoted
Add a new helper create_tlb_entry() to create a tlb entry by the virtual
and physical address. This is a preparation to support boot kernel at a
randomized address.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Reviewed-by: Christophe Leroy <redacted>
Reviewed-by: Diana Craciun <redacted>
Tested-by: Diana Craciun <redacted>
---
arch/powerpc/kernel/head_fsl_booke.S | 29 ++++++++++++++++++++++++++++
arch/powerpc/mm/mmu_decl.h | 1 +
2 files changed, 30 insertions(+)
Should set MAS7 under MMU_FTR_BIG_PHYS (or CONFIG_PHYS_64BIT if it's
too early for features) -- even if relocatable kernels over 4GiB aren't
supported (I don't remember if they work or not), MAS7 might be non-zero
on entry. And the function claims to take a 64-bit phys addr as input...
Good catch. And I should consider 32-bit phys addr as input too. I will
fix this in next version. Thanks.
MAS2_M should be MAS2_M_IF_NEEDED to match other kmem tlb entries.
On Fri, Aug 09, 2019 at 06:07:54PM +0800, Jason Yan wrote:
quoted
This patch add support to boot kernel from places other than KERNELBASE.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate. Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
The offset of the kernel was not randomized yet(a fixed 64M is set). We
will randomize it in the next patch.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Tested-by: Diana Craciun <redacted>
Reviewed-by: Christophe Leroy <redacted>
---
arch/powerpc/Kconfig | 11 ++++
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/early_32.c | 2 +-
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 17 +++--
arch/powerpc/kernel/head_fsl_booke.S | 13 +++-
arch/powerpc/kernel/kaslr_booke.c | 62 +++++++++++++++++++
arch/powerpc/mm/mmu_decl.h | 7 +++
arch/powerpc/mm/nohash/fsl_booke.c | 7 ++-
8 files changed, 105 insertions(+), 15 deletions(-)
create mode 100644 arch/powerpc/kernel/kaslr_booke.c
+/*
+ * To see if we need to relocate the kernel to a random offset
+ * void *dt_ptr - address of the device tree
+ * phys_addr_t size - size of the first memory block
+ */
+notrace void __init kaslr_early_init(void *dt_ptr, phys_addr_t size)
+{
+ unsigned long tlb_virt;
+ phys_addr_t tlb_phys;
+ unsigned long offset;
+ unsigned long kernel_sz;
+
+ kernel_sz = (unsigned long)_end - KERNELBASE;
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-28 11:03:26
On 2019/8/28 12:54, Scott Wood wrote:
On Fri, Aug 09, 2019 at 06:07:54PM +0800, Jason Yan wrote:
quoted
This patch add support to boot kernel from places other than KERNELBASE.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate. Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
The offset of the kernel was not randomized yet(a fixed 64M is set). We
will randomize it in the next patch.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Tested-by: Diana Craciun <redacted>
Reviewed-by: Christophe Leroy <redacted>
---
arch/powerpc/Kconfig | 11 ++++
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/early_32.c | 2 +-
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 17 +++--
arch/powerpc/kernel/head_fsl_booke.S | 13 +++-
arch/powerpc/kernel/kaslr_booke.c | 62 +++++++++++++++++++
arch/powerpc/mm/mmu_decl.h | 7 +++
arch/powerpc/mm/nohash/fsl_booke.c | 7 ++-
8 files changed, 105 insertions(+), 15 deletions(-)
create mode 100644 arch/powerpc/kernel/kaslr_booke.c
@@ -548,6 +548,17 @@ config RELOCATABLEsettingcanstillbeusefultobootwrappersthatneedtoknowtheloadaddressofthekernel(eg.u-boot/mkimage).+configRANDOMIZE_BASE+bool"Randomize the address of the kernel image"+depends on(FSL_BOOKE&&FLATMEM&&PPC32)+depends onRELOCATABLE+help+Randomizesthevirtualaddressatwhichthekernelimageis+loaded,asasecurityfeaturethatdetersexploitattempts+relyingonknowledgeofthelocationofkernelinternals.++Ifunsure,sayN.+
Why is N the safe default (other than concerns about code maturity,
though arm64 and mips don't seem to have updated this recommendation
after several years)? On x86 this defaults to Y.
Actually I would like to set this default Y. I was just wondering if
people like this feature or not at the beginning so I had to be more
careful.
+/*
+ * To see if we need to relocate the kernel to a random offset
+ * void *dt_ptr - address of the device tree
+ * phys_addr_t size - size of the first memory block
+ */
+notrace void __init kaslr_early_init(void *dt_ptr, phys_addr_t size)
+{
+ unsigned long tlb_virt;
+ phys_addr_t tlb_phys;
+ unsigned long offset;
+ unsigned long kernel_sz;
+
+ kernel_sz = (unsigned long)_end - KERNELBASE;
Why KERNELBASE and not kernstart_addr?
Did you mean kernstart_virt_addr? It should be kernstart_virt_addr.
@@ -316,6 +317,8 @@ notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)/* We should never reach here */panic("Relocation error");}++kaslr_early_init(__va(dt_ptr),size);
Are you assuming that available memory starts at physical address zero?
This isn't true of some partitioning scenarios, or in a kdump crash
kernel.
I'm not assuming that but I haven't tested that case for now. I will
reconsider and test these scenarios and fix all bugs.
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2019-08-28 13:01:38
Scott Wood [off-list ref] writes:
On Tue, 2019-08-27 at 11:33 +1000, Michael Ellerman wrote:
quoted
Jason Yan [off-list ref] writes:
quoted
A polite ping :)
What else should I do now?
That's a good question.
Scott, are you still maintaining FSL bits,
Sort of... now that it's become very low volume, it's easy to forget when
something does show up (or miss it if I'm not CCed). It'd probably help if I
were to just ack patches instead of thinking "I'll do a pull request for this
later" when it's just one or two patches per cycle.
Yep, understand. Just sending acks is totally fine if you don't have
enough for a pull request.
cheers
From: Scott Wood <oss@buserror.net> Date: 2019-08-28 16:44:57
On Wed, 2019-08-28 at 19:03 +0800, Jason Yan wrote:
On 2019/8/28 12:54, Scott Wood wrote:
quoted
On Fri, Aug 09, 2019 at 06:07:54PM +0800, Jason Yan wrote:
quoted
+/*
+ * To see if we need to relocate the kernel to a random offset
+ * void *dt_ptr - address of the device tree
+ * phys_addr_t size - size of the first memory block
+ */
+notrace void __init kaslr_early_init(void *dt_ptr, phys_addr_t size)
+{
+ unsigned long tlb_virt;
+ phys_addr_t tlb_phys;
+ unsigned long offset;
+ unsigned long kernel_sz;
+
+ kernel_sz = (unsigned long)_end - KERNELBASE;
Why KERNELBASE and not kernstart_addr?
Did you mean kernstart_virt_addr? It should be kernstart_virt_addr.
Yes, kernstart_virt_addr. KERNELBASE will be incorrect if the kernel was
loaded at a nonzero physical address without CONFIG_PHYSICAL_START being
adjusted to match.
-Scott
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-29 01:57:34
On 2019/8/28 12:05, Scott Wood wrote:
On Fri, 2019-08-09 at 18:07 +0800, Jason Yan wrote:
quoted
This series implements KASLR for powerpc/fsl_booke/32, as a security
feature that deters exploit attempts relying on knowledge of the location
of kernel internals.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate.
Have you tested this with a kernel that was loaded at a non-zero address? I
tried loading a kernel at 0x04000000 (by changing the address in the uImage,
and setting bootm_low to 04000000 in U-Boot), and it works without
CONFIG_RANDOMIZE and fails with.
Not yet. I will test this kind of cases in the next days. Thank you so
much. If there are any other corner cases that have to be tested, please
let me know.
quoted
Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
Entropy is derived from the banner and timer base, which will change every
build and boot. This not so much safe so additionally the bootloader may
pass entropy via the /chosen/kaslr-seed node in device tree.
How complicated would it be to directly access the HW RNG (if present) that
early in the boot? It'd be nice if a U-Boot update weren't required (and
particularly concerning that KASLR would appear to work without a U-Boot
update, but without decent entropy).
-Scott
.
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-29 02:41:42
On 2019/8/28 12:59, Scott Wood wrote:
On Tue, 2019-08-27 at 23:05 -0500, Scott Wood wrote:
quoted
On Fri, 2019-08-09 at 18:07 +0800, Jason Yan wrote:
quoted
Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
Entropy is derived from the banner and timer base, which will change every
build and boot. This not so much safe so additionally the bootloader may
pass entropy via the /chosen/kaslr-seed node in device tree.
How complicated would it be to directly access the HW RNG (if present) that
early in the boot? It'd be nice if a U-Boot update weren't required (and
particularly concerning that KASLR would appear to work without a U-Boot
update, but without decent entropy).
OK, I see that kaslr-seed is used on some other platforms, though arm64 aborts
KASLR if it doesn't get a seed. I'm not sure if that's better than a loud
warning message (or if it was a conscious choice rather than just not having
an alternative implemented), but silently using poor entropy for something
like this seems bad.
It can still make the attacker's cost higher with not so good entropy.
The same strategy exists in X86 when X86 KASLR uses RDTSC if without
X86_FEATURE_RDRAND supported. I agree that having a warning message
looks better for reminding people in this situation.
From: Jason Yan <yanaijie@huawei.com> Date: 2019-08-29 06:27:05
On 2019/8/28 13:47, Christophe Leroy wrote:
Le 28/08/2019 à 06:54, Scott Wood a écrit :
quoted
On Fri, Aug 09, 2019 at 06:07:54PM +0800, Jason Yan wrote:
quoted
This patch add support to boot kernel from places other than KERNELBASE.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate. Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
The offset of the kernel was not randomized yet(a fixed 64M is set). We
will randomize it in the next patch.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Cc: Diana Craciun <redacted>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christophe Leroy <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Kees Cook <redacted>
Tested-by: Diana Craciun <redacted>
Reviewed-by: Christophe Leroy <redacted>
---
arch/powerpc/Kconfig | 11 ++++
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/early_32.c | 2 +-
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 17 +++--
arch/powerpc/kernel/head_fsl_booke.S | 13 +++-
arch/powerpc/kernel/kaslr_booke.c | 62 +++++++++++++++++++
arch/powerpc/mm/mmu_decl.h | 7 +++
arch/powerpc/mm/nohash/fsl_booke.c | 7 ++-
8 files changed, 105 insertions(+), 15 deletions(-)
create mode 100644 arch/powerpc/kernel/kaslr_booke.c
[...]
quoted
quoted
diff --git a/arch/powerpc/kernel/kaslr_booke.c
b/arch/powerpc/kernel/kaslr_booke.c
new file mode 100644
index 000000000000..f8dc60534ac1
+/*
+ * To see if we need to relocate the kernel to a random offset
+ * void *dt_ptr - address of the device tree
+ * phys_addr_t size - size of the first memory block
+ */
+notrace void __init kaslr_early_init(void *dt_ptr, phys_addr_t size)
+{
+ unsigned long tlb_virt;
+ phys_addr_t tlb_phys;
+ unsigned long offset;
+ unsigned long kernel_sz;
+
+ kernel_sz = (unsigned long)_end - KERNELBASE;
From: Jason Yan <yanaijie@huawei.com> Date: 2019-09-10 05:35:30
Hi Scott,
On 2019/8/28 12:05, Scott Wood wrote:
On Fri, 2019-08-09 at 18:07 +0800, Jason Yan wrote:
quoted
This series implements KASLR for powerpc/fsl_booke/32, as a security
feature that deters exploit attempts relying on knowledge of the location
of kernel internals.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate.
Have you tested this with a kernel that was loaded at a non-zero address? I
tried loading a kernel at 0x04000000 (by changing the address in the uImage,
and setting bootm_low to 04000000 in U-Boot), and it works without
CONFIG_RANDOMIZE and fails with.
How did you change the load address of the uImage, by changing the
kernel config CONFIG_PHYSICAL_START or the "-a/-e" parameter of mkimage?
I tried both, but it did not work with or without CONFIG_RANDOMIZE.
Thanks,
Jason
quoted
Freescale Book-E
parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
entries are not suitable to map the kernel directly in a randomized
region, so we chose to copy the kernel to a proper place and restart to
relocate.
Entropy is derived from the banner and timer base, which will change every
build and boot. This not so much safe so additionally the bootloader may
pass entropy via the /chosen/kaslr-seed node in device tree.
How complicated would it be to directly access the HW RNG (if present) that
early in the boot? It'd be nice if a U-Boot update weren't required (and
particularly concerning that KASLR would appear to work without a U-Boot
update, but without decent entropy).
-Scott
.
From: Scott Wood <oss@buserror.net> Date: 2019-09-14 14:35:48
On Tue, 2019-09-10 at 13:34 +0800, Jason Yan wrote:
Hi Scott,
On 2019/8/28 12:05, Scott Wood wrote:
quoted
On Fri, 2019-08-09 at 18:07 +0800, Jason Yan wrote:
quoted
This series implements KASLR for powerpc/fsl_booke/32, as a security
feature that deters exploit attempts relying on knowledge of the
location
of kernel internals.
Since CONFIG_RELOCATABLE has already supported, what we need to do is
map or copy kernel to a proper place and relocate.
Have you tested this with a kernel that was loaded at a non-zero
address? I
tried loading a kernel at 0x04000000 (by changing the address in the
uImage,
and setting bootm_low to 04000000 in U-Boot), and it works without
CONFIG_RANDOMIZE and fails with.
How did you change the load address of the uImage, by changing the
kernel config CONFIG_PHYSICAL_START or the "-a/-e" parameter of mkimage?
I tried both, but it did not work with or without CONFIG_RANDOMIZE.
With mkimage. Did you set bootm_low in U-Boot as described above? Was
CONFIG_RELOCATABLE set in the non-CONFIG_RANDOMIZE kernel?
-Scott