* [kernel-hardening] [PATCH 00/30] implement KASLR for ARM
@ 2017-08-14 12:53 Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 01/30] asm-generic: add .data.rel.ro sections to __ro_after_init Ard Biesheuvel
` (30 more replies)
0 siblings, 31 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
This series implements randomization of the placement of the core ARM kernel
inside the lowmem region. It consists of the following parts:
- changes that allow us to build vmlinux as a PIE executable which retains
the metadata required to fix up all absolute symbol references at runtime
- changes that eliminate absolute references from low-level code that may
execute with the MMU off: this removes the need to perform explicit cache
maintenance after the absolute references have been fixed up at runtime with
the caches enabled
- changes to the core kernel startup code to take the physical offset into
account when creating the virtual mapping (the pa-to-va mapping remains
unchanged)
- changes to the decompressor to take the KASLR offset into account when
placing the kernel in physical memory
- changes to the UEFI stub code to choose the KASLR offset and communicate
it to the decompressor
Bootloader changes required for other boot environments are left as an
exercise for the reader.
To test these changes, get a UEFI image for QEMU here [0] and boot a
multi_v7_defconfig+CONFIG_RANDOMIZE_BASE=y build using:
qemu-system-aarch64 -M virt -m 2048 -bios QEMU_EFI.fd -kernel zImage \
-device virtio-rng-pci -net none -nographic -append earlycon
and expect to see something like
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0xf0800000 - 0xff800000 ( 240 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xf0000000 ( 768 MB)
[ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
[ 0.000000] modules : 0xbf800000 - 0xbfe00000 ( 6 MB)
[ 0.000000] .text : 0xd4208000 - 0xd4c00000 (10208 kB) <----
[ 0.000000] .init : 0xd5200000 - 0xd5600000 (4096 kB) <----
[ 0.000000] .data : 0xd5600000 - 0xd5776f28 (1500 kB) <----
[ 0.000000] .bss : 0xd57805e0 - 0xd57e60ac ( 407 kB) <----
[0] https://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-ARM/RELEASE_GCC49/QEMU_EFI.fd
(or update patch #26 to poke a hardcoded value into kaslr_offset directly)
Note that this series partially overlaps with my series 'ARM: add and use
convenience macros for PC relative references', for which I will not send
a follow up. I kept the necessary ones, and dropped some others that are
not actually that useful in the context of KASLR.
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Nicolas Pitre <nico@linaro.org>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Dave Martin <dave.martin@arm.com>
Ard Biesheuvel (30):
asm-generic: add .data.rel.ro sections to __ro_after_init
ARM: assembler: introduce adr_l, ldr_l and str_l macros
ARM: head-common.S: use PC-relative insn sequence for __proc_info
ARM: head-common.S: use PC-relative insn sequence for idmap creation
ARM: head.S: use PC-relative insn sequence for secondary_data
ARM: kernel: use relative references for UP/SMP alternatives
ARM: head: use PC-relative insn sequence for __smp_alt
ARM: sleep.S: use PC-relative insn sequence for
sleep_save_sp/mpidr_hash
ARM: head.S: use PC-relative insn sequences for __fixup_pv_table
ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET
ARM: kvm: replace open coded VA->PA calculations with adr_l call
arm-soc: exynos: replace open coded VA->PA conversions
arm-soc: mvebu: replace open coded VA->PA conversion
arm-soc: various: replace open coded VA->PA calculation of pen_release
ARM: kernel: switch to relative exception tables
ARM: kernel: use relative phys-to-virt patch tables
arm-soc: tegra: make sleep asm code runtime relocatable
ARM: kernel: make vmlinux buildable as a PIE executable
ARM: kernel: use PC-relative symbol references in MMU switch code
ARM: kernel: use PC relative symbol references in suspend/resume code
ARM: mm: export default vmalloc base address
ARM: kernel: refer to swapper_pg_dir via its symbol
ARM: kernel: implement randomization of the kernel load address
ARM: decompressor: explicitly map decompressor binary cacheable
ARM: compressed: factor out zImage header and make it extensible
ARM: decompressor: add KASLR support
efi/libstub: add 'max' parameter to efi_random_alloc()
efi/libstub: check for vmalloc= command line argument
efi/libstub: arm: reserve bootloader supplied initrd in memory map
efi/libstub: arm: implement KASLR
arch/arm/Kconfig | 19 ++
arch/arm/Makefile | 5 +
arch/arm/boot/compressed/head.S | 46 ++---
arch/arm/boot/compressed/vmlinux.lds.S | 5 +-
arch/arm/include/asm/Kbuild | 1 -
arch/arm/include/asm/assembler.h | 86 +++++++-
arch/arm/include/asm/extable.h | 20 ++
arch/arm/include/asm/futex.h | 2 +-
arch/arm/include/asm/memory.h | 6 +-
arch/arm/include/asm/pgtable.h | 1 +
arch/arm/include/asm/processor.h | 2 +-
arch/arm/include/asm/uaccess.h | 8 +-
arch/arm/include/asm/word-at-a-time.h | 2 +-
arch/arm/include/asm/zimage.h | 65 ++++++
arch/arm/kernel/entry-armv.S | 6 +-
arch/arm/kernel/head-common.S | 61 ++----
arch/arm/kernel/head.S | 217 ++++++++++++--------
arch/arm/kernel/hyp-stub.S | 33 ++-
arch/arm/kernel/sleep.S | 27 +--
arch/arm/kernel/swp_emulate.c | 4 +-
arch/arm/kernel/vmlinux.lds.S | 9 +
arch/arm/kvm/init.S | 8 +-
arch/arm/lib/backtrace.S | 8 +-
arch/arm/lib/getuser.S | 22 +-
arch/arm/lib/putuser.S | 12 +-
arch/arm/mach-exynos/headsmp.S | 9 +-
arch/arm/mach-exynos/sleep.S | 26 +--
arch/arm/mach-mvebu/coherency_ll.S | 8 +-
arch/arm/mach-prima2/headsmp.S | 11 +-
arch/arm/mach-spear/headsmp.S | 11 +-
arch/arm/mach-sti/headsmp.S | 10 +-
arch/arm/mach-tegra/sleep-tegra20.S | 22 +-
arch/arm/mach-tegra/sleep-tegra30.S | 6 +-
arch/arm/mach-tegra/sleep.S | 4 +-
arch/arm/mm/alignment.c | 14 +-
arch/arm/mm/extable.c | 2 +-
arch/arm/mm/mmu.c | 3 +-
arch/arm/nwfpe/entry.S | 2 +-
arch/arm/plat-versatile/headsmp.S | 9 +-
drivers/firmware/efi/libstub/arm-stub.c | 51 +++--
drivers/firmware/efi/libstub/arm32-stub.c | 46 ++++-
drivers/firmware/efi/libstub/arm64-stub.c | 2 +-
drivers/firmware/efi/libstub/efi-stub-helper.c | 9 +
drivers/firmware/efi/libstub/efistub.h | 7 +-
drivers/firmware/efi/libstub/fdt.c | 42 ++++
drivers/firmware/efi/libstub/random.c | 10 +-
include/asm-generic/vmlinux.lds.h | 2 +-
include/linux/hidden.h | 21 ++
scripts/sortextable.c | 2 +-
49 files changed, 636 insertions(+), 368 deletions(-)
create mode 100644 arch/arm/include/asm/extable.h
create mode 100644 arch/arm/include/asm/zimage.h
create mode 100644 include/linux/hidden.h
--
2.11.0
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 01/30] asm-generic: add .data.rel.ro sections to __ro_after_init
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 14:26 ` [kernel-hardening] " Arnd Bergmann
2017-08-14 12:53 ` [kernel-hardening] [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros Ard Biesheuvel
` (29 subsequent siblings)
30 siblings, 1 reply; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
When running in PIC mode, the compiler will emit const structures
containing runtime relocatable quantities into .data.rel.ro.* sections,
so that the linker can be smart about placing them together in a segment
that is read-write initially, and is remapped read-only afterwards. This
is exactly what __ro_after_init aims to provide, so move these sections
together.
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
include/asm-generic/vmlinux.lds.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index da0be9a8d1de..d16537b0b102 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -261,7 +261,7 @@
#ifndef RO_AFTER_INIT_DATA
#define RO_AFTER_INIT_DATA \
VMLINUX_SYMBOL(__start_ro_after_init) = .; \
- *(.data..ro_after_init) \
+ *(.data..ro_after_init .data.rel.ro.*) \
VMLINUX_SYMBOL(__end_ro_after_init) = .;
#endif
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 01/30] asm-generic: add .data.rel.ro sections to __ro_after_init Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 15:29 ` [kernel-hardening] " Dave Martin
2017-08-14 15:32 ` Dave Martin
2017-08-14 12:53 ` [kernel-hardening] [PATCH 03/30] ARM: head-common.S: use PC-relative insn sequence for __proc_info Ard Biesheuvel
` (28 subsequent siblings)
30 siblings, 2 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Like arm64, ARM supports position independent code sequences that
produce symbol references with a greater reach than the ordinary
adr/ldr instructions.
Currently, we use open coded instruction sequences involving literals
and arithmetic operations. Instead, we can use movw/movt pairs on v7
CPUs, circumventing the D-cache entirely. For older CPUs, we can emit
the literal into a subsection, allowing it to be emitted out of line
while retaining the ability to perform arithmetic on label offsets.
E.g., on pre-v7 CPUs, we can emit a PC-relative reference as follows:
ldr <reg>, 222f
111: add <reg>, <reg>, pc
.subsection 1
222: .long <sym> - (111b + 8)
.previous
This is allowed by the assembler because, unlike ordinary sections,
subsections are combined into a single section into the object file,
and so the label references are not true cross-section references that
are visible as relocations. Note that we could even do something like
add <reg>, pc, #(222f - 111f) & ~0xfff
ldr <reg>, [<reg>, #(222f - 111f) & 0xfff]
111: add <reg>, <reg>, pc
.subsection 1
222: .long <sym> - (111b + 8)
.previous
if it turns out that the 4 KB range of the ldr instruction is insufficient
to reach the literal in the subsection, although this is currently not a
problem (of the 98 objects built from .S files in a multi_v7_defconfig
build, only 11 have .text sections that are over 1 KB, and the largest one
[entry-armv.o] is 3308 bytes)
Subsections have been available in binutils since 2004 at least, so
they should not cause any issues with older toolchains.
So use the above to implement the macros mov_l, adr_l, adrm_l (using ldm
to load multiple literals at once), ldr_l and str_l, all of which will
use movw/movt pairs on v7 and later CPUs, and use PC-relative literals
otherwise.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/include/asm/assembler.h | 71 ++++++++++++++++++++
1 file changed, 71 insertions(+)
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index ad301f107dd2..516ebaf4ff38 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -518,4 +518,75 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
#endif
.endm
+#ifdef CONFIG_THUMB2_KERNEL
+#define ARM_PC_BIAS 4
+#else
+#define ARM_PC_BIAS 8
+#endif
+
+ .macro __adldst_l, op, reg, sym, tmp, c
+ .if __LINUX_ARM_ARCH__ < 7
+ ldr\c \tmp, 111f
+ .subsection 1
+ .align 2
+111: .long \sym - (222f + ARM_PC_BIAS)
+ .previous
+ .else
+ W(movw\c\()) \tmp, #:lower16:\sym - (222f + ARM_PC_BIAS)
+ W(movt\c\()) \tmp, #:upper16:\sym - (222f + ARM_PC_BIAS)
+ .endif
+222:
+ .ifc \op, add
+ add\c \reg, \tmp, pc
+ .elseif CONFIG_THUMB2_KERNEL == 1
+ add \tmp, \tmp, pc
+ \op\c \reg, [\tmp]
+ .else
+ \op\c \reg, [pc, \tmp]
+ .endif
+ .endm
+
+ /*
+ * mov_l - move a constant value or [relocated] address into a register
+ */
+ .macro mov_l, dst:req, imm:req, cond
+ .if __LINUX_ARM_ARCH__ < 7
+ ldr\cond \dst, =\imm
+ .else
+ W(movw\cond\()) \dst, #:lower16:\imm
+ W(movt\cond\()) \dst, #:upper16:\imm
+ .endif
+ .endm
+
+ /*
+ * adr_l - adr pseudo-op with unlimited range
+ *
+ * @dst: destination register
+ * @sym: name of the symbol
+ */
+ .macro adr_l, dst:req, sym:req, cond
+ __adldst_l add, \dst, \sym, \dst, \cond
+ .endm
+
+ /*
+ * ldr_l - ldr <literal> pseudo-op with unlimited range
+ *
+ * @dst: destination register
+ * @sym: name of the symbol
+ */
+ .macro ldr_l, dst:req, sym:req, cond
+ __adldst_l ldr, \dst, \sym, \dst, \cond
+ .endm
+
+ /*
+ * str_l - str <literal> pseudo-op with unlimited range
+ *
+ * @src: source register
+ * @sym: name of the symbol
+ * @tmp: mandatory scratch register
+ */
+ .macro str_l, src:req, sym:req, tmp:req, cond
+ __adldst_l str, \src, \sym, \tmp, \cond
+ .endm
+
#endif /* __ASM_ASSEMBLER_H__ */
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 03/30] ARM: head-common.S: use PC-relative insn sequence for __proc_info
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 01/30] asm-generic: add .data.rel.ro sections to __ro_after_init Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 04/30] ARM: head-common.S: use PC-relative insn sequence for idmap creation Ard Biesheuvel
` (27 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Replace the open coded PC relative offset calculations with a pair
of adr_l invocations. This ensures these quantities are invariant
under runtime relocation.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/head-common.S | 22 ++++++--------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 8733012d231f..06035488130c 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -150,11 +150,12 @@ ENDPROC(lookup_processor_type)
* r9 = cpuid (preserved)
*/
__lookup_processor_type:
- adr r3, __lookup_processor_type_data
- ldmia r3, {r4 - r6}
- sub r3, r3, r4 @ get offset between virt&phys
- add r5, r5, r3 @ convert virt addresses to
- add r6, r6, r3 @ physical address space
+ /*
+ * Look in <asm/procinfo.h> for information about the __proc_info
+ * structure.
+ */
+ adr_l r5, __proc_info_begin
+ adr_l r6, __proc_info_end
1: ldmia r5, {r3, r4} @ value, mask
and r4, r4, r9 @ mask wanted bits
teq r3, r4
@@ -166,17 +167,6 @@ __lookup_processor_type:
2: ret lr
ENDPROC(__lookup_processor_type)
-/*
- * Look in <asm/procinfo.h> for information about the __proc_info structure.
- */
- .align 2
- .type __lookup_processor_type_data, %object
-__lookup_processor_type_data:
- .long .
- .long __proc_info_begin
- .long __proc_info_end
- .size __lookup_processor_type_data, . - __lookup_processor_type_data
-
__error_lpae:
#ifdef CONFIG_DEBUG_LL
adr r0, str_lpae
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 04/30] ARM: head-common.S: use PC-relative insn sequence for idmap creation
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (2 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 03/30] ARM: head-common.S: use PC-relative insn sequence for __proc_info Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 05/30] ARM: head.S: use PC-relative insn sequence for secondary_data Ard Biesheuvel
` (26 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Replace the open coded PC relative offset calculations involving
__turn_mmu_on and __turn_mmu_on_end with a pair of adr_l invocations.
This ensures these quantities are invariant under runtime relocation.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/head.S | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 04286fd9e09c..0a98aec0e39d 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -227,11 +227,8 @@ __create_page_tables:
* Create identity mapping to cater for __enable_mmu.
* This identity mapping will be removed by paging_init().
*/
- adr r0, __turn_mmu_on_loc
- ldmia r0, {r3, r5, r6}
- sub r0, r0, r3 @ virt->phys offset
- add r5, r5, r0 @ phys __turn_mmu_on
- add r6, r6, r0 @ phys __turn_mmu_on_end
+ adr_l r5, __turn_mmu_on @ _pa(__turn_mmu_on)
+ adr_l r6, __turn_mmu_on_end @ _pa(__turn_mmu_on_end)
mov r5, r5, lsr #SECTION_SHIFT
mov r6, r6, lsr #SECTION_SHIFT
@@ -354,11 +351,6 @@ __create_page_tables:
ret lr
ENDPROC(__create_page_tables)
.ltorg
- .align
-__turn_mmu_on_loc:
- .long .
- .long __turn_mmu_on
- .long __turn_mmu_on_end
#if defined(CONFIG_SMP)
.text
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 05/30] ARM: head.S: use PC-relative insn sequence for secondary_data
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (3 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 04/30] ARM: head-common.S: use PC-relative insn sequence for idmap creation Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 06/30] ARM: kernel: use relative references for UP/SMP alternatives Ard Biesheuvel
` (25 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Replace the open coded PC relative offset calculations with adr_l
and ldr_l invocations. This ensures these quantities are invariant
under runtime relocation.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/head.S | 19 ++++---------------
1 file changed, 4 insertions(+), 15 deletions(-)
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 0a98aec0e39d..6e9df3663a57 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -386,10 +386,8 @@ ENTRY(secondary_startup)
/*
* Use the page tables supplied from __cpu_up.
*/
- adr r4, __secondary_data
- ldmia r4, {r5, r7, r12} @ address to jump to after
- sub lr, r4, r5 @ mmu has been enabled
- add r3, r7, lr
+ adr_l r3, secondary_data
+ mov_l r12, __secondary_switched
ldrd r4, [r3, #0] @ get secondary_data.pgdir
ARM_BE8(eor r4, r4, r5) @ Swap r5 and r4 in BE:
ARM_BE8(eor r5, r4, r5) @ it can be done in 3 steps
@@ -404,22 +402,13 @@ ARM_BE8(eor r4, r4, r5) @ without using a temp reg.
ENDPROC(secondary_startup)
ENDPROC(secondary_startup_arm)
- /*
- * r6 = &secondary_data
- */
ENTRY(__secondary_switched)
- ldr sp, [r7, #12] @ get secondary_data.stack
+ ldr_l r7, secondary_data + 12 @ get secondary_data.stack
+ mov sp, r7
mov fp, #0
b secondary_start_kernel
ENDPROC(__secondary_switched)
- .align
-
- .type __secondary_data, %object
-__secondary_data:
- .long .
- .long secondary_data
- .long __secondary_switched
#endif /* defined(CONFIG_SMP) */
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 06/30] ARM: kernel: use relative references for UP/SMP alternatives
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (4 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 05/30] ARM: head.S: use PC-relative insn sequence for secondary_data Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 07/30] ARM: head: use PC-relative insn sequence for __smp_alt Ard Biesheuvel
` (24 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
To avoid absolute references that are subject to runtime relocation
when running a kernel built with CONFIG_RELOCATABLE=y, use relative
references in the smp.alt entries.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/include/asm/assembler.h | 4 ++--
arch/arm/include/asm/processor.h | 2 +-
arch/arm/kernel/head.S | 10 +++++-----
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 516ebaf4ff38..3176bf7dcbd9 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -260,7 +260,7 @@
*/
#define ALT_UP(instr...) \
.pushsection ".alt.smp.init", "a" ;\
- .long 9998b ;\
+ .long 9998b - . ;\
9997: instr ;\
.if . - 9997b == 2 ;\
nop ;\
@@ -272,7 +272,7 @@
#define ALT_UP_B(label) \
.equ up_b_offset, label - 9998b ;\
.pushsection ".alt.smp.init", "a" ;\
- .long 9998b ;\
+ .long 9998b - . ;\
W(b) . + up_b_offset ;\
.popsection
#else
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index c3d5fc124a05..3667b395bb17 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -92,7 +92,7 @@ unsigned long get_wchan(struct task_struct *p);
#define __ALT_SMP_ASM(smp, up) \
"9998: " smp "\n" \
" .pushsection \".alt.smp.init\", \"a\"\n" \
- " .long 9998b\n" \
+ " .long 9998b - .\n" \
" " up "\n" \
" .popsection\n"
#else
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 6e9df3663a57..ec22f42fd8bb 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -548,14 +548,15 @@ smp_on_up:
__do_fixup_smp_on_up:
cmp r4, r5
reths lr
- ldmia r4!, {r0, r6}
- ARM( str r6, [r0, r3] )
- THUMB( add r0, r0, r3 )
+ ldmia r4, {r0, r6}
+ ARM( str r6, [r0, r4] )
+ THUMB( add r0, r0, r4 )
+ add r4, r4, #8
#ifdef __ARMEB__
THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian.
#endif
THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords
- THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3.
+ THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r0.
THUMB( strh r6, [r0] )
b __do_fixup_smp_on_up
ENDPROC(__do_fixup_smp_on_up)
@@ -564,7 +565,6 @@ ENTRY(fixup_smp)
stmfd sp!, {r4 - r6, lr}
mov r4, r0
add r5, r0, r1
- mov r3, #0
bl __do_fixup_smp_on_up
ldmfd sp!, {r4 - r6, pc}
ENDPROC(fixup_smp)
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 07/30] ARM: head: use PC-relative insn sequence for __smp_alt
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (5 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 06/30] ARM: kernel: use relative references for UP/SMP alternatives Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 08/30] ARM: sleep.S: use PC-relative insn sequence for sleep_save_sp/mpidr_hash Ard Biesheuvel
` (23 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Replace the open coded PC relative offset calculations with a pair
of adr_l invocations. This ensures these quantities are invariant
under runtime relocation.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/head.S | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index ec22f42fd8bb..db6b823f20a4 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -523,19 +523,11 @@ ARM_BE8(rev r0, r0) @ byteswap if big endian
retne lr
__fixup_smp_on_up:
- adr r0, 1f
- ldmia r0, {r3 - r5}
- sub r3, r0, r3
- add r4, r4, r3
- add r5, r5, r3
+ adr_l r4, __smpalt_begin
+ adr_l r5, __smpalt_end
b __do_fixup_smp_on_up
ENDPROC(__fixup_smp)
- .align
-1: .word .
- .word __smpalt_begin
- .word __smpalt_end
-
.pushsection .data
.globl smp_on_up
smp_on_up:
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 08/30] ARM: sleep.S: use PC-relative insn sequence for sleep_save_sp/mpidr_hash
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (6 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 07/30] ARM: head: use PC-relative insn sequence for __smp_alt Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 09/30] ARM: head.S: use PC-relative insn sequences for __fixup_pv_table Ard Biesheuvel
` (22 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Replace the open coded PC relative offset calculations with adr_l and
ldr_l invocations.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/sleep.S | 16 +++-------------
1 file changed, 3 insertions(+), 13 deletions(-)
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 0f6c1000582c..3026b119d3ff 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -137,9 +137,8 @@ ARM_BE8(setend be) @ ensure we are in BE mode
mov r1, #0
ALT_SMP(mrc p15, 0, r0, c0, c0, 5)
ALT_UP_B(1f)
- adr r2, mpidr_hash_ptr
- ldr r3, [r2]
- add r2, r2, r3 @ r2 = struct mpidr_hash phys address
+ adr_l r2, mpidr_hash @ r2 = struct mpidr_hash phys address
+
/*
* This ldmia relies on the memory layout of the mpidr_hash
* struct mpidr_hash.
@@ -147,10 +146,7 @@ ARM_BE8(setend be) @ ensure we are in BE mode
ldmia r2, { r3-r6 } @ r3 = mpidr mask (r4,r5,r6) = l[0,1,2] shifts
compute_mpidr_hash r1, r4, r5, r6, r0, r3
1:
- adr r0, _sleep_save_sp
- ldr r2, [r0]
- add r0, r0, r2
- ldr r0, [r0, #SLEEP_SAVE_SP_PHYS]
+ ldr_l r0, sleep_save_sp + SLEEP_SAVE_SP_PHYS
ldr r0, [r0, r1, lsl #2]
@ load phys pgd, stack, resume fn
@@ -164,12 +160,6 @@ ENDPROC(cpu_resume)
ENDPROC(cpu_resume_arm)
#endif
- .align 2
-_sleep_save_sp:
- .long sleep_save_sp - .
-mpidr_hash_ptr:
- .long mpidr_hash - . @ mpidr_hash struct offset
-
.data
.type sleep_save_sp, #object
ENTRY(sleep_save_sp)
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 09/30] ARM: head.S: use PC-relative insn sequences for __fixup_pv_table
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (7 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 08/30] ARM: sleep.S: use PC-relative insn sequence for sleep_save_sp/mpidr_hash Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 10/30] ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET Ard Biesheuvel
` (21 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Replace the open coded PC relative offset calculations with adr_l
and mov_l invocations. This ensures these quantities are invariant
under runtime relocation.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/head.S | 27 ++++++--------------
1 file changed, 8 insertions(+), 19 deletions(-)
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index db6b823f20a4..f607e290ef4b 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -578,14 +578,11 @@ ENDPROC(fixup_smp)
*/
__HEAD
__fixup_pv_table:
- adr r0, 1f
- ldmia r0, {r3-r7}
+ adr_l r6, __pv_phys_pfn_offset
+ adr_l r7, __pv_offset @ __pa(__pv_offset)
+ mov_l r3, __pv_offset @ __va(__pv_offset)
mvn ip, #0
- subs r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET
- add r4, r4, r3 @ adjust table start address
- add r5, r5, r3 @ adjust table end address
- add r6, r6, r3 @ adjust __pv_phys_pfn_offset address
- add r7, r7, r3 @ adjust __pv_offset address
+ subs r3, r7, r3 @ PHYS_OFFSET - PAGE_OFFSET
mov r0, r8, lsr #PAGE_SHIFT @ convert to PFN
str r0, [r6] @ save computed PHYS_OFFSET to __pv_phys_pfn_offset
strcc ip, [r7, #HIGH_OFFSET] @ save to __pv_offset high bits
@@ -594,20 +591,15 @@ __fixup_pv_table:
THUMB( it ne @ cross section branch )
bne __error
str r3, [r7, #LOW_OFFSET] @ save to __pv_offset low bits
+ adr_l r4, __pv_table_begin
+ adr_l r5, __pv_table_end
b __fixup_a_pv_table
ENDPROC(__fixup_pv_table)
-
- .align
-1: .long .
- .long __pv_table_begin
- .long __pv_table_end
-2: .long __pv_phys_pfn_offset
- .long __pv_offset
+ .ltorg
.text
__fixup_a_pv_table:
- adr r0, 3f
- ldr r6, [r0]
+ mov_l r6, __pv_offset
add r6, r6, r3
ldr r0, [r6, #HIGH_OFFSET] @ pv_offset high word
ldr r6, [r6, #LOW_OFFSET] @ pv_offset low word
@@ -676,9 +668,6 @@ ARM_BE8(rev16 ip, ip)
#endif
ENDPROC(__fixup_a_pv_table)
- .align
-3: .long __pv_offset
-
ENTRY(fixup_pv_table)
stmfd sp!, {r4 - r7, lr}
mov r3, #0 @ no offset
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 10/30] ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (8 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 09/30] ARM: head.S: use PC-relative insn sequences for __fixup_pv_table Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 11/30] ARM: kvm: replace open coded VA->PA calculations with adr_l call Ard Biesheuvel
` (20 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Replace the open coded arithmetic with a simple adr_l/sub pair. This
ensures these quantities are invariant under runtime relocation.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/head.S | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index f607e290ef4b..62c961849035 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -106,10 +106,8 @@ ENTRY(stext)
#endif
#ifndef CONFIG_XIP_KERNEL
- adr r3, 2f
- ldmia r3, {r4, r8}
- sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET)
- add r8, r8, r4 @ PHYS_OFFSET
+ adr_l r8, _text @ __pa(_text)
+ sub r8, r8, #TEXT_OFFSET @ PHYS_OFFSET
#else
ldr r8, =PLAT_PHYS_OFFSET @ always constant in this case
#endif
@@ -161,10 +159,6 @@ ENTRY(stext)
1: b __enable_mmu
ENDPROC(stext)
.ltorg
-#ifndef CONFIG_XIP_KERNEL
-2: .long .
- .long PAGE_OFFSET
-#endif
/*
* Setup the initial page tables. We only setup the barest
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 11/30] ARM: kvm: replace open coded VA->PA calculations with adr_l call
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (9 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 10/30] ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 12/30] arm-soc: exynos: replace open coded VA->PA conversions Ard Biesheuvel
` (19 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Replace the open coded calculations of the actual physical address
of the KVM stub vector table with a single adr_l invocation.
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/boot/compressed/head.S | 15 ++-------
arch/arm/kernel/hyp-stub.S | 33 +++++++-------------
arch/arm/kvm/init.S | 8 +----
3 files changed, 15 insertions(+), 41 deletions(-)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 8a756870c238..5884e8151376 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -427,15 +427,10 @@ dtb_check_done:
/*
* Compute the address of the hyp vectors after relocation.
- * This requires some arithmetic since we cannot directly
- * reference __hyp_stub_vectors in a PC-relative way.
* Call __hyp_set_vectors with the new address so that we
* can HVC again after the copy.
*/
-0: adr r0, 0b
- movw r1, #:lower16:__hyp_stub_vectors - 0b
- movt r1, #:upper16:__hyp_stub_vectors - 0b
- add r0, r0, r1
+ adr_l r0, __hyp_stub_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
@@ -568,17 +563,11 @@ not_relocated: mov r0, #0
cmp r0, #HYP_MODE @ if not booted in HYP mode...
bne __enter_kernel @ boot kernel directly
- adr r12, .L__hyp_reentry_vectors_offset
- ldr r0, [r12]
- add r0, r0, r12
-
+ adr_l r0, __hyp_reentry_vectors
bl __hyp_set_vectors
__HVC(0) @ otherwise bounce to hyp mode
b . @ should never be reached
-
- .align 2
-.L__hyp_reentry_vectors_offset: .long __hyp_reentry_vectors - .
#else
b __enter_kernel
#endif
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
index ec7e7377d423..55b5fab83861 100644
--- a/arch/arm/kernel/hyp-stub.S
+++ b/arch/arm/kernel/hyp-stub.S
@@ -36,41 +36,38 @@ ENTRY(__boot_cpu_mode)
.text
/*
- * Save the primary CPU boot mode. Requires 3 scratch registers.
+ * Save the primary CPU boot mode. Requires 2 scratch registers.
*/
- .macro store_primary_cpu_mode reg1, reg2, reg3
+ .macro store_primary_cpu_mode reg1, reg2
mrs \reg1, cpsr
and \reg1, \reg1, #MODE_MASK
- adr \reg2, .L__boot_cpu_mode_offset
- ldr \reg3, [\reg2]
- str \reg1, [\reg2, \reg3]
+ str_l \reg1, __boot_cpu_mode, \reg2
.endm
/*
* Compare the current mode with the one saved on the primary CPU.
* If they don't match, record that fact. The Z bit indicates
* if there's a match or not.
- * Requires 3 additionnal scratch registers.
+ * Requires 2 additionnal scratch registers.
*/
- .macro compare_cpu_mode_with_primary mode, reg1, reg2, reg3
- adr \reg2, .L__boot_cpu_mode_offset
- ldr \reg3, [\reg2]
- ldr \reg1, [\reg2, \reg3]
+ .macro compare_cpu_mode_with_primary mode, reg1, reg2
+ adr_l \reg2, __boot_cpu_mode
+ ldr \reg1, [\reg2]
cmp \mode, \reg1 @ matches primary CPU boot mode?
orrne \reg1, \reg1, #BOOT_CPU_MODE_MISMATCH
- strne \reg1, [\reg2, \reg3] @ record what happened and give up
+ strne \reg1, [\reg2] @ record what happened and give up
.endm
#else /* ZIMAGE */
- .macro store_primary_cpu_mode reg1:req, reg2:req, reg3:req
+ .macro store_primary_cpu_mode reg1:req, reg2:req
.endm
/*
* The zImage loader only runs on one CPU, so we don't bother with mult-CPU
* consistency checking:
*/
- .macro compare_cpu_mode_with_primary mode, reg1, reg2, reg3
+ .macro compare_cpu_mode_with_primary mode, reg1, reg2
cmp \mode, \mode
.endm
@@ -85,7 +82,7 @@ ENTRY(__boot_cpu_mode)
*/
@ Call this from the primary CPU
ENTRY(__hyp_stub_install)
- store_primary_cpu_mode r4, r5, r6
+ store_primary_cpu_mode r4, r5
ENDPROC(__hyp_stub_install)
@ fall through...
@@ -99,7 +96,7 @@ ENTRY(__hyp_stub_install_secondary)
* If the secondary has booted with a different mode, give up
* immediately.
*/
- compare_cpu_mode_with_primary r4, r5, r6, r7
+ compare_cpu_mode_with_primary r4, r5, r6
retne lr
/*
@@ -264,12 +261,6 @@ ENTRY(__hyp_reset_vectors)
ret lr
ENDPROC(__hyp_reset_vectors)
-#ifndef ZIMAGE
-.align 2
-.L__boot_cpu_mode_offset:
- .long __boot_cpu_mode - .
-#endif
-
.align 5
ENTRY(__hyp_stub_vectors)
__hyp_stub_reset: W(b) .
diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S
index 5386528665b5..d777c6fbd869 100644
--- a/arch/arm/kvm/init.S
+++ b/arch/arm/kvm/init.S
@@ -143,13 +143,7 @@ reset:
bic r1, r1, r0
mcr p15, 4, r1, c1, c0, 0 @ HSCTLR
- /*
- * Install stub vectors, using ardb's VA->PA trick.
- */
-0: adr r0, 0b @ PA(0)
- movw r1, #:lower16:__hyp_stub_vectors - 0b @ VA(stub) - VA(0)
- movt r1, #:upper16:__hyp_stub_vectors - 0b
- add r1, r1, r0 @ PA(stub)
+ adr_l r1, __hyp_stub_vectors @ PA(stub)
mcr p15, 4, r1, c12, c0, 0 @ HVBAR
b exit
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 12/30] arm-soc: exynos: replace open coded VA->PA conversions
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (10 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 11/30] ARM: kvm: replace open coded VA->PA calculations with adr_l call Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 13/30] arm-soc: mvebu: replace open coded VA->PA conversion Ard Biesheuvel
` (18 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
This replaces a couple of open coded calculations to obtain the
physical address of a far symbol with calls to the new adr_l etc
macros.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/mach-exynos/headsmp.S | 9 +------
arch/arm/mach-exynos/sleep.S | 26 ++++----------------
2 files changed, 6 insertions(+), 29 deletions(-)
diff --git a/arch/arm/mach-exynos/headsmp.S b/arch/arm/mach-exynos/headsmp.S
index d3d24ab351ae..25de5aff1c41 100644
--- a/arch/arm/mach-exynos/headsmp.S
+++ b/arch/arm/mach-exynos/headsmp.S
@@ -23,10 +23,7 @@ ENTRY(exynos4_secondary_startup)
ARM_BE8(setend be)
mrc p15, 0, r0, c0, c0, 5
and r0, r0, #15
- adr r4, 1f
- ldmia r4, {r5, r6}
- sub r4, r4, r5
- add r6, r6, r4
+ adr_l r6, pen_release
pen: ldr r7, [r6]
cmp r7, r0
bne pen
@@ -37,7 +34,3 @@ pen: ldr r7, [r6]
*/
b secondary_startup
ENDPROC(exynos4_secondary_startup)
-
- .align 2
-1: .long .
- .long pen_release
diff --git a/arch/arm/mach-exynos/sleep.S b/arch/arm/mach-exynos/sleep.S
index cf950790fbdc..003465699263 100644
--- a/arch/arm/mach-exynos/sleep.S
+++ b/arch/arm/mach-exynos/sleep.S
@@ -17,6 +17,7 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
#include <asm/hardware/cache-l2x0.h>
#include "smc.h"
@@ -62,19 +63,13 @@ ENTRY(exynos_cpu_resume_ns)
cmp r0, r1
bne skip_cp15
- adr r0, _cp15_save_power
- ldr r1, [r0]
- ldr r1, [r0, r1]
- adr r0, _cp15_save_diag
- ldr r2, [r0]
- ldr r2, [r0, r2]
+ ldr_l r1, cp15_save_power
+ ldr_l r2, cp15_save_diag
mov r0, #SMC_CMD_C15RESUME
dsb
smc #0
#ifdef CONFIG_CACHE_L2X0
- adr r0, 1f
- ldr r2, [r0]
- add r0, r2, r0
+ adr_l r0, l2x0_saved_regs
/* Check that the address has been initialised. */
ldr r1, [r0, #L2X0_R_PHY_BASE]
@@ -93,9 +88,7 @@ ENTRY(exynos_cpu_resume_ns)
smc #0
/* Reload saved regs pointer because smc corrupts registers. */
- adr r0, 1f
- ldr r2, [r0]
- add r0, r2, r0
+ adr_l r0, l2x0_saved_regs
ldr r1, [r0, #L2X0_R_PWR_CTRL]
ldr r2, [r0, #L2X0_R_AUX_CTRL]
@@ -114,15 +107,6 @@ skip_cp15:
b cpu_resume
ENDPROC(exynos_cpu_resume_ns)
- .align
-_cp15_save_power:
- .long cp15_save_power - .
-_cp15_save_diag:
- .long cp15_save_diag - .
-#ifdef CONFIG_CACHE_L2X0
-1: .long l2x0_saved_regs - .
-#endif /* CONFIG_CACHE_L2X0 */
-
.data
.globl cp15_save_diag
cp15_save_diag:
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 13/30] arm-soc: mvebu: replace open coded VA->PA conversion
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (11 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 12/30] arm-soc: exynos: replace open coded VA->PA conversions Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 14/30] arm-soc: various: replace open coded VA->PA calculation of pen_release Ard Biesheuvel
` (17 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
This replaces an open coded calculation to obtain the physical
address of a far symbol with a call to the new ldr_l etc macro.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/mach-mvebu/coherency_ll.S | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S
index 8b2fbc8b6bc6..df0ccb5cef1d 100644
--- a/arch/arm/mach-mvebu/coherency_ll.S
+++ b/arch/arm/mach-mvebu/coherency_ll.S
@@ -42,9 +42,7 @@ ENTRY(ll_get_coherency_base)
ldr r1, =coherency_base
cmp r1, #0
beq 2f
- adr r1, 3f
- ldr r3, [r1]
- ldr r1, [r1, r3]
+ ldr_l r1, coherency_phys_base
b 2f
1:
/*
@@ -160,7 +158,3 @@ ENTRY(ll_disable_coherency)
dsb
ret lr
ENDPROC(ll_disable_coherency)
-
- .align 2
-3:
- .long coherency_phys_base - .
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 14/30] arm-soc: various: replace open coded VA->PA calculation of pen_release
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (12 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 13/30] arm-soc: mvebu: replace open coded VA->PA conversion Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 15/30] ARM: kernel: switch to relative exception tables Ard Biesheuvel
` (16 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
This replaces a few copies of the open coded calculations of the
physical address of 'pen_release' in the secondary startup code
of a couple of platforms. This ensures these quantities are invariant
under runtime relocation.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/mach-prima2/headsmp.S | 11 +++--------
arch/arm/mach-spear/headsmp.S | 11 +++--------
arch/arm/mach-sti/headsmp.S | 10 +++-------
arch/arm/plat-versatile/headsmp.S | 9 +--------
4 files changed, 10 insertions(+), 31 deletions(-)
diff --git a/arch/arm/mach-prima2/headsmp.S b/arch/arm/mach-prima2/headsmp.S
index 209d9fc5c16c..070df700bb38 100644
--- a/arch/arm/mach-prima2/headsmp.S
+++ b/arch/arm/mach-prima2/headsmp.S
@@ -9,6 +9,8 @@
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
+
/*
* SIRFSOC specific entry point for secondary CPUs. This provides
* a "holding pen" into which all secondary cores are held until we're
@@ -17,10 +19,7 @@
ENTRY(sirfsoc_secondary_startup)
mrc p15, 0, r0, c0, c0, 5
and r0, r0, #15
- adr r4, 1f
- ldmia r4, {r5, r6}
- sub r4, r4, r5
- add r6, r6, r4
+ adr_l r6, pen_release
pen: ldr r7, [r6]
cmp r7, r0
bne pen
@@ -31,7 +30,3 @@ pen: ldr r7, [r6]
*/
b secondary_startup
ENDPROC(sirfsoc_secondary_startup)
-
- .align
-1: .long .
- .long pen_release
diff --git a/arch/arm/mach-spear/headsmp.S b/arch/arm/mach-spear/headsmp.S
index c52192dc3d9f..4da01b103f33 100644
--- a/arch/arm/mach-spear/headsmp.S
+++ b/arch/arm/mach-spear/headsmp.S
@@ -13,6 +13,8 @@
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
+
__INIT
/*
@@ -23,10 +25,7 @@
ENTRY(spear13xx_secondary_startup)
mrc p15, 0, r0, c0, c0, 5
and r0, r0, #15
- adr r4, 1f
- ldmia r4, {r5, r6}
- sub r4, r4, r5
- add r6, r6, r4
+ adr_l r6, pen_release
pen: ldr r7, [r6]
cmp r7, r0
bne pen
@@ -40,8 +39,4 @@ pen: ldr r7, [r6]
* should now contain the SVC stack for this core
*/
b secondary_startup
-
- .align
-1: .long .
- .long pen_release
ENDPROC(spear13xx_secondary_startup)
diff --git a/arch/arm/mach-sti/headsmp.S b/arch/arm/mach-sti/headsmp.S
index e0ad451700d5..cdf3442f397b 100644
--- a/arch/arm/mach-sti/headsmp.S
+++ b/arch/arm/mach-sti/headsmp.S
@@ -16,6 +16,8 @@
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
+
/*
* ST specific entry point for secondary CPUs. This provides
* a "holding pen" into which all secondary cores are held until we're
@@ -24,10 +26,7 @@
ENTRY(sti_secondary_startup)
mrc p15, 0, r0, c0, c0, 5
and r0, r0, #15
- adr r4, 1f
- ldmia r4, {r5, r6}
- sub r4, r4, r5
- add r6, r6, r4
+ adr_l r6, pen_release
pen: ldr r7, [r6]
cmp r7, r0
bne pen
@@ -38,6 +37,3 @@ pen: ldr r7, [r6]
*/
b secondary_startup
ENDPROC(sti_secondary_startup)
-
-1: .long .
- .long pen_release
diff --git a/arch/arm/plat-versatile/headsmp.S b/arch/arm/plat-versatile/headsmp.S
index 40f27e52de75..0f2a5eddac5a 100644
--- a/arch/arm/plat-versatile/headsmp.S
+++ b/arch/arm/plat-versatile/headsmp.S
@@ -21,10 +21,7 @@ ENTRY(versatile_secondary_startup)
ARM_BE8(setend be)
mrc p15, 0, r0, c0, c0, 5
bic r0, #0xff000000
- adr r4, 1f
- ldmia r4, {r5, r6}
- sub r4, r4, r5
- add r6, r6, r4
+ adr_l r6, pen_release
pen: ldr r7, [r6]
cmp r7, r0
bne pen
@@ -34,8 +31,4 @@ pen: ldr r7, [r6]
* should now contain the SVC stack for this core
*/
b secondary_startup
-
- .align
-1: .long .
- .long pen_release
ENDPROC(versatile_secondary_startup)
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 15/30] ARM: kernel: switch to relative exception tables
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (13 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 14/30] arm-soc: various: replace open coded VA->PA calculation of pen_release Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 16/30] ARM: kernel: use relative phys-to-virt patch tables Ard Biesheuvel
` (15 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
To avoid having to relocate the contents of extable entries at
runtime when running with KASLR enabled, wire up the existing
support for emitting them as relative references. This ensures
these quantities are invariant under runtime relocation.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/include/asm/Kbuild | 1 -
arch/arm/include/asm/assembler.h | 6 +++---
arch/arm/include/asm/extable.h | 20 ++++++++++++++++++
arch/arm/include/asm/futex.h | 2 +-
arch/arm/include/asm/uaccess.h | 8 +++----
arch/arm/include/asm/word-at-a-time.h | 2 +-
arch/arm/kernel/entry-armv.S | 6 +++---
arch/arm/kernel/swp_emulate.c | 4 ++--
arch/arm/lib/backtrace.S | 8 +++----
arch/arm/lib/getuser.S | 22 ++++++++++----------
arch/arm/lib/putuser.S | 12 +++++------
arch/arm/mm/alignment.c | 14 ++++++-------
arch/arm/mm/extable.c | 2 +-
arch/arm/nwfpe/entry.S | 2 +-
scripts/sortextable.c | 2 +-
15 files changed, 65 insertions(+), 46 deletions(-)
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 721ab5ecfb9b..f2d67fa34eb3 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -3,7 +3,6 @@ generic-y += current.h
generic-y += early_ioremap.h
generic-y += emergency-restart.h
generic-y += exec.h
-generic-y += extable.h
generic-y += irq_regs.h
generic-y += kdebug.h
generic-y += local.h
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 3176bf7dcbd9..09b6b28f2595 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -247,7 +247,7 @@
9999: x; \
.pushsection __ex_table,"a"; \
.align 3; \
- .long 9999b,9001f; \
+ .long 9999b - ., 9001f - .; \
.popsection
#ifdef CONFIG_SMP
@@ -383,7 +383,7 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
.pushsection __ex_table,"a"
.align 3
- .long 9999b, \abort
+ .long 9999b - ., \abort - .
.popsection
.endm
@@ -424,7 +424,7 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
.pushsection __ex_table,"a"
.align 3
- .long 9999b, \abort
+ .long 9999b - ., \abort - .
.popsection
.endr
.endm
diff --git a/arch/arm/include/asm/extable.h b/arch/arm/include/asm/extable.h
new file mode 100644
index 000000000000..3610cc116a86
--- /dev/null
+++ b/arch/arm/include/asm/extable.h
@@ -0,0 +1,20 @@
+#ifndef __ASM_EXTABLE_H
+#define __ASM_EXTABLE_H
+
+/*
+ * The exception table consists of pairs of relative offsets: the first
+ * is the relative offset to an instruction that is allowed to fault,
+ * and the second is the relative offset at which the program should
+ * continue. No registers are modified, so it is entirely up to the
+ * continuation code to figure out what to do.
+ */
+
+struct exception_table_entry
+{
+ int insn, fixup;
+};
+
+#define ARCH_HAS_RELATIVE_EXTABLE
+
+extern int fixup_exception(struct pt_regs *regs);
+#endif
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index 6795368ad023..31760d0ab76b 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -11,7 +11,7 @@
"3:\n" \
" .pushsection __ex_table,\"a\"\n" \
" .align 3\n" \
- " .long 1b, 4f, 2b, 4f\n" \
+ " .long 1b - ., 4f - ., 2b - ., 4f - .\n" \
" .popsection\n" \
" .pushsection .text.fixup,\"ax\"\n" \
" .align 2\n" \
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 0bf2347495f1..62b9bb7d991a 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -295,7 +295,7 @@ do { \
" .popsection\n" \
" .pushsection __ex_table,\"a\"\n" \
" .align 3\n" \
- " .long 1b, 3b\n" \
+ " .long 1b - ., 3b - .\n" \
" .popsection" \
: "+r" (err), "=&r" (x) \
: "r" (addr), "i" (-EFAULT) \
@@ -385,7 +385,7 @@ do { \
" .popsection\n" \
" .pushsection __ex_table,\"a\"\n" \
" .align 3\n" \
- " .long 1b, 3b\n" \
+ " .long 1b - ., 3b - .\n" \
" .popsection" \
: "+r" (err) \
: "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
@@ -435,8 +435,8 @@ do { \
" .popsection\n" \
" .pushsection __ex_table,\"a\"\n" \
" .align 3\n" \
- " .long 1b, 4b\n" \
- " .long 2b, 4b\n" \
+ " .long 1b - ., 4b - .\n" \
+ " .long 2b - ., 4b - .\n" \
" .popsection" \
: "+r" (err), "+r" (__pu_addr) \
: "r" (x), "i" (-EFAULT) \
diff --git a/arch/arm/include/asm/word-at-a-time.h b/arch/arm/include/asm/word-at-a-time.h
index 5831dce4b51c..d433c686d9ca 100644
--- a/arch/arm/include/asm/word-at-a-time.h
+++ b/arch/arm/include/asm/word-at-a-time.h
@@ -86,7 +86,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr)
" .popsection\n"
" .pushsection __ex_table,\"a\"\n"
" .align 3\n"
- " .long 1b, 3b\n"
+ " .long 1b - ., 3b - .\n"
" .popsection"
: "=&r" (ret), "=&r" (offset)
: "r" (addr), "Qo" (*(unsigned long *)addr));
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index c731f0d2b2af..1c7c12123b18 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -570,10 +570,10 @@ ENDPROC(__und_usr)
ret r9
.popsection
.pushsection __ex_table,"a"
- .long 1b, 4b
+ .long 1b - ., 4b - .
#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
- .long 2b, 4b
- .long 3b, 4b
+ .long 2b - ., 4b - .
+ .long 3b - ., 4b - .
#endif
.popsection
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index 3bda08bee674..a783e9c0b266 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -50,8 +50,8 @@
" .previous\n" \
" .section __ex_table,\"a\"\n" \
" .align 3\n" \
- " .long 0b, 3b\n" \
- " .long 1b, 3b\n" \
+ " .long 0b - ., 3b - .\n" \
+ " .long 1b - ., 3b - .\n" \
" .previous" \
: "=&r" (res), "+r" (data), "=&r" (temp) \
: "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 7d7952e5a3b1..84a8df7aa63c 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -107,10 +107,10 @@ ENDPROC(c_backtrace)
.pushsection __ex_table,"a"
.align 3
- .long 1001b, 1006b
- .long 1002b, 1006b
- .long 1003b, 1006b
- .long 1004b, 1006b
+ .long 1001b - ., 1006b - .
+ .long 1002b - ., 1006b - .
+ .long 1003b - ., 1006b - .
+ .long 1004b - ., 1006b - .
.popsection
.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index df73914e81c8..d47b4776d308 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -133,17 +133,17 @@ ENDPROC(__get_user_bad)
ENDPROC(__get_user_bad8)
.pushsection __ex_table, "a"
- .long 1b, __get_user_bad
- .long 2b, __get_user_bad
- .long 3b, __get_user_bad
- .long 4b, __get_user_bad
- .long 5b, __get_user_bad8
- .long 6b, __get_user_bad8
+ .long 1b - ., __get_user_bad - .
+ .long 2b - ., __get_user_bad - .
+ .long 3b - ., __get_user_bad - .
+ .long 4b - ., __get_user_bad - .
+ .long 5b - ., __get_user_bad8 - .
+ .long 6b - ., __get_user_bad8 - .
#ifdef __ARMEB__
- .long 7b, __get_user_bad
- .long 8b, __get_user_bad8
- .long 9b, __get_user_bad8
- .long 10b, __get_user_bad8
- .long 11b, __get_user_bad8
+ .long 7b - ., __get_user_bad - .
+ .long 8b - ., __get_user_bad8 - .
+ .long 9b - ., __get_user_bad8 - .
+ .long 10b - ., __get_user_bad8 - .
+ .long 11b - ., __get_user_bad8 - .
#endif
.popsection
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index 38d660d3705f..6b854197ff48 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -89,10 +89,10 @@ __put_user_bad:
ENDPROC(__put_user_bad)
.pushsection __ex_table, "a"
- .long 1b, __put_user_bad
- .long 2b, __put_user_bad
- .long 3b, __put_user_bad
- .long 4b, __put_user_bad
- .long 5b, __put_user_bad
- .long 6b, __put_user_bad
+ .long 1b - ., __put_user_bad - .
+ .long 2b - ., __put_user_bad - .
+ .long 3b - ., __put_user_bad - .
+ .long 4b - ., __put_user_bad - .
+ .long 5b - ., __put_user_bad - .
+ .long 6b - ., __put_user_bad - .
.popsection
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 2c96190e018b..2c74cb826b6a 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -209,7 +209,7 @@ union offset_union {
" .popsection\n" \
" .pushsection __ex_table,\"a\"\n" \
" .align 3\n" \
- " .long 1b, 3b\n" \
+ " .long 1b - ., 3b - .\n" \
" .popsection\n" \
: "=r" (err), "=&r" (val), "=r" (addr) \
: "0" (err), "2" (addr))
@@ -269,8 +269,8 @@ union offset_union {
" .popsection\n" \
" .pushsection __ex_table,\"a\"\n" \
" .align 3\n" \
- " .long 1b, 4b\n" \
- " .long 2b, 4b\n" \
+ " .long 1b - ., 4b - .\n" \
+ " .long 2b - ., 4b - .\n" \
" .popsection\n" \
: "=r" (err), "=&r" (v), "=&r" (a) \
: "0" (err), "1" (v), "2" (a)); \
@@ -309,10 +309,10 @@ union offset_union {
" .popsection\n" \
" .pushsection __ex_table,\"a\"\n" \
" .align 3\n" \
- " .long 1b, 6b\n" \
- " .long 2b, 6b\n" \
- " .long 3b, 6b\n" \
- " .long 4b, 6b\n" \
+ " .long 1b - ., 6b - .\n" \
+ " .long 2b - ., 6b - .\n" \
+ " .long 3b - ., 6b - .\n" \
+ " .long 4b - ., 6b - .\n" \
" .popsection\n" \
: "=r" (err), "=&r" (v), "=&r" (a) \
: "0" (err), "1" (v), "2" (a)); \
diff --git a/arch/arm/mm/extable.c b/arch/arm/mm/extable.c
index f436f7439e46..6a8b85bf0cac 100644
--- a/arch/arm/mm/extable.c
+++ b/arch/arm/mm/extable.c
@@ -10,7 +10,7 @@ int fixup_exception(struct pt_regs *regs)
fixup = search_exception_tables(instruction_pointer(regs));
if (fixup) {
- regs->ARM_pc = fixup->fixup;
+ regs->ARM_pc = (unsigned long)&fixup->fixup + fixup->fixup;
#ifdef CONFIG_THUMB2_KERNEL
/* Clear the IT state to avoid nasty surprises in the fixup */
regs->ARM_cpsr &= ~PSR_IT_MASK;
diff --git a/arch/arm/nwfpe/entry.S b/arch/arm/nwfpe/entry.S
index 39c20afad7ed..c4fe13b31705 100644
--- a/arch/arm/nwfpe/entry.S
+++ b/arch/arm/nwfpe/entry.S
@@ -121,5 +121,5 @@ next:
.pushsection __ex_table,"a"
.align 3
- .long .Lx1, .Lfix
+ .long .Lx1 - ., .Lfix - .
.popsection
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index 365a907f98b3..56a4c6714da7 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -314,6 +314,7 @@ do_file(char const *const fname)
break;
case EM_S390:
+ case EM_ARM:
case EM_AARCH64:
case EM_PARISC:
case EM_PPC:
@@ -322,7 +323,6 @@ do_file(char const *const fname)
break;
case EM_ARCOMPACT:
case EM_ARCV2:
- case EM_ARM:
case EM_MICROBLAZE:
case EM_MIPS:
case EM_XTENSA:
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 16/30] ARM: kernel: use relative phys-to-virt patch tables
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (14 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 15/30] ARM: kernel: switch to relative exception tables Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 17/30] arm-soc: tegra: make sleep asm code runtime relocatable Ard Biesheuvel
` (14 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Replace the contents of the __pv_table entries with relative references
so that we don't have to relocate them at runtime when running the KASLR
kernel. This ensures these quantities are invariant under runtime
relocation, which makes any cache maintenance after runtime relocation
unnecessary.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/include/asm/memory.h | 6 +++---
arch/arm/kernel/head.S | 21 ++++++++++----------
2 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 1f54e4e98c1e..47a984e3a244 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -195,7 +195,7 @@ extern const void *__pv_table_begin, *__pv_table_end;
__asm__("@ __pv_stub\n" \
"1: " instr " %0, %1, %2\n" \
" .pushsection .pv_table,\"a\"\n" \
- " .long 1b\n" \
+ " .long 1b - .\n" \
" .popsection\n" \
: "=r" (to) \
: "r" (from), "I" (type))
@@ -204,7 +204,7 @@ extern const void *__pv_table_begin, *__pv_table_end;
__asm__ volatile("@ __pv_stub_mov\n" \
"1: mov %R0, %1\n" \
" .pushsection .pv_table,\"a\"\n" \
- " .long 1b\n" \
+ " .long 1b - .\n" \
" .popsection\n" \
: "=r" (t) \
: "I" (__PV_BITS_7_0))
@@ -214,7 +214,7 @@ extern const void *__pv_table_begin, *__pv_table_end;
"1: adds %Q0, %1, %2\n" \
" adc %R0, %R0, #0\n" \
" .pushsection .pv_table,\"a\"\n" \
- " .long 1b\n" \
+ " .long 1b - .\n" \
" .popsection\n" \
: "+r" (y) \
: "r" (x), "I" (__PV_BITS_31_24) \
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 62c961849035..5d685e86148c 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -593,8 +593,7 @@ ENDPROC(__fixup_pv_table)
.text
__fixup_a_pv_table:
- mov_l r6, __pv_offset
- add r6, r6, r3
+ adr_l r6, __pv_offset
ldr r0, [r6, #HIGH_OFFSET] @ pv_offset high word
ldr r6, [r6, #LOW_OFFSET] @ pv_offset low word
mov r6, r6, lsr #24
@@ -612,22 +611,22 @@ __fixup_a_pv_table:
orr r6, r6, r7, lsl #12
orr r6, #0x4000
b 2f
-1: add r7, r3
- ldrh ip, [r7, #2]
+1: add r7, r4
+ ldrh ip, [r7, #-2]
ARM_BE8(rev16 ip, ip)
tst ip, #0x4000
and ip, #0x8f00
orrne ip, r6 @ mask in offset bits 31-24
orreq ip, r0 @ mask in offset bits 7-0
ARM_BE8(rev16 ip, ip)
- strh ip, [r7, #2]
+ strh ip, [r7, #-2]
bne 2f
- ldrh ip, [r7]
+ ldrh ip, [r7, #-4]
ARM_BE8(rev16 ip, ip)
bic ip, #0x20
orr ip, ip, r0, lsr #16
ARM_BE8(rev16 ip, ip)
- strh ip, [r7]
+ strh ip, [r7, #-4]
2: cmp r4, r5
ldrcc r7, [r4], #4 @ use branch for delay slot
bcc 1b
@@ -639,7 +638,8 @@ ARM_BE8(rev16 ip, ip)
moveq r0, #0x400000 @ set bit 22, mov to mvn instruction
#endif
b 2f
-1: ldr ip, [r7, r3]
+1: ldr ip, [r7, r4]!
+ add r4, r4, #4
#ifdef CONFIG_CPU_ENDIAN_BE8
@ in BE8, we load data in BE, but instructions still in LE
bic ip, ip, #0xff000000
@@ -654,9 +654,9 @@ ARM_BE8(rev16 ip, ip)
biceq ip, ip, #0x400000 @ clear bit 22
orreq ip, ip, r0 @ mask in offset bits 7-0
#endif
- str ip, [r7, r3]
+ str ip, [r7]
2: cmp r4, r5
- ldrcc r7, [r4], #4 @ use branch for delay slot
+ ldrcc r7, [r4] @ use branch for delay slot
bcc 1b
ret lr
#endif
@@ -664,7 +664,6 @@ ENDPROC(__fixup_a_pv_table)
ENTRY(fixup_pv_table)
stmfd sp!, {r4 - r7, lr}
- mov r3, #0 @ no offset
mov r4, r0 @ r0 = table start
add r5, r0, r1 @ r1 = table size
bl __fixup_a_pv_table
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 17/30] arm-soc: tegra: make sleep asm code runtime relocatable
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (15 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 16/30] ARM: kernel: use relative phys-to-virt patch tables Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 14:42 ` [kernel-hardening] " Dave Martin
2017-08-14 12:53 ` [kernel-hardening] [PATCH 18/30] ARM: kernel: make vmlinux buildable as a PIE executable Ard Biesheuvel
` (13 subsequent siblings)
30 siblings, 1 reply; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
The PIE kernel build does not allow absolute references encoded in
movw/movt instruction pairs, so use our mov_l macro instead (which
will still use such a pair unless CONFIG_RELOCATABLE is defined)
Also, avoid 32-bit absolute literals to refer to absolute symbols.
Instead, use a 16 bit reference so that PIE linker cannot get
confused whether the symbol reference is subject to relocation at
runtime.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/mach-tegra/sleep-tegra20.S | 22 ++++++++++++--------
arch/arm/mach-tegra/sleep-tegra30.S | 6 +++---
arch/arm/mach-tegra/sleep.S | 4 ++--
3 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index 5c8e638ee51a..cab95de5c8f1 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -99,7 +99,7 @@ ENTRY(tegra20_cpu_shutdown)
cmp r0, #0
reteq lr @ must not be called for CPU 0
mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r2, =__tegra20_cpu1_resettable_status_offset
+ ldrh r2, 0f
mov r12, #CPU_RESETTABLE
strb r12, [r1, r2]
@@ -121,6 +121,7 @@ ENTRY(tegra20_cpu_shutdown)
beq .
ret lr
ENDPROC(tegra20_cpu_shutdown)
+0: .short __tegra20_cpu1_resettable_status_offset
#endif
#ifdef CONFIG_PM_SLEEP
@@ -181,6 +182,9 @@ ENTRY(tegra_pen_unlock)
ret lr
ENDPROC(tegra_pen_unlock)
+.L__tegra20_cpu1_resettable_status_offset:
+ .short __tegra20_cpu1_resettable_status_offset
+
/*
* tegra20_cpu_clear_resettable(void)
*
@@ -189,7 +193,7 @@ ENDPROC(tegra_pen_unlock)
*/
ENTRY(tegra20_cpu_clear_resettable)
mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r2, =__tegra20_cpu1_resettable_status_offset
+ ldrh r2, .L__tegra20_cpu1_resettable_status_offset
mov r12, #CPU_NOT_RESETTABLE
strb r12, [r1, r2]
ret lr
@@ -203,7 +207,7 @@ ENDPROC(tegra20_cpu_clear_resettable)
*/
ENTRY(tegra20_cpu_set_resettable_soon)
mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r2, =__tegra20_cpu1_resettable_status_offset
+ ldrh r2, .L__tegra20_cpu1_resettable_status_offset
mov r12, #CPU_RESETTABLE_SOON
strb r12, [r1, r2]
ret lr
@@ -217,7 +221,7 @@ ENDPROC(tegra20_cpu_set_resettable_soon)
*/
ENTRY(tegra20_cpu_is_resettable_soon)
mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r2, =__tegra20_cpu1_resettable_status_offset
+ ldrh r2, .L__tegra20_cpu1_resettable_status_offset
ldrb r12, [r1, r2]
cmp r12, #CPU_RESETTABLE_SOON
moveq r0, #1
@@ -238,11 +242,11 @@ ENTRY(tegra20_sleep_core_finish)
bl tegra_disable_clean_inv_dcache
mov r0, r4
- mov32 r3, tegra_shut_off_mmu
+ mov_l r3, tegra_shut_off_mmu
add r3, r3, r0
- mov32 r0, tegra20_tear_down_core
- mov32 r1, tegra20_iram_start
+ mov_l r0, tegra20_tear_down_core
+ mov_l r1, tegra20_iram_start
sub r0, r0, r1
mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
add r0, r0, r1
@@ -265,7 +269,7 @@ ENTRY(tegra20_sleep_cpu_secondary_finish)
bl tegra_disable_clean_inv_dcache
mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r4, =__tegra20_cpu1_resettable_status_offset
+ ldrh r4, .L__tegra20_cpu1_resettable_status_offset
mov r3, #CPU_RESETTABLE
strb r3, [r0, r4]
@@ -284,7 +288,7 @@ ENTRY(tegra20_sleep_cpu_secondary_finish)
bl tegra_pen_lock
mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r4, =__tegra20_cpu1_resettable_status_offset
+ ldrh r4, .L__tegra20_cpu1_resettable_status_offset
mov r3, #CPU_NOT_RESETTABLE
strb r3, [r0, r4]
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index dd4a67dabd91..478b2ca3ef6e 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -261,11 +261,11 @@ ENTRY(tegra30_sleep_core_finish)
mov32 r6, TEGRA_FLOW_CTRL_BASE
mov32 r7, TEGRA_TMRUS_BASE
- mov32 r3, tegra_shut_off_mmu
+ mov_l r3, tegra_shut_off_mmu
add r3, r3, r0
- mov32 r0, tegra30_tear_down_core
- mov32 r1, tegra30_iram_start
+ mov_l r0, tegra30_tear_down_core
+ mov_l r1, tegra30_iram_start
sub r0, r0, r1
mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
add r0, r0, r1
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index 5e3496753df1..785df3edc767 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -101,11 +101,11 @@ ENTRY(tegra_sleep_cpu_finish)
bl tegra_disable_clean_inv_dcache
mov r0, r4
- mov32 r6, tegra_tear_down_cpu
+ mov_l r6, tegra_tear_down_cpu
ldr r1, [r6]
add r1, r1, r0
- mov32 r3, tegra_shut_off_mmu
+ mov_l r3, tegra_shut_off_mmu
add r3, r3, r0
mov r0, r1
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 18/30] ARM: kernel: make vmlinux buildable as a PIE executable
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (16 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 17/30] arm-soc: tegra: make sleep asm code runtime relocatable Ard Biesheuvel
@ 2017-08-14 12:53 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 19/30] ARM: kernel: use PC-relative symbol references in MMU switch code Ard Biesheuvel
` (12 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:53 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Update the build flags and linker script to allow vmlinux to be build
as a PIE binary, which retains relocation information about absolute
symbol references so that they can be fixed up at runtime. This will
be used for implementing KASLR,
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/Kconfig | 4 ++++
arch/arm/Makefile | 5 +++++
arch/arm/include/asm/assembler.h | 7 ++++++-
arch/arm/kernel/vmlinux.lds.S | 9 +++++++++
include/linux/hidden.h | 21 ++++++++++++++++++++
5 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 61a0cb15067e..300add3b8023 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2085,6 +2085,10 @@ config DMI
firmware need to be enabled. This would require the DMI subsystem
to be enabled much earlier than we do on ARM, which is non-trivial.
+config RELOCATABLE
+ bool
+ select HAVE_ARCH_PREL32_RELOCATIONS
+
endmenu
menu "CPU Power Management"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 47d3a1ab08d2..88d9c33e24f5 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -52,6 +52,11 @@ AS += -EL
LD += -EL
endif
+ifeq ($(CONFIG_RELOCATABLE),y)
+KBUILD_CFLAGS += -include $(srctree)/include/linux/hidden.h -fpic
+LDFLAGS_vmlinux += -pie -shared -Bsymbolic
+endif
+
#
# The Scalar Replacement of Aggregates (SRA) optimization pass in GCC 4.9 and
# later may result in code being generated that handles signed short and signed
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 09b6b28f2595..b2254c1dc2de 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -550,7 +550,12 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
* mov_l - move a constant value or [relocated] address into a register
*/
.macro mov_l, dst:req, imm:req, cond
- .if __LINUX_ARM_ARCH__ < 7
+ .if CONFIG_RELOCATABLE == 1
+ ldr_l \dst, 333f, \cond
+ .section ".data.rel.ro.local", "aw", %progbits
+333: .long \imm
+ .previous
+ .elseif __LINUX_ARM_ARCH__ < 7
ldr\cond \dst, =\imm
.else
W(movw\cond\()) \dst, #:lower16:\imm
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index c83a7ba737d6..5853d4be2067 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -89,6 +89,9 @@ SECTIONS
#endif
*(.discard)
*(.discard.*)
+ *(.ARM.exidx.discard.text)
+ *(.interp .dynamic)
+ *(.dynsym .dynstr .hash)
}
. = PAGE_OFFSET + TEXT_OFFSET;
@@ -209,6 +212,12 @@ SECTIONS
__smpalt_end = .;
}
#endif
+ .rel.dyn : ALIGN(8) {
+ __rel_begin = .;
+ *(.rel .rel.* .rel.dyn)
+ }
+ __rel_end = ADDR(.rel.dyn) + SIZEOF(.rel.dyn);
+
.init.pv_table : {
__pv_table_begin = .;
*(.pv_table)
diff --git a/include/linux/hidden.h b/include/linux/hidden.h
new file mode 100644
index 000000000000..49b7823eed6e
--- /dev/null
+++ b/include/linux/hidden.h
@@ -0,0 +1,21 @@
+
+/*
+ * GCC assumes that we are building shared libraries or hosted binaries
+ * when the -fpic or -fpie switches are used. This results in all references
+ * to symbols with external linkage to be redirected via entries in the global
+ * offset table (GOT), which keeps .text pages clean and reduces the footprint
+ * of CoWed dirty pages to the GOT itself. It also allows symbol preemption,
+ * which is mandatory under ELF rules for shared libraries.
+ *
+ * For the kernel, we use PIC so that we can relocate the executable image at
+ * runtime. This does not involve CoW or symbol preemption, and we'd rather
+ * have relative references instead of absolute ones whenever possible.
+ * So set the default visibility to hidden: this informs the compiler that
+ * none of our symbols will ever be exported from a shared library, allowing
+ * it to use relative references where possible.
+ *
+ * Note that simply passing -fvisibility=hidden is not sufficient to achieve
+ * this: In that case, definitions will be marked hidden, but declarations
+ * will not, and we still end up with GOT entries unnecessarily.
+ */
+#pragma GCC visibility push(hidden)
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 19/30] ARM: kernel: use PC-relative symbol references in MMU switch code
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (17 preceding siblings ...)
2017-08-14 12:53 ` [kernel-hardening] [PATCH 18/30] ARM: kernel: make vmlinux buildable as a PIE executable Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 20/30] ARM: kernel: use PC relative symbol references in suspend/resume code Ard Biesheuvel
` (11 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
To prepare for adding support for KASLR, which relocates all absolute
symbol references at runtime after the caches have been enabled,
update the MMU switch code to avoid using absolute symbol references
where possible. This ensures these quantities are invariant under
runtime relocation.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/head-common.S | 39 ++++++++------------
1 file changed, 15 insertions(+), 24 deletions(-)
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 06035488130c..b74477507a12 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -79,9 +79,10 @@ ENDPROC(__vet_atags)
*/
__INIT
__mmap_switched:
- adr r3, __mmap_switched_data
-
- ldmia r3!, {r4, r5, r6, r7}
+ adr_l r4, __data_loc
+ adr_l r5, _sdata
+ adr_l r6, __bss_start
+ adr_l r7, _end
cmp r4, r5 @ Copy data segment if needed
1: cmpne r5, r6
ldrne fp, [r4], #4
@@ -93,9 +94,17 @@ __mmap_switched:
strcc fp, [r6],#4
bcc 1b
- ARM( ldmia r3, {r4, r5, r6, r7, sp})
- THUMB( ldmia r3, {r4, r5, r6, r7} )
- THUMB( ldr sp, [r3, #16] )
+ adr_l r3, init_thread_union + THREAD_START_SP
+ mov sp, r3
+ adr_l r4, processor_id
+ adr_l r5, __machine_arch_type
+ adr_l r6, __atags_pointer
+#ifdef CONFIG_CPU_CP15
+ adr_l r7, cr_alignment
+#else
+ mov r7, #0
+#endif
+
str r9, [r4] @ Save processor ID
str r1, [r5] @ Save machine type
str r2, [r6] @ Save atags pointer
@@ -104,24 +113,6 @@ __mmap_switched:
b start_kernel
ENDPROC(__mmap_switched)
- .align 2
- .type __mmap_switched_data, %object
-__mmap_switched_data:
- .long __data_loc @ r4
- .long _sdata @ r5
- .long __bss_start @ r6
- .long _end @ r7
- .long processor_id @ r4
- .long __machine_arch_type @ r5
- .long __atags_pointer @ r6
-#ifdef CONFIG_CPU_CP15
- .long cr_alignment @ r7
-#else
- .long 0 @ r7
-#endif
- .long init_thread_union + THREAD_START_SP @ sp
- .size __mmap_switched_data, . - __mmap_switched_data
-
/*
* This provides a C-API version of __lookup_processor_type
*/
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 20/30] ARM: kernel: use PC relative symbol references in suspend/resume code
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (18 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 19/30] ARM: kernel: use PC-relative symbol references in MMU switch code Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 16:02 ` [kernel-hardening] " Nicolas Pitre
2017-08-14 12:54 ` [kernel-hardening] [PATCH 21/30] ARM: mm: export default vmalloc base address Ard Biesheuvel
` (10 subsequent siblings)
30 siblings, 1 reply; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Replace some unnecessary absolute references with relative ones. Also,
to prepare for runtime relocation, which occurs with the caches on,
defer taking the absolute address of cpu_resume_after_mmu() until after
the MMU is enabled.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/sleep.S | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 3026b119d3ff..9efd1c7d3552 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -60,18 +60,17 @@
ENTRY(__cpu_suspend)
stmfd sp!, {r4 - r11, lr}
#ifdef MULTI_CPU
- ldr r10, =processor
- ldr r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
+ ldr_l r4, processor + CPU_SLEEP_SIZE @ size of CPU sleep state
#else
- ldr r4, =cpu_suspend_size
+ adr_l r4, cpu_suspend_size
#endif
mov r5, sp @ current virtual SP
add r4, r4, #12 @ Space for pgd, virt sp, phys resume fn
sub sp, sp, r4 @ allocate CPU state on stack
- ldr r3, =sleep_save_sp
+ adr_l r3, sleep_save_sp
stmfd sp!, {r0, r1} @ save suspend func arg and pointer
ldr r3, [r3, #SLEEP_SAVE_SP_VIRT]
- ALT_SMP(ldr r0, =mpidr_hash)
+ ALT_SMP(adr_l r0, mpidr_hash)
ALT_UP_B(1f)
/* This ldmia relies on the memory layout of the mpidr_hash struct */
ldmia r0, {r1, r6-r8} @ r1 = mpidr mask (r6,r7,r8) = l[0,1,2] shifts
@@ -100,13 +99,13 @@ ENDPROC(cpu_suspend_abort)
.align 5
.pushsection .idmap.text,"ax"
ENTRY(cpu_resume_mmu)
- ldr r3, =cpu_resume_after_mmu
instr_sync
mcr p15, 0, r0, c1, c0, 0 @ turn on MMU, I-cache, etc
mrc p15, 0, r0, c0, c0, 0 @ read id reg
instr_sync
mov r0, r0
mov r0, r0
+ ldr r3, =cpu_resume_after_mmu
ret r3 @ jump to virtual address
ENDPROC(cpu_resume_mmu)
.popsection
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 21/30] ARM: mm: export default vmalloc base address
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (19 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 20/30] ARM: kernel: use PC relative symbol references in suspend/resume code Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 22/30] ARM: kernel: refer to swapper_pg_dir via its symbol Ard Biesheuvel
` (9 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
In order for the EFI stub to be able to decide over what range to
randomize the load address of the kernel, expose the definition of
the default vmalloc base address as VMALLOC_DEFAULT_BASE.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/include/asm/pgtable.h | 1 +
arch/arm/mm/mmu.c | 3 +--
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 1c462381c225..a0d4a63a6516 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -45,6 +45,7 @@
#define VMALLOC_OFFSET (8*1024*1024)
#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#define VMALLOC_END 0xff800000UL
+#define VMALLOC_DEFAULT_BASE (VMALLOC_END - (240 << 20) - VMALLOC_OFFSET)
#define LIBRARY_TEXT_START 0x0c000000
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e46a6a446cdd..566f7e657931 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1128,8 +1128,7 @@ void __init debug_ll_io_init(void)
}
#endif
-static void * __initdata vmalloc_min =
- (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
+static void * __initdata vmalloc_min = (void *)VMALLOC_DEFAULT_BASE;
/*
* vmalloc=size forces the vmalloc area to be exactly 'size'
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 22/30] ARM: kernel: refer to swapper_pg_dir via its symbol
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (20 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 21/30] ARM: mm: export default vmalloc base address Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 23/30] ARM: kernel: implement randomization of the kernel load address Ard Biesheuvel
` (8 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
The location of swapper_pg_dir is relative to the kernel, not to
PAGE_OFFSET or PHYS_OFFSET. So define the symbol relative to the
start of the kernel image, and refer to it via its name.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/head.S | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 5d685e86148c..71bc0d037bc9 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -48,14 +48,6 @@
#define PMD_ORDER 2
#endif
- .globl swapper_pg_dir
- .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE
-
- .macro pgtbl, rd, phys
- add \rd, \phys, #TEXT_OFFSET
- sub \rd, \rd, #PG_DIR_SIZE
- .endm
-
/*
* Kernel startup entry point.
* ---------------------------
@@ -77,6 +69,9 @@
.arm
__HEAD
+ .globl swapper_pg_dir
+ .equ swapper_pg_dir, . - PG_DIR_SIZE
+
ENTRY(stext)
ARM_BE8(setend be ) @ ensure we are in BE8 mode
@@ -172,7 +167,7 @@ ENDPROC(stext)
* r4 = physical page table address
*/
__create_page_tables:
- pgtbl r4, r8 @ page table address
+ adr_l r4, swapper_pg_dir @ page table address
/*
* Clear the swapper page table
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 23/30] ARM: kernel: implement randomization of the kernel load address
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (21 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 22/30] ARM: kernel: refer to swapper_pg_dir via its symbol Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 24/30] ARM: decompressor: explicitly map decompressor binary cacheable Ard Biesheuvel
` (7 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
This implements randomization of the placement of the kernel image
inside the lowmem region. It is intended to work together with the
decompressor to place the kernel at an offset in physical memory
that is a multiple of 2 MB, and to take the same offset into account
when creating the virtual mapping.
This uses runtime relocation of the kernel built as a PIE binary, to
fix up all absolute symbol references to refer to their runtime virtual
address. The physical-to-virtual mapping remains unchanged.
In order to allow the decompressor to hand over to the core kernel
without making assumptions that are not guaranteed to hold when
invoking the core kernel directly using bootloaders that are not
KASLR aware, the KASLR offset is expected to be placed in r3 when
entering the kernel 4 bytes past the entry point, skipping the first
instruction.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/Kconfig | 15 +++
arch/arm/kernel/head.S | 103 ++++++++++++++++++--
2 files changed, 109 insertions(+), 9 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 300add3b8023..0d7b40f1061d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1825,6 +1825,21 @@ config XEN
help
Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
+config RANDOMIZE_BASE
+ bool "Randomize the address of the kernel image"
+ depends on MMU && AUTO_ZRELADDR
+ depends on !XIP_KERNEL && !ZBOOT_ROM && !HAVE_TCM
+ select RELOCATABLE
+ help
+ Randomizes the virtual and physical address at which the kernel
+ image is loaded, as a security feature that deters exploit attempts
+ relying on knowledge of the location of kernel internals.
+
+ This relies on the UEFI stub to invoke the EFI_RNG_PROTOCOL to
+ randomize the load address of the decompressed kernel in the
+ physical space. The same offset is applied to the virtual mapping
+ of the kernel in the virtual space by the kernel proper.
+
endmenu
menu "Boot options"
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 71bc0d037bc9..0795da990dde 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -48,6 +48,28 @@
#define PMD_ORDER 2
#endif
+ .macro get_kaslr_offset, reg
+#ifdef CONFIG_RANDOMIZE_BASE
+ ldr_l \reg, __kaslr_offset
+#else
+ mov \reg, #0
+#endif
+ .endm
+
+ .macro add_kaslr_offset, reg, tmp
+#ifdef CONFIG_RANDOMIZE_BASE
+ get_kaslr_offset \tmp
+ add \reg, \reg, \tmp
+#endif
+ .endm
+
+ .macro sub_kaslr_offset, reg, tmp
+#ifdef CONFIG_RANDOMIZE_BASE
+ get_kaslr_offset \tmp
+ sub \reg, \reg, \tmp
+#endif
+ .endm
+
/*
* Kernel startup entry point.
* ---------------------------
@@ -73,6 +95,7 @@
.equ swapper_pg_dir, . - PG_DIR_SIZE
ENTRY(stext)
+ mov r3, #0 @ normal entry point - clear r3
ARM_BE8(setend be ) @ ensure we are in BE8 mode
THUMB( badr r9, 1f ) @ Kernel is always entered in ARM.
@@ -80,6 +103,16 @@ ENTRY(stext)
THUMB( .thumb ) @ switch to Thumb now.
THUMB(1: )
+#ifdef CONFIG_RANDOMIZE_BASE
+ str_l r3, __kaslr_offset, r9 @ offset in r3 if entered via kaslr ep
+
+ .section ".bss", "aw", %nobits
+ .align 2
+__kaslr_offset:
+ .long 0 @ will be wiped before entering C code
+ .previous
+#endif
+
#ifdef CONFIG_ARM_VIRT_EXT
bl __hyp_stub_install
#endif
@@ -103,6 +136,7 @@ ENTRY(stext)
#ifndef CONFIG_XIP_KERNEL
adr_l r8, _text @ __pa(_text)
sub r8, r8, #TEXT_OFFSET @ PHYS_OFFSET
+ sub_kaslr_offset r8, r12
#else
ldr r8, =PLAT_PHYS_OFFSET @ always constant in this case
#endif
@@ -139,8 +173,8 @@ ENTRY(stext)
* r0 will hold the CPU control register value, r1, r2, r4, and
* r9 will be preserved. r5 will also be preserved if LPAE.
*/
- ldr r13, =__mmap_switched @ address to jump to after
- @ mmu has been enabled
+ adr_l lr, __primary_switch @ address to jump to after
+ mov r13, lr @ mmu has been enabled
badr lr, 1f @ return (PIC) address
#ifdef CONFIG_ARM_LPAE
mov r5, #0 @ high TTBR0
@@ -151,7 +185,8 @@ ENTRY(stext)
ldr r12, [r10, #PROCINFO_INITFUNC]
add r12, r12, r10
ret r12
-1: b __enable_mmu
+1: get_kaslr_offset r12 @ get before turning MMU on
+ b __enable_mmu
ENDPROC(stext)
.ltorg
@@ -230,9 +265,14 @@ __create_page_tables:
/*
* Map our RAM from the start to the end of the kernel .bss section.
*/
- add r0, r4, #PAGE_OFFSET >> (SECTION_SHIFT - PMD_ORDER)
- ldr r6, =(_end - 1)
- orr r3, r8, r7
+ get_kaslr_offset r3
+ add r0, r3, #PAGE_OFFSET
+ add r0, r4, r0, lsr #(SECTION_SHIFT - PMD_ORDER)
+ adr_l r6, _end - 1
+ sub r6, r6, r8
+ add r6, r6, #PAGE_OFFSET
+ add r3, r3, r8
+ orr r3, r3, r7
add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)
1: str r3, [r0], #1 << PMD_ORDER
add r3, r3, #1 << SECTION_SHIFT
@@ -376,7 +416,7 @@ ENTRY(secondary_startup)
* Use the page tables supplied from __cpu_up.
*/
adr_l r3, secondary_data
- mov_l r12, __secondary_switched
+ adr_l r12, __secondary_switch
ldrd r4, [r3, #0] @ get secondary_data.pgdir
ARM_BE8(eor r4, r4, r5) @ Swap r5 and r4 in BE:
ARM_BE8(eor r5, r4, r5) @ it can be done in 3 steps
@@ -414,6 +454,7 @@ ENDPROC(__secondary_switched)
* r4 = TTBR pointer (low word)
* r5 = TTBR pointer (high word if LPAE)
* r9 = processor ID
+ * r12 = KASLR offset
* r13 = *virtual* address to jump to upon completion
*/
__enable_mmu:
@@ -451,6 +492,7 @@ ENDPROC(__enable_mmu)
* r1 = machine ID
* r2 = atags or dtb pointer
* r9 = processor ID
+ * r12 = KASLR offset
* r13 = *virtual* address to jump to upon completion
*
* other registers depend on the function called upon completion
@@ -466,10 +508,52 @@ ENTRY(__turn_mmu_on)
mov r3, r3
mov r3, r13
ret r3
-__turn_mmu_on_end:
ENDPROC(__turn_mmu_on)
- .popsection
+__primary_switch:
+#ifdef CONFIG_RELOCATABLE
+ adr_l r7, _text @ r7 := __pa(_text)
+ sub r7, r7, #TEXT_OFFSET @ r7 := PHYS_OFFSET
+
+ adr_l r5, __rel_begin
+ adr_l r6, __rel_end
+ sub r5, r5, r7
+ sub r6, r6, r7
+
+ add r5, r5, #PAGE_OFFSET
+ add r6, r6, #PAGE_OFFSET
+ add r5, r5, r12
+ add r6, r6, r12
+
+ adr_l r3, __stubs_start @ __pa(__stubs_start)
+ sub r3, r3, r7 @ offset of __stubs_start
+ add r3, r3, #PAGE_OFFSET @ __va(__stubs_start)
+ sub r3, r3, #0xffff1000 @ subtract VA of stubs section
+
+0: cmp r5, r6
+ bge 1f
+ ldm r5!, {r7, r8} @ load next relocation entry
+ cmp r8, #23 @ R_ARM_RELATIVE
+ bne 0b
+ cmp r7, #0xff000000 @ vector page?
+ addgt r7, r7, r3 @ fix up VA offset
+ ldr r8, [r7, r12]
+ add r8, r8, r12
+ str r8, [r7, r12]
+ b 0b
+1:
+#endif
+ ldr pc, =__mmap_switched
+ENDPROC(__primary_switch)
+
+#ifdef CONFIG_SMP
+__secondary_switch:
+ ldr pc, =__secondary_switched
+ENDPROC(__secondary_switch)
+#endif
+ .ltorg
+__turn_mmu_on_end:
+ .popsection
#ifdef CONFIG_SMP_ON_UP
__HEAD
@@ -570,6 +654,7 @@ __fixup_pv_table:
adr_l r6, __pv_phys_pfn_offset
adr_l r7, __pv_offset @ __pa(__pv_offset)
mov_l r3, __pv_offset @ __va(__pv_offset)
+ add_kaslr_offset r3, ip
mvn ip, #0
subs r3, r7, r3 @ PHYS_OFFSET - PAGE_OFFSET
mov r0, r8, lsr #PAGE_SHIFT @ convert to PFN
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 24/30] ARM: decompressor: explicitly map decompressor binary cacheable
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (22 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 23/30] ARM: kernel: implement randomization of the kernel load address Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 25/30] ARM: compressed: factor out zImage header and make it extensible Ard Biesheuvel
` (6 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
When randomizing the kernel load address, there may be a large
distance in memory between the decompressor binary and its payload
and the destination area in memory. Ensure that the decompressor
itself is mapped cacheable in this case, by tweaking the existing
routine that takes care of this for XIP decompressors.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/boot/compressed/head.S | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 5884e8151376..583cc6899d98 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -706,20 +706,24 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size
teq r0, r2
bne 1b
/*
- * If ever we are running from Flash, then we surely want the cache
- * to be enabled also for our execution instance... We map 2MB of it
- * so there is no map overlap problem for up to 1 MB compressed kernel.
- * If the execution is in RAM then we would only be duplicating the above.
+ * Make sure our entire executable image (including payload) is mapped
+ * cacheable, in case it is located outside the region we covered above.
+ * (This may be the case if running from flash or with randomization enabled)
+ * If the regions happen to overlap, we just duplicate some of the above.
*/
orr r1, r6, #0x04 @ ensure B is set for this
orr r1, r1, #3 << 10
mov r2, pc
+ adr_l r9, _end
mov r2, r2, lsr #20
+ mov r9, r9, lsr #20
orr r1, r1, r2, lsl #20
add r0, r3, r2, lsl #2
- str r1, [r0], #4
+ add r9, r3, r9, lsl #2
+0: str r1, [r0], #4
add r1, r1, #1048576
- str r1, [r0]
+ cmp r0, r9
+ bls 0b
mov pc, lr
ENDPROC(__setup_mmu)
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 25/30] ARM: compressed: factor out zImage header and make it extensible
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (23 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 24/30] ARM: decompressor: explicitly map decompressor binary cacheable Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 26/30] ARM: decompressor: add KASLR support Ard Biesheuvel
` (5 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
To prepare for adding metadata to the zImage to put KASLR randomization
under the control of the bootloader, factor out the zImage header, and
make it extensible by adding two new fields: a magic number that cannot
be mistaken for a valid instruction, to prevent misidentification, and
an offset into the binary where an array of optional headers is placed.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/boot/compressed/head.S | 7 +---
arch/arm/boot/compressed/vmlinux.lds.S | 5 ++-
arch/arm/include/asm/zimage.h | 39 ++++++++++++++++++++
3 files changed, 45 insertions(+), 6 deletions(-)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 583cc6899d98..e451738d8954 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -11,6 +11,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/v7m.h>
+#include <asm/zimage.h>
#include "efi-header.S"
@@ -139,11 +140,7 @@ start:
#endif
W(b) 1f
- .word _magic_sig @ Magic numbers to help the loader
- .word _magic_start @ absolute load/run zImage address
- .word _magic_end @ zImage end address
- .word 0x04030201 @ endianness flag
-
+ __ZIMAGE_HEADER
__EFI_HEADER
1:
ARM_BE8( setend be ) @ go BE8 if compiled for BE8
diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S
index 81c493156ce8..27696bc315d3 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -6,6 +6,8 @@
* published by the Free Software Foundation.
*/
+#include <asm/zimage.h>
+
#ifdef CONFIG_CPU_ENDIAN_BE8
#define ZIMAGE_MAGIC(x) ( (((x) >> 24) & 0x000000ff) | \
(((x) >> 8) & 0x0000ff00) | \
@@ -72,9 +74,10 @@ SECTIONS
.pad : { BYTE(0); . = ALIGN(8); }
_edata = .;
- _magic_sig = ZIMAGE_MAGIC(0x016f2818);
+ _magic_sig = ZIMAGE_MAGIC(ZIMAGE_HEADER_MAGIC);
_magic_start = ZIMAGE_MAGIC(_start);
_magic_end = ZIMAGE_MAGIC(_edata);
+ _magic_opt_sig = ZIMAGE_MAGIC(ZIMAGE_OPTIONAL_HEADER_MAGIC);
. = BSS_START;
__bss_start = .;
diff --git a/arch/arm/include/asm/zimage.h b/arch/arm/include/asm/zimage.h
new file mode 100644
index 000000000000..ff65cc3bb716
--- /dev/null
+++ b/arch/arm/include/asm/zimage.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 Linaro Ltd; <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ASM_ZIMAGE_H
+#define __ASM_ZIMAGE_H
+
+#define ZIMAGE_HEADER_MAGIC 0x016f2818
+#define ZIMAGE_OPTIONAL_HEADER_MAGIC 0xe7fedef0
+
+#if defined(__ASSEMBLY__) && !defined(LINKER_SCRIPT)
+
+ .macro __ZIMAGE_HEADER
+ .word _magic_sig @ Magic numbers to help the loader
+ .word _magic_start @ absolute load/run zImage address
+ .word _magic_end @ zImage end address
+ .word 0x04030201 @ endianness flag
+
+ /* optional headers */
+ .word _magic_opt_sig @ optional header magic number
+ .word __zimage_opt_header - .
+
+ .pushsection ".rodata", "a", %progbits
+__zimage_opt_header:
+ /*
+ * Each header starts with a u16[2] containing id and size of the
+ * entire header, including the u16[] itself.
+ */
+ .long 0xffffffff @ end of optional headers
+ .popsection
+ .endm
+
+#endif
+#endif
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 26/30] ARM: decompressor: add KASLR support
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (24 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 25/30] ARM: compressed: factor out zImage header and make it extensible Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 27/30] efi/libstub: add 'max' parameter to efi_random_alloc() Ard Biesheuvel
` (4 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Add support to the decompressor to load the kernel at a randomized
offset, and invoke the kernel proper while passing on the information
about the offset at which the kernel was loaded.
This implementation was created with the UEFI stub in mind (which has
a rich execution environment that provides access to the platforms
random number generators), which will assign the kaslr_offset variable
directly. However, to allow other bootloaders to use this facility,
the KASLR offset is exposed via a zImage header field as well.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/boot/compressed/head.S | 8 ++++++
arch/arm/include/asm/zimage.h | 30 ++++++++++++++++++--
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index e451738d8954..7111a2cbef95 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -200,6 +200,10 @@ not_angel:
*/
mov r4, pc
and r4, r4, #0xf8000000
+#ifdef CONFIG_RANDOMIZE_BASE
+ ldr_l r0, kaslr_offset
+ add r4, r4, r0
+#endif
/* Determine final kernel image address. */
add r4, r4, #TEXT_OFFSET
#else
@@ -1353,6 +1357,10 @@ __hyp_reentry_vectors:
__enter_kernel:
mov r0, #0 @ must be 0
+#ifdef CONFIG_RANDOMIZE_BASE
+ ldr_l r3, kaslr_offset
+ add r4, r4, #4 @ skip first instruction
+#endif
ARM( mov pc, r4 ) @ call kernel
M_CLASS( add r4, r4, #1 ) @ enter in Thumb mode for M class
THUMB( bx r4 ) @ entry point is always ARM for A/R classes
diff --git a/arch/arm/include/asm/zimage.h b/arch/arm/include/asm/zimage.h
index ff65cc3bb716..554a48ddcfd8 100644
--- a/arch/arm/include/asm/zimage.h
+++ b/arch/arm/include/asm/zimage.h
@@ -10,10 +10,15 @@
#ifndef __ASM_ZIMAGE_H
#define __ASM_ZIMAGE_H
+#include <asm/pgtable.h>
+
#define ZIMAGE_HEADER_MAGIC 0x016f2818
#define ZIMAGE_OPTIONAL_HEADER_MAGIC 0xe7fedef0
-#if defined(__ASSEMBLY__) && !defined(LINKER_SCRIPT)
+#define ZIMAGE_OPT_HDR_ID_KASLR 0x1
+
+#ifndef LINKER_SCRIPT
+#ifdef __ASSEMBLY__
.macro __ZIMAGE_HEADER
.word _magic_sig @ Magic numbers to help the loader
@@ -31,9 +36,30 @@
* Each header starts with a u16[2] containing id and size of the
* entire header, including the u16[] itself.
*/
+
+#ifdef CONFIG_RANDOMIZE_BASE
+0: .short ZIMAGE_OPT_HDR_ID_KASLR
+ .short __kaslr_hdr_size
+
+ /*
+ * The KASLR header carries the information needed by the bootloader
+ * to choose a randomization offset, and record it in the offset
+ * field below.
+ */
+ENTRY(kaslr_offset)
+ .long 0 @ kaslr offset
+ .long CONFIG_PAGE_OFFSET @ page offset
+ .long VMALLOC_DEFAULT_BASE @ start of vmalloc area
+ .long SECTION_SIZE @ kaslr granularity
+ .set __kaslr_hdr_size, . - 0b
+#endif
+
.long 0xffffffff @ end of optional headers
.popsection
.endm
-#endif
+#else /* __ASSEMBLY__ */
+extern u32 kaslr_offset;
+#endif /* __ASSEMBLY__ */
+#endif /* LINKER_SCRIPT */
#endif
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 27/30] efi/libstub: add 'max' parameter to efi_random_alloc()
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (25 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 26/30] ARM: decompressor: add KASLR support Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 28/30] efi/libstub: check for vmalloc= command line argument Ard Biesheuvel
` (3 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Add an upper limit to efi_random_alloc() so we can use it to randomly
allocate the ARM kernel in lowmem.
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
drivers/firmware/efi/libstub/arm64-stub.c | 2 +-
drivers/firmware/efi/libstub/efistub.h | 3 ++-
drivers/firmware/efi/libstub/random.c | 10 ++++++----
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index b4c2589d7c91..940766f90adb 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -94,7 +94,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
*reserve_size = kernel_memsize + offset;
status = efi_random_alloc(sys_table_arg, *reserve_size,
MIN_KIMG_ALIGN, reserve_addr,
- (u32)phys_seed);
+ (u32)phys_seed, ULONG_MAX);
*image_addr = *reserve_addr + offset;
} else {
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 83f268c05007..3a670a5f759f 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -60,7 +60,8 @@ efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table,
efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
unsigned long size, unsigned long align,
- unsigned long *addr, unsigned long random_seed);
+ unsigned long *addr, unsigned long random_seed,
+ unsigned long max);
efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 7e72954d5860..85b80a4a85b3 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -42,7 +42,8 @@ efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table_arg,
*/
static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
unsigned long size,
- unsigned long align_shift)
+ unsigned long align_shift,
+ unsigned long max)
{
unsigned long align = 1UL << align_shift;
u64 first_slot, last_slot, region_end;
@@ -50,7 +51,7 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
if (md->type != EFI_CONVENTIONAL_MEMORY)
return 0;
- region_end = min((u64)ULONG_MAX, md->phys_addr + md->num_pages*EFI_PAGE_SIZE - 1);
+ region_end = min((u64)max, md->phys_addr + md->num_pages*EFI_PAGE_SIZE - 1);
first_slot = round_up(md->phys_addr, align);
last_slot = round_down(region_end - size + 1, align);
@@ -73,7 +74,8 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
unsigned long size,
unsigned long align,
unsigned long *addr,
- unsigned long random_seed)
+ unsigned long random_seed,
+ unsigned long max)
{
unsigned long map_size, desc_size, total_slots = 0, target_slot;
unsigned long buff_size;
@@ -101,7 +103,7 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
efi_memory_desc_t *md = (void *)memory_map + map_offset;
unsigned long slots;
- slots = get_entry_num_slots(md, size, ilog2(align));
+ slots = get_entry_num_slots(md, size, ilog2(align), max);
MD_NUM_SLOTS(md) = slots;
total_slots += slots;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 28/30] efi/libstub: check for vmalloc= command line argument
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (26 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 27/30] efi/libstub: add 'max' parameter to efi_random_alloc() Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 29/30] efi/libstub: arm: reserve bootloader supplied initrd in memory map Ard Biesheuvel
` (2 subsequent siblings)
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Check for and record the presence of a vmalloc= argument on the
kernel command line. We need this information on ARM systems when
implementing KASLR, given that the size of the vmalloc region will
affect the size of the lowmem region, therefore affecting the
available randomization range as well.
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
drivers/firmware/efi/libstub/efi-stub-helper.c | 9 +++++++++
drivers/firmware/efi/libstub/efistub.h | 1 +
2 files changed, 10 insertions(+)
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index b0184360efc6..f3e9d43030ac 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -34,6 +34,7 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
static int __section(.data) __nokaslr;
static int __section(.data) __quiet;
+static int __section(.data) __vmalloc_arg;
int __pure nokaslr(void)
{
@@ -43,6 +44,10 @@ int __pure is_quiet(void)
{
return __quiet;
}
+int __pure have_vmalloc(void)
+{
+ return __vmalloc_arg;
+}
#define EFI_MMAP_NR_SLACK_SLOTS 8
@@ -433,6 +438,10 @@ efi_status_t efi_parse_options(char const *cmdline)
if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
__quiet = 1;
+ str = strstr(cmdline, "vmalloc=");
+ if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
+ __vmalloc_arg = 1;
+
/*
* If no EFI parameters were specified on the cmdline we've got
* nothing to do.
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 3a670a5f759f..aaf2aeb785ea 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -26,6 +26,7 @@
extern int __pure nokaslr(void);
extern int __pure is_quiet(void);
+extern int __pure have_vmalloc(void);
#define pr_efi(sys_table, msg) do { \
if (!is_quiet()) efi_printk(sys_table, "EFI stub: "msg); \
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 29/30] efi/libstub: arm: reserve bootloader supplied initrd in memory map
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (27 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 28/30] efi/libstub: check for vmalloc= command line argument Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-18 11:48 ` [kernel-hardening] " Ard Biesheuvel
2017-08-21 10:37 ` Mark Rutland
2017-08-14 12:54 ` [kernel-hardening] [PATCH 30/30] efi/libstub: arm: implement KASLR Ard Biesheuvel
2017-08-14 15:30 ` [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM Arnd Bergmann
30 siblings, 2 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
Under KASLR, the EFI stub may allocate the kernel anywhere in the
physical address space, which could be right on top of an initrd
if it was supplied by the bootloader (i.e., GRUB) in /chosen rather
than passed via the initrd= command line option. So allocate the
pages explicitly, this ensures that the random memory allocation
routine will disregard the region.
Note that this means that we need to defer the handle_kernel_image()
call.
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
drivers/firmware/efi/libstub/arm-stub.c | 51 ++++++++++++--------
drivers/firmware/efi/libstub/efistub.h | 3 ++
drivers/firmware/efi/libstub/fdt.c | 42 ++++++++++++++++
3 files changed, 75 insertions(+), 21 deletions(-)
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 8181ac179d14..f5ef5ccd5f45 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -133,6 +133,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
unsigned long reserve_size = 0;
enum efi_secureboot_mode secure_boot;
struct screen_info *si;
+ bool have_chosen_initrd;
/* Check if we were booted by the EFI firmware */
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
@@ -183,15 +184,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
si = setup_graphics(sys_table);
- status = handle_kernel_image(sys_table, image_addr, &image_size,
- &reserve_addr,
- &reserve_size,
- dram_base, image);
- if (status != EFI_SUCCESS) {
- pr_efi_err(sys_table, "Failed to relocate kernel\n");
- goto fail_free_cmdline;
- }
-
secure_boot = efi_get_secureboot(sys_table);
/*
@@ -209,7 +201,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
if (status != EFI_SUCCESS) {
pr_efi_err(sys_table, "Failed to load device tree!\n");
- goto fail_free_image;
+ goto fail_free_cmdline;
}
}
@@ -222,16 +214,33 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
pr_efi(sys_table, "Using DTB from configuration table\n");
}
- if (!fdt_addr)
+ if (!fdt_addr) {
pr_efi(sys_table, "Generating empty DTB\n");
+ have_chosen_initrd = false;
+ } else {
+ status = efi_reserve_dtb_initrd(sys_table, (void *)fdt_addr);
+ have_chosen_initrd = (status != EFI_NOT_FOUND);
+ }
- status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
- efi_get_max_initrd_addr(dram_base,
- *image_addr),
- (unsigned long *)&initrd_addr,
- (unsigned long *)&initrd_size);
- if (status != EFI_SUCCESS)
- pr_efi_err(sys_table, "Failed initrd from command line!\n");
+ status = handle_kernel_image(sys_table, image_addr, &image_size,
+ &reserve_addr, &reserve_size,
+ dram_base, image);
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table, "Failed to relocate kernel\n");
+ goto fail_free_fdt;
+ }
+
+ if (!have_chosen_initrd) {
+ status = handle_cmdline_files(sys_table, image, cmdline_ptr,
+ "initrd=",
+ efi_get_max_initrd_addr(dram_base,
+ *image_addr),
+ (unsigned long *)&initrd_addr,
+ (unsigned long *)&initrd_size);
+ if (status != EFI_SUCCESS)
+ pr_efi_err(sys_table,
+ "Failed initrd from command line!\n");
+ }
efi_random_get_seed(sys_table);
@@ -272,11 +281,11 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
pr_efi_err(sys_table, "Failed to update FDT and exit boot services\n");
efi_free(sys_table, initrd_size, initrd_addr);
- efi_free(sys_table, fdt_size, fdt_addr);
-
-fail_free_image:
efi_free(sys_table, image_size, *image_addr);
efi_free(sys_table, reserve_size, reserve_addr);
+
+fail_free_fdt:
+ efi_free(sys_table, fdt_size, fdt_addr);
fail_free_cmdline:
free_screen_info(sys_table, si);
efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index aaf2aeb785ea..35b514d7d962 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -68,4 +68,7 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
+efi_status_t efi_reserve_dtb_initrd(efi_system_table_t *sys_table_arg,
+ const void *fdt);
+
#endif
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index 8830fa601e45..54408c95e094 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -385,3 +385,45 @@ void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size)
return fdt;
}
+
+efi_status_t efi_reserve_dtb_initrd(efi_system_table_t *sys_table_arg,
+ const void *fdt)
+{
+ int chosen, len;
+ const void *prop;
+ efi_physical_addr_t start, end;
+ unsigned long num_pages;
+ efi_status_t status;
+
+ chosen = fdt_path_offset(fdt, "/chosen");
+ if (chosen == -FDT_ERR_NOTFOUND)
+ return EFI_NOT_FOUND;
+
+ prop = fdt_getprop(fdt, chosen, "linux,initrd-start", &len);
+ if (!prop)
+ return EFI_NOT_FOUND;
+
+ start = (len == sizeof(fdt32_t)) ? fdt32_to_cpu(*(fdt32_t *)prop)
+ : fdt64_to_cpu(*(fdt64_t *)prop);
+
+ prop = fdt_getprop(fdt, chosen, "linux,initrd-end", &len);
+ if (!prop)
+ return EFI_NOT_FOUND;
+
+ end = (len == sizeof(fdt32_t)) ? fdt32_to_cpu(*(fdt32_t *)prop)
+ : fdt64_to_cpu(*(fdt64_t *)prop);
+
+ start = round_down(start, EFI_PAGE_SIZE);
+ num_pages = round_up(end - start, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+
+ status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
+ EFI_LOADER_DATA, num_pages, &start);
+
+ if (status != EFI_SUCCESS)
+ pr_efi_err(sys_table_arg,
+ "Failed to reserve initrd area found in /chosen\n");
+ else
+ pr_efi(sys_table_arg, "Using initrd found in /chosen\n");
+
+ return status;
+}
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] [PATCH 30/30] efi/libstub: arm: implement KASLR
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (28 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 29/30] efi/libstub: arm: reserve bootloader supplied initrd in memory map Ard Biesheuvel
@ 2017-08-14 12:54 ` Ard Biesheuvel
2017-08-14 15:30 ` [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM Arnd Bergmann
30 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 12:54 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
This wires up the new KASLR implementation for ARM to the random number
generator and memory allocation routines in the UEFI stub.
Given how the UEFI stub keeps track of the placement of the DTB and
potentially an initrd via its memory map, we can quite simply use
efi_random_alloc() to carve out a window for the kernel proper, and
inform the decompressor about this by setting the kaslr_offset variable
directly.
Since the presence of a vmalloc= command line option complicates the
calculations involved, let's just disable KASLR for now if a vmalloc=
command line argument was provided.
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
drivers/firmware/efi/libstub/arm32-stub.c | 46 +++++++++++++++++++-
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
index becbda445913..f812cbca08ee 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -8,6 +8,8 @@
*/
#include <linux/efi.h>
#include <asm/efi.h>
+#include <asm/pgtable.h>
+#include <asm/zimage.h>
#include "efistub.h"
@@ -200,6 +202,29 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
efi_loaded_image_t *image)
{
efi_status_t status;
+ u32 phys_seed = 0;
+
+ if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
+ if (have_vmalloc()) {
+ pr_efi(sys_table,
+ "vmalloc= command line argument found, disabling KASLR\n");
+ } else if (!nokaslr()) {
+ status = efi_get_random_bytes(sys_table,
+ sizeof(phys_seed),
+ (u8 *)&phys_seed);
+ if (status == EFI_NOT_FOUND) {
+ pr_efi(sys_table,
+ "EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
+ } else if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table,
+ "efi_get_random_bytes() failed\n");
+ return status;
+ }
+ } else {
+ pr_efi(sys_table,
+ "KASLR disabled on kernel command line\n");
+ }
+ }
/*
* Verify that the DRAM base address is compatible with the ARM
@@ -210,8 +235,25 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
*/
dram_base = round_up(dram_base, SZ_128M);
- status = reserve_kernel_base(sys_table, dram_base, reserve_addr,
- reserve_size);
+ if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE) || phys_seed == 0) {
+ status = reserve_kernel_base(sys_table, dram_base, reserve_addr,
+ reserve_size);
+ } else {
+ /* the end of the lowmem region */
+ unsigned long max = dram_base + VMALLOC_DEFAULT_BASE
+ - PAGE_OFFSET - 1;
+ /*
+ * The DTB and initrd are covered by allocations in the UEFI
+ * memory map, so we can create a random allocation for the
+ * uncompressed kernel, and inform the decompressor about the
+ * offset with respect to the base of memory.
+ */
+ *reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+ status = efi_random_alloc(sys_table, *reserve_size, SZ_2M,
+ reserve_addr, phys_seed, max);
+ kaslr_offset = *reserve_addr - dram_base;
+ }
+
if (status != EFI_SUCCESS) {
pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n");
return status;
--
2.11.0
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 01/30] asm-generic: add .data.rel.ro sections to __ro_after_init
2017-08-14 12:53 ` [kernel-hardening] [PATCH 01/30] asm-generic: add .data.rel.ro sections to __ro_after_init Ard Biesheuvel
@ 2017-08-14 14:26 ` Arnd Bergmann
0 siblings, 0 replies; 60+ messages in thread
From: Arnd Bergmann @ 2017-08-14 14:26 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Kernel Hardening, Linux ARM, Nicolas Pitre, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Mon, Aug 14, 2017 at 2:53 PM, Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:
> When running in PIC mode, the compiler will emit const structures
> containing runtime relocatable quantities into .data.rel.ro.* sections,
> so that the linker can be smart about placing them together in a segment
> that is read-write initially, and is remapped read-only afterwards. This
> is exactly what __ro_after_init aims to provide, so move these sections
> together.
>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 17/30] arm-soc: tegra: make sleep asm code runtime relocatable
2017-08-14 12:53 ` [kernel-hardening] [PATCH 17/30] arm-soc: tegra: make sleep asm code runtime relocatable Ard Biesheuvel
@ 2017-08-14 14:42 ` Dave Martin
2017-08-14 14:49 ` Ard Biesheuvel
0 siblings, 1 reply; 60+ messages in thread
From: Dave Martin @ 2017-08-14 14:42 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: kernel-hardening, Mark Rutland, Kees Cook, Arnd Bergmann,
Nicolas Pitre, Marc Zyngier, Russell King, Tony Lindgren,
Matt Fleming, Thomas Garnier, linux-arm-kernel
On Mon, Aug 14, 2017 at 01:53:58PM +0100, Ard Biesheuvel wrote:
> The PIE kernel build does not allow absolute references encoded in
> movw/movt instruction pairs, so use our mov_l macro instead (which
> will still use such a pair unless CONFIG_RELOCATABLE is defined)
>
> Also, avoid 32-bit absolute literals to refer to absolute symbols.
> Instead, use a 16 bit reference so that PIE linker cannot get
> confused whether the symbol reference is subject to relocation at
> runtime.
This sounds like we're papering over something.
If the linker is "confused", that sounds like we are either abusing
it somehow, or the linker is broken.
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> arch/arm/mach-tegra/sleep-tegra20.S | 22 ++++++++++++--------
> arch/arm/mach-tegra/sleep-tegra30.S | 6 +++---
> arch/arm/mach-tegra/sleep.S | 4 ++--
> 3 files changed, 18 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
> index 5c8e638ee51a..cab95de5c8f1 100644
> --- a/arch/arm/mach-tegra/sleep-tegra20.S
> +++ b/arch/arm/mach-tegra/sleep-tegra20.S
> @@ -99,7 +99,7 @@ ENTRY(tegra20_cpu_shutdown)
> cmp r0, #0
> reteq lr @ must not be called for CPU 0
> mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
> - ldr r2, =__tegra20_cpu1_resettable_status_offset
> + ldrh r2, 0f
> mov r12, #CPU_RESETTABLE
> strb r12, [r1, r2]
>
> @@ -121,6 +121,7 @@ ENTRY(tegra20_cpu_shutdown)
> beq .
> ret lr
> ENDPROC(tegra20_cpu_shutdown)
> +0: .short __tegra20_cpu1_resettable_status_offset
> #endif
>
> #ifdef CONFIG_PM_SLEEP
> @@ -181,6 +182,9 @@ ENTRY(tegra_pen_unlock)
> ret lr
> ENDPROC(tegra_pen_unlock)
>
> +.L__tegra20_cpu1_resettable_status_offset:
> + .short __tegra20_cpu1_resettable_status_offset
> +
> /*
> * tegra20_cpu_clear_resettable(void)
> *
> @@ -189,7 +193,7 @@ ENDPROC(tegra_pen_unlock)
> */
> ENTRY(tegra20_cpu_clear_resettable)
> mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
Can we simply port mov32 to mov_l? Or do we hit a problem with
multiplatform kernels where mov_l may involve a literal pool entry
(and does it matter)?
[...]
Cheers
---Dave
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 17/30] arm-soc: tegra: make sleep asm code runtime relocatable
2017-08-14 14:42 ` [kernel-hardening] " Dave Martin
@ 2017-08-14 14:49 ` Ard Biesheuvel
2017-08-14 15:29 ` Dave Martin
0 siblings, 1 reply; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 14:49 UTC (permalink / raw)
To: Dave Martin
Cc: Kernel Hardening, Mark Rutland, Kees Cook, Arnd Bergmann,
Nicolas Pitre, Marc Zyngier, Russell King, Tony Lindgren,
Matt Fleming, Thomas Garnier, linux-arm-kernel
On 14 August 2017 at 15:42, Dave Martin <Dave.Martin@arm.com> wrote:
> On Mon, Aug 14, 2017 at 01:53:58PM +0100, Ard Biesheuvel wrote:
>> The PIE kernel build does not allow absolute references encoded in
>> movw/movt instruction pairs, so use our mov_l macro instead (which
>> will still use such a pair unless CONFIG_RELOCATABLE is defined)
>>
>> Also, avoid 32-bit absolute literals to refer to absolute symbols.
>> Instead, use a 16 bit reference so that PIE linker cannot get
>> confused whether the symbol reference is subject to relocation at
>> runtime.
>
> This sounds like we're papering over something.
>
> If the linker is "confused", that sounds like we are either abusing
> it somehow, or the linker is broken.
>
There is some ambiguity in how SHN_ABS symbols are treated in shared
libraries and PIE executables.
https://sourceware.org/ml/binutils/2012-05/msg00019.html
I haven't confirmed whether it actually causes problems in this
particular case, but it is safer (and not entirely inappropriate) to
use a 16-bit field for a quantity that can easily fit one.
>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>> arch/arm/mach-tegra/sleep-tegra20.S | 22 ++++++++++++--------
>> arch/arm/mach-tegra/sleep-tegra30.S | 6 +++---
>> arch/arm/mach-tegra/sleep.S | 4 ++--
>> 3 files changed, 18 insertions(+), 14 deletions(-)
>>
>> diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
>> index 5c8e638ee51a..cab95de5c8f1 100644
>> --- a/arch/arm/mach-tegra/sleep-tegra20.S
>> +++ b/arch/arm/mach-tegra/sleep-tegra20.S
>> @@ -99,7 +99,7 @@ ENTRY(tegra20_cpu_shutdown)
>> cmp r0, #0
>> reteq lr @ must not be called for CPU 0
>> mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
>> - ldr r2, =__tegra20_cpu1_resettable_status_offset
>> + ldrh r2, 0f
>> mov r12, #CPU_RESETTABLE
>> strb r12, [r1, r2]
>>
>> @@ -121,6 +121,7 @@ ENTRY(tegra20_cpu_shutdown)
>> beq .
>> ret lr
>> ENDPROC(tegra20_cpu_shutdown)
>> +0: .short __tegra20_cpu1_resettable_status_offset
>> #endif
>>
>> #ifdef CONFIG_PM_SLEEP
>> @@ -181,6 +182,9 @@ ENTRY(tegra_pen_unlock)
>> ret lr
>> ENDPROC(tegra_pen_unlock)
>>
>> +.L__tegra20_cpu1_resettable_status_offset:
>> + .short __tegra20_cpu1_resettable_status_offset
>> +
>> /*
>> * tegra20_cpu_clear_resettable(void)
>> *
>> @@ -189,7 +193,7 @@ ENDPROC(tegra_pen_unlock)
>> */
>> ENTRY(tegra20_cpu_clear_resettable)
>> mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
>
> Can we simply port mov32 to mov_l? Or do we hit a problem with
> multiplatform kernels where mov_l may involve a literal pool entry
> (and does it matter)?
>
The only place where it matters is in code that lives in idmap.text,
since the relative reference will point to the ID mapped alias of a
section that is not covered by the ID ID map. I think we should be
able to use mov_l everywhere else, and it should do the right thing
for ordinary and PIE builds
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 17/30] arm-soc: tegra: make sleep asm code runtime relocatable
2017-08-14 14:49 ` Ard Biesheuvel
@ 2017-08-14 15:29 ` Dave Martin
0 siblings, 0 replies; 60+ messages in thread
From: Dave Martin @ 2017-08-14 15:29 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Mark Rutland, Kees Cook, Arnd Bergmann, Nicolas Pitre,
Marc Zyngier, Kernel Hardening, Russell King, Tony Lindgren,
linux-arm-kernel, Thomas Garnier, Matt Fleming
On Mon, Aug 14, 2017 at 03:49:15PM +0100, Ard Biesheuvel wrote:
> On 14 August 2017 at 15:42, Dave Martin <Dave.Martin@arm.com> wrote:
> > On Mon, Aug 14, 2017 at 01:53:58PM +0100, Ard Biesheuvel wrote:
> >> The PIE kernel build does not allow absolute references encoded in
> >> movw/movt instruction pairs, so use our mov_l macro instead (which
> >> will still use such a pair unless CONFIG_RELOCATABLE is defined)
> >>
> >> Also, avoid 32-bit absolute literals to refer to absolute symbols.
> >> Instead, use a 16 bit reference so that PIE linker cannot get
> >> confused whether the symbol reference is subject to relocation at
> >> runtime.
> >
> > This sounds like we're papering over something.
> >
> > If the linker is "confused", that sounds like we are either abusing
> > it somehow, or the linker is broken.
> >
>
> There is some ambiguity in how SHN_ABS symbols are treated in shared
> libraries and PIE executables.
>
> https://sourceware.org/ml/binutils/2012-05/msg00019.html
>
> I haven't confirmed whether it actually causes problems in this
> particular case, but it is safer (and not entirely inappropriate) to
> use a 16-bit field for a quantity that can easily fit one.
OK, so, fundamental linker design flaw that cannot be fixed for
historical reasons. Gotcha.
This "fix" feels like a bit of a hack, since it relies on the absence of
a certain relocation type that could be added later (though it seems
highly unlikely).
Cleaner options would be to expose both symbols that are subtracted,
rather than the result, or to do the subtraction at build time and
generate a header that affected files include (though that's more
invasive on the Makefile side).
May be overkill though.
>
> >
> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >> ---
> >> arch/arm/mach-tegra/sleep-tegra20.S | 22 ++++++++++++--------
> >> arch/arm/mach-tegra/sleep-tegra30.S | 6 +++---
> >> arch/arm/mach-tegra/sleep.S | 4 ++--
> >> 3 files changed, 18 insertions(+), 14 deletions(-)
> >>
> >> diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
> >> index 5c8e638ee51a..cab95de5c8f1 100644
> >> --- a/arch/arm/mach-tegra/sleep-tegra20.S
> >> +++ b/arch/arm/mach-tegra/sleep-tegra20.S
> >> @@ -99,7 +99,7 @@ ENTRY(tegra20_cpu_shutdown)
> >> cmp r0, #0
> >> reteq lr @ must not be called for CPU 0
> >> mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
> >> - ldr r2, =__tegra20_cpu1_resettable_status_offset
> >> + ldrh r2, 0f
> >> mov r12, #CPU_RESETTABLE
> >> strb r12, [r1, r2]
> >>
> >> @@ -121,6 +121,7 @@ ENTRY(tegra20_cpu_shutdown)
> >> beq .
> >> ret lr
> >> ENDPROC(tegra20_cpu_shutdown)
> >> +0: .short __tegra20_cpu1_resettable_status_offset
> >> #endif
> >>
> >> #ifdef CONFIG_PM_SLEEP
> >> @@ -181,6 +182,9 @@ ENTRY(tegra_pen_unlock)
> >> ret lr
> >> ENDPROC(tegra_pen_unlock)
> >>
> >> +.L__tegra20_cpu1_resettable_status_offset:
> >> + .short __tegra20_cpu1_resettable_status_offset
> >> +
> >> /*
> >> * tegra20_cpu_clear_resettable(void)
> >> *
> >> @@ -189,7 +193,7 @@ ENDPROC(tegra_pen_unlock)
> >> */
> >> ENTRY(tegra20_cpu_clear_resettable)
> >> mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
> >
> > Can we simply port mov32 to mov_l? Or do we hit a problem with
> > multiplatform kernels where mov_l may involve a literal pool entry
> > (and does it matter)?
> >
>
> The only place where it matters is in code that lives in idmap.text,
> since the relative reference will point to the ID mapped alias of a
> section that is not covered by the ID ID map. I think we should be
> able to use mov_l everywhere else, and it should do the right thing
> for ordinary and PIE builds
Fair enough.
Cheers
---Dave
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 12:53 ` [kernel-hardening] [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros Ard Biesheuvel
@ 2017-08-14 15:29 ` Dave Martin
2017-08-14 15:38 ` Ard Biesheuvel
2017-08-14 15:32 ` Dave Martin
1 sibling, 1 reply; 60+ messages in thread
From: Dave Martin @ 2017-08-14 15:29 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: kernel-hardening, Mark Rutland, Kees Cook, Arnd Bergmann,
Nicolas Pitre, Marc Zyngier, Russell King, Tony Lindgren,
Matt Fleming, Thomas Garnier, linux-arm-kernel
On Mon, Aug 14, 2017 at 01:53:43PM +0100, Ard Biesheuvel wrote:
> Like arm64, ARM supports position independent code sequences that
> produce symbol references with a greater reach than the ordinary
> adr/ldr instructions.
>
> Currently, we use open coded instruction sequences involving literals
> and arithmetic operations. Instead, we can use movw/movt pairs on v7
> CPUs, circumventing the D-cache entirely. For older CPUs, we can emit
> the literal into a subsection, allowing it to be emitted out of line
> while retaining the ability to perform arithmetic on label offsets.
>
> E.g., on pre-v7 CPUs, we can emit a PC-relative reference as follows:
>
> ldr <reg>, 222f
> 111: add <reg>, <reg>, pc
> .subsection 1
> 222: .long <sym> - (111b + 8)
> .previous
>
> This is allowed by the assembler because, unlike ordinary sections,
> subsections are combined into a single section into the object file,
> and so the label references are not true cross-section references that
> are visible as relocations. Note that we could even do something like
>
> add <reg>, pc, #(222f - 111f) & ~0xfff
> ldr <reg>, [<reg>, #(222f - 111f) & 0xfff]
> 111: add <reg>, <reg>, pc
> .subsection 1
> 222: .long <sym> - (111b + 8)
> .previous
This is reinventing ldr=
I seem to remember ldr= barfing on things that .long happily accepts
though, was this the reason?
> if it turns out that the 4 KB range of the ldr instruction is insufficient
> to reach the literal in the subsection, although this is currently not a
> problem (of the 98 objects built from .S files in a multi_v7_defconfig
> build, only 11 have .text sections that are over 1 KB, and the largest one
> [entry-armv.o] is 3308 bytes)
>
> Subsections have been available in binutils since 2004 at least, so
> they should not cause any issues with older toolchains.
(I also believe this to be an ancient feature, but I've not done the
digging to prove it.)
> So use the above to implement the macros mov_l, adr_l, adrm_l (using ldm
> to load multiple literals at once), ldr_l and str_l, all of which will
> use movw/movt pairs on v7 and later CPUs, and use PC-relative literals
> otherwise.
>
> Cc: Russell King <linux@armlinux.org.uk>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> arch/arm/include/asm/assembler.h | 71 ++++++++++++++++++++
> 1 file changed, 71 insertions(+)
>
> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> index ad301f107dd2..516ebaf4ff38 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -518,4 +518,75 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
> #endif
> .endm
>
> +#ifdef CONFIG_THUMB2_KERNEL
> +#define ARM_PC_BIAS 4
> +#else
> +#define ARM_PC_BIAS 8
> +#endif
> +
> + .macro __adldst_l, op, reg, sym, tmp, c
> + .if __LINUX_ARM_ARCH__ < 7
> + ldr\c \tmp, 111f
> + .subsection 1
> + .align 2
> +111: .long \sym - (222f + ARM_PC_BIAS)
See above comment about ldr=.
> + .previous
> + .else
> + W(movw\c\()) \tmp, #:lower16:\sym - (222f + ARM_PC_BIAS)
> + W(movt\c\()) \tmp, #:upper16:\sym - (222f + ARM_PC_BIAS)
Why W()?
There are no narrow forms of these instructions anyway -- if there were
then they couldn't accommodate a 16-bit immediate.
> + .endif
> +222:
> + .ifc \op, add
> + add\c \reg, \tmp, pc
> + .elseif CONFIG_THUMB2_KERNEL == 1
> + add \tmp, \tmp, pc
> + \op\c \reg, [\tmp]
Shame
\op\c \reg, [pc, \tmp]
doesn't work.
But it doesn't, apparently.
> + .else
> + \op\c \reg, [pc, \tmp]
> + .endif
> + .endm
> +
> + /*
> + * mov_l - move a constant value or [relocated] address into a register
> + */
> + .macro mov_l, dst:req, imm:req, cond
> + .if __LINUX_ARM_ARCH__ < 7
> + ldr\cond \dst, =\imm
> + .else
> + W(movw\cond\()) \dst, #:lower16:\imm
> + W(movt\cond\()) \dst, #:upper16:\imm
> + .endif
> + .endm
> +
> + /*
> + * adr_l - adr pseudo-op with unlimited range
> + *
> + * @dst: destination register
> + * @sym: name of the symbol
> + */
> + .macro adr_l, dst:req, sym:req, cond
> + __adldst_l add, \dst, \sym, \dst, \cond
> + .endm
> +
> + /*
> + * ldr_l - ldr <literal> pseudo-op with unlimited range
> + *
> + * @dst: destination register
> + * @sym: name of the symbol
> + */
> + .macro ldr_l, dst:req, sym:req, cond
> + __adldst_l ldr, \dst, \sym, \dst, \cond
> + .endm
> +
> + /*
> + * str_l - str <literal> pseudo-op with unlimited range
> + *
> + * @src: source register
> + * @sym: name of the symbol
> + * @tmp: mandatory scratch register
> + */
> + .macro str_l, src:req, sym:req, tmp:req, cond
> + __adldst_l str, \src, \sym, \tmp, \cond
> + .endm
Cheers
---Dave
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
` (29 preceding siblings ...)
2017-08-14 12:54 ` [kernel-hardening] [PATCH 30/30] efi/libstub: arm: implement KASLR Ard Biesheuvel
@ 2017-08-14 15:30 ` Arnd Bergmann
2017-08-14 15:49 ` Ard Biesheuvel
30 siblings, 1 reply; 60+ messages in thread
From: Arnd Bergmann @ 2017-08-14 15:30 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Kernel Hardening, Linux ARM, Nicolas Pitre, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Mon, Aug 14, 2017 at 2:53 PM, Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:
> This series implements randomization of the placement of the core ARM kernel
> inside the lowmem region. It consists of the following parts:
>
> - changes that allow us to build vmlinux as a PIE executable which retains
> the metadata required to fix up all absolute symbol references at runtime
> - changes that eliminate absolute references from low-level code that may
> execute with the MMU off: this removes the need to perform explicit cache
> maintenance after the absolute references have been fixed up at runtime with
> the caches enabled
> - changes to the core kernel startup code to take the physical offset into
> account when creating the virtual mapping (the pa-to-va mapping remains
> unchanged)
> - changes to the decompressor to take the KASLR offset into account when
> placing the kernel in physical memory
> - changes to the UEFI stub code to choose the KASLR offset and communicate
> it to the decompressor
Would it make sense to also randomize the pa-to-va mapping on top of this?
That can certainly be a later follow-up, I'm just trying to think of the options
we have, given that the kernel is now relocatable and we can support arbitrary
pa-to-va mappings already.
Can you explain how the random seed is passed from the bootloader
to the kernel when we don't use EFI? Is this implemented at all? I see
that you add a seed to "/chosen/kaslr-seed" in the EFI stub when using
the EFI boot services, but I don't see where that value gets read again
when we relocate the kernel.
Arnd
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 12:53 ` [kernel-hardening] [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros Ard Biesheuvel
2017-08-14 15:29 ` [kernel-hardening] " Dave Martin
@ 2017-08-14 15:32 ` Dave Martin
2017-08-14 15:40 ` Ard Biesheuvel
1 sibling, 1 reply; 60+ messages in thread
From: Dave Martin @ 2017-08-14 15:32 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: kernel-hardening, Mark Rutland, Kees Cook, Arnd Bergmann,
Nicolas Pitre, Marc Zyngier, Russell King, Tony Lindgren,
Matt Fleming, Thomas Garnier, linux-arm-kernel
On Mon, Aug 14, 2017 at 01:53:43PM +0100, Ard Biesheuvel wrote:
> Like arm64, ARM supports position independent code sequences that
> produce symbol references with a greater reach than the ordinary
> adr/ldr instructions.
>
> Currently, we use open coded instruction sequences involving literals
> and arithmetic operations. Instead, we can use movw/movt pairs on v7
> CPUs, circumventing the D-cache entirely. For older CPUs, we can emit
> the literal into a subsection, allowing it to be emitted out of line
> while retaining the ability to perform arithmetic on label offsets.
>
> E.g., on pre-v7 CPUs, we can emit a PC-relative reference as follows:
>
> ldr <reg>, 222f
> 111: add <reg>, <reg>, pc
> .subsection 1
> 222: .long <sym> - (111b + 8)
> .previous
>
> This is allowed by the assembler because, unlike ordinary sections,
> subsections are combined into a single section into the object file,
> and so the label references are not true cross-section references that
> are visible as relocations. Note that we could even do something like
>
> add <reg>, pc, #(222f - 111f) & ~0xfff
> ldr <reg>, [<reg>, #(222f - 111f) & 0xfff]
> 111: add <reg>, <reg>, pc
> .subsection 1
> 222: .long <sym> - (111b + 8)
> .previous
>
> if it turns out that the 4 KB range of the ldr instruction is insufficient
> to reach the literal in the subsection, although this is currently not a
> problem (of the 98 objects built from .S files in a multi_v7_defconfig
> build, only 11 have .text sections that are over 1 KB, and the largest one
> [entry-armv.o] is 3308 bytes)
>
> Subsections have been available in binutils since 2004 at least, so
> they should not cause any issues with older toolchains.
>
> So use the above to implement the macros mov_l, adr_l, adrm_l (using ldm
I don't see adrm_l in this patch.
> to load multiple literals at once), ldr_l and str_l, all of which will
> use movw/movt pairs on v7 and later CPUs, and use PC-relative literals
> otherwise.
Also...
By default, I'd assume that we should port _all_ uses of :upper16:/
:lower16: to use these. Does this series consciously do that? Are
there any exceptions?
[...]
Cheers
---Dave
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 15:29 ` [kernel-hardening] " Dave Martin
@ 2017-08-14 15:38 ` Ard Biesheuvel
2017-08-14 15:50 ` Dave Martin
0 siblings, 1 reply; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 15:38 UTC (permalink / raw)
To: Dave Martin
Cc: Kernel Hardening, Mark Rutland, Kees Cook, Arnd Bergmann,
Nicolas Pitre, Marc Zyngier, Russell King, Tony Lindgren,
Matt Fleming, Thomas Garnier, linux-arm-kernel
On 14 August 2017 at 16:29, Dave Martin <Dave.Martin@arm.com> wrote:
> On Mon, Aug 14, 2017 at 01:53:43PM +0100, Ard Biesheuvel wrote:
>> Like arm64, ARM supports position independent code sequences that
>> produce symbol references with a greater reach than the ordinary
>> adr/ldr instructions.
>>
>> Currently, we use open coded instruction sequences involving literals
>> and arithmetic operations. Instead, we can use movw/movt pairs on v7
>> CPUs, circumventing the D-cache entirely. For older CPUs, we can emit
>> the literal into a subsection, allowing it to be emitted out of line
>> while retaining the ability to perform arithmetic on label offsets.
>>
>> E.g., on pre-v7 CPUs, we can emit a PC-relative reference as follows:
>>
>> ldr <reg>, 222f
>> 111: add <reg>, <reg>, pc
>> .subsection 1
>> 222: .long <sym> - (111b + 8)
>> .previous
>>
>> This is allowed by the assembler because, unlike ordinary sections,
>> subsections are combined into a single section into the object file,
>> and so the label references are not true cross-section references that
>> are visible as relocations. Note that we could even do something like
>>
>> add <reg>, pc, #(222f - 111f) & ~0xfff
>> ldr <reg>, [<reg>, #(222f - 111f) & 0xfff]
>> 111: add <reg>, <reg>, pc
>> .subsection 1
>> 222: .long <sym> - (111b + 8)
>> .previous
>
> This is reinventing ldr=
>
> I seem to remember ldr= barfing on things that .long happily accepts
> though, was this the reason?
>
Yes. ldr = does not accept expressions involving symbols, only plain
symbols or expressions that evaluate to constants.
So something like
ldr <reg>, =<sym> - <label>
is rejected while the equivalent
ldr <reg>, 0f
0: .long <sym> - <label>
does work.
>> if it turns out that the 4 KB range of the ldr instruction is insufficient
>> to reach the literal in the subsection, although this is currently not a
>> problem (of the 98 objects built from .S files in a multi_v7_defconfig
>> build, only 11 have .text sections that are over 1 KB, and the largest one
>> [entry-armv.o] is 3308 bytes)
>>
>> Subsections have been available in binutils since 2004 at least, so
>> they should not cause any issues with older toolchains.
>
> (I also believe this to be an ancient feature, but I've not done the
> digging to prove it.)
>
OK
>> So use the above to implement the macros mov_l, adr_l, adrm_l (using ldm
>> to load multiple literals at once), ldr_l and str_l, all of which will
>> use movw/movt pairs on v7 and later CPUs, and use PC-relative literals
>> otherwise.
>>
>> Cc: Russell King <linux@armlinux.org.uk>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>> arch/arm/include/asm/assembler.h | 71 ++++++++++++++++++++
>> 1 file changed, 71 insertions(+)
>>
>> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
>> index ad301f107dd2..516ebaf4ff38 100644
>> --- a/arch/arm/include/asm/assembler.h
>> +++ b/arch/arm/include/asm/assembler.h
>> @@ -518,4 +518,75 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
>> #endif
>> .endm
>>
>> +#ifdef CONFIG_THUMB2_KERNEL
>> +#define ARM_PC_BIAS 4
>> +#else
>> +#define ARM_PC_BIAS 8
>> +#endif
>> +
>> + .macro __adldst_l, op, reg, sym, tmp, c
>> + .if __LINUX_ARM_ARCH__ < 7
>> + ldr\c \tmp, 111f
>> + .subsection 1
>> + .align 2
>> +111: .long \sym - (222f + ARM_PC_BIAS)
>
> See above comment about ldr=.
>
>> + .previous
>> + .else
>> + W(movw\c\()) \tmp, #:lower16:\sym - (222f + ARM_PC_BIAS)
>> + W(movt\c\()) \tmp, #:upper16:\sym - (222f + ARM_PC_BIAS)
>
> Why W()?
>
> There are no narrow forms of these instructions anyway -- if there were
> then they couldn't accommodate a 16-bit immediate.
>
That's a trick, actually, which I failed to add a comment for.
We use .arm sections in the thumb2 kernel, and using these macros
there would result in the wrong offset to be used. Adding the .w
suffix forces an error in the assembler which even results in a fairly
meaningful error message complaining about using .w in ARM code.
>> + .endif
>> +222:
>> + .ifc \op, add
>> + add\c \reg, \tmp, pc
>> + .elseif CONFIG_THUMB2_KERNEL == 1
>> + add \tmp, \tmp, pc
>> + \op\c \reg, [\tmp]
>
> Shame
> \op\c \reg, [pc, \tmp]
> doesn't work.
>
> But it doesn't, apparently.
>
No, thumb2 does not allow that
>> + .else
>> + \op\c \reg, [pc, \tmp]
>> + .endif
>> + .endm
>> +
>> + /*
>> + * mov_l - move a constant value or [relocated] address into a register
>> + */
>> + .macro mov_l, dst:req, imm:req, cond
>> + .if __LINUX_ARM_ARCH__ < 7
>> + ldr\cond \dst, =\imm
>> + .else
>> + W(movw\cond\()) \dst, #:lower16:\imm
>> + W(movt\cond\()) \dst, #:upper16:\imm
>> + .endif
>> + .endm
>> +
>> + /*
>> + * adr_l - adr pseudo-op with unlimited range
>> + *
>> + * @dst: destination register
>> + * @sym: name of the symbol
>> + */
>> + .macro adr_l, dst:req, sym:req, cond
>> + __adldst_l add, \dst, \sym, \dst, \cond
>> + .endm
>> +
>> + /*
>> + * ldr_l - ldr <literal> pseudo-op with unlimited range
>> + *
>> + * @dst: destination register
>> + * @sym: name of the symbol
>> + */
>> + .macro ldr_l, dst:req, sym:req, cond
>> + __adldst_l ldr, \dst, \sym, \dst, \cond
>> + .endm
>> +
>> + /*
>> + * str_l - str <literal> pseudo-op with unlimited range
>> + *
>> + * @src: source register
>> + * @sym: name of the symbol
>> + * @tmp: mandatory scratch register
>> + */
>> + .macro str_l, src:req, sym:req, tmp:req, cond
>> + __adldst_l str, \src, \sym, \tmp, \cond
>> + .endm
>
> Cheers
> ---Dave
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 15:32 ` Dave Martin
@ 2017-08-14 15:40 ` Ard Biesheuvel
2017-08-14 15:53 ` Dave Martin
0 siblings, 1 reply; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 15:40 UTC (permalink / raw)
To: Dave Martin
Cc: Kernel Hardening, Mark Rutland, Kees Cook, Arnd Bergmann,
Nicolas Pitre, Marc Zyngier, Russell King, Tony Lindgren,
Matt Fleming, Thomas Garnier, linux-arm-kernel
On 14 August 2017 at 16:32, Dave Martin <Dave.Martin@arm.com> wrote:
> On Mon, Aug 14, 2017 at 01:53:43PM +0100, Ard Biesheuvel wrote:
>> Like arm64, ARM supports position independent code sequences that
>> produce symbol references with a greater reach than the ordinary
>> adr/ldr instructions.
>>
>> Currently, we use open coded instruction sequences involving literals
>> and arithmetic operations. Instead, we can use movw/movt pairs on v7
>> CPUs, circumventing the D-cache entirely. For older CPUs, we can emit
>> the literal into a subsection, allowing it to be emitted out of line
>> while retaining the ability to perform arithmetic on label offsets.
>>
>> E.g., on pre-v7 CPUs, we can emit a PC-relative reference as follows:
>>
>> ldr <reg>, 222f
>> 111: add <reg>, <reg>, pc
>> .subsection 1
>> 222: .long <sym> - (111b + 8)
>> .previous
>>
>> This is allowed by the assembler because, unlike ordinary sections,
>> subsections are combined into a single section into the object file,
>> and so the label references are not true cross-section references that
>> are visible as relocations. Note that we could even do something like
>>
>> add <reg>, pc, #(222f - 111f) & ~0xfff
>> ldr <reg>, [<reg>, #(222f - 111f) & 0xfff]
>> 111: add <reg>, <reg>, pc
>> .subsection 1
>> 222: .long <sym> - (111b + 8)
>> .previous
>>
>> if it turns out that the 4 KB range of the ldr instruction is insufficient
>> to reach the literal in the subsection, although this is currently not a
>> problem (of the 98 objects built from .S files in a multi_v7_defconfig
>> build, only 11 have .text sections that are over 1 KB, and the largest one
>> [entry-armv.o] is 3308 bytes)
>>
>> Subsections have been available in binutils since 2004 at least, so
>> they should not cause any issues with older toolchains.
>>
>> So use the above to implement the macros mov_l, adr_l, adrm_l (using ldm
>
> I don't see adrm_l in this patch.
>
Oops (2)
Nico already mentioned that, and I failed to fix the commit log. I
added it at some point, but it wasn't really useful
>> to load multiple literals at once), ldr_l and str_l, all of which will
>> use movw/movt pairs on v7 and later CPUs, and use PC-relative literals
>> otherwise.
>
> Also...
>
> By default, I'd assume that we should port _all_ uses of :upper16:/
> :lower16: to use these. Does this series consciously do that? Are
> there any exceptions?
>
There aren't that many. Anything that refers to absolute symbols will
break under CONFIG_RELOCATABLE and I haven't noticed any issues (I
tested extensively with Thumb2)
I don't mind open coded movw/movt for relative references in code that
is tightly coupled to a platform that guarantees v7+ so I didn't do a
full sweep. Also, I started with 50+ patches and tried to remove the
ones that are mostly orthogonal to the KASLR stuff.
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM
2017-08-14 15:30 ` [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM Arnd Bergmann
@ 2017-08-14 15:49 ` Ard Biesheuvel
2017-08-14 16:03 ` Arnd Bergmann
2017-08-14 16:16 ` Nicolas Pitre
0 siblings, 2 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 15:49 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Kernel Hardening, Linux ARM, Nicolas Pitre, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 14 August 2017 at 16:30, Arnd Bergmann <arnd@arndb.de> wrote:
> On Mon, Aug 14, 2017 at 2:53 PM, Ard Biesheuvel
> <ard.biesheuvel@linaro.org> wrote:
>> This series implements randomization of the placement of the core ARM kernel
>> inside the lowmem region. It consists of the following parts:
>>
>> - changes that allow us to build vmlinux as a PIE executable which retains
>> the metadata required to fix up all absolute symbol references at runtime
>> - changes that eliminate absolute references from low-level code that may
>> execute with the MMU off: this removes the need to perform explicit cache
>> maintenance after the absolute references have been fixed up at runtime with
>> the caches enabled
>> - changes to the core kernel startup code to take the physical offset into
>> account when creating the virtual mapping (the pa-to-va mapping remains
>> unchanged)
>> - changes to the decompressor to take the KASLR offset into account when
>> placing the kernel in physical memory
>> - changes to the UEFI stub code to choose the KASLR offset and communicate
>> it to the decompressor
>
> Would it make sense to also randomize the pa-to-va mapping on top of this?
> That can certainly be a later follow-up, I'm just trying to think of the options
> we have, given that the kernel is now relocatable and we can support arbitrary
> pa-to-va mappings already.
>
We could randomize PAGE_OFFSET as well. That allows you to build a
3g/1g split kernel and execute it as 2g/2g split. Pretty neat!
Randomizing the VA to PA mapping while keep PAGE_OFFSET constant will
result in either memory to be thrown away (because it is virtually
mapped below PAGE_OFFSET) or lowmem space to be wasted (because there
is a hole between PAGE_OFFSET and the VA of the lowest lowmem address)
So i think there may be opportunities, but I haven't quite figured
them out myself yet.
> Can you explain how the random seed is passed from the bootloader
> to the kernel when we don't use EFI? Is this implemented at all? I see
> that you add a seed to "/chosen/kaslr-seed" in the EFI stub when using
> the EFI boot services, but I don't see where that value gets read again
> when we relocate the kernel.
/chosen/kaslr-seed is only used on arm64, not on ARM. We could add
code to the decompressor that uses /chosen/kaslr-seed, but it is a bit
fiddly because the execution environment is so constrained, and there
is no simple access to symbols defined by the core kernel's linker
script.
On UEFI systems, the kaslr offset is calculated based on the UEFI
memory map, which describes all of memory and has reservations for the
DTB, the initrd etc. The EFI stub is linked together with the
decompressor, so passing the kaslr offset simply involves setting a
variable.
To allow other bootloaders to do the same, the kaslr metadata is
exposed via a zImage header, containing the values of PAGE_OFFSET, the
base of the vmalloc area and the randomization granularity. A
bootloader can read these values, and taking the size of DRAM and the
placement of initrd and DTB into account, it can choose a value for
kaslr offset and write it back into the zImage header.
This is a bit involved, but it is really difficult to make these
things backward compatible, i.e., passing something in a register is
not possible if that register was not mandated to be zero initially.
Similarly, the decompressor passed the kaslr offset to the startup
code in the core kernel. It does so by passing it in r3 and jumping 4
bytes past the entry point. This way, we are backward compatible with
configurations where the decompressor is not used, because in that
case, you always jump to the first instruction, which zeroes r3.
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 15:38 ` Ard Biesheuvel
@ 2017-08-14 15:50 ` Dave Martin
2017-08-14 16:18 ` Nicolas Pitre
0 siblings, 1 reply; 60+ messages in thread
From: Dave Martin @ 2017-08-14 15:50 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Mark Rutland, Kees Cook, Arnd Bergmann, Nicolas Pitre,
Marc Zyngier, Kernel Hardening, Russell King, Tony Lindgren,
linux-arm-kernel, Thomas Garnier, Matt Fleming
On Mon, Aug 14, 2017 at 04:38:02PM +0100, Ard Biesheuvel wrote:
> On 14 August 2017 at 16:29, Dave Martin <Dave.Martin@arm.com> wrote:
> > On Mon, Aug 14, 2017 at 01:53:43PM +0100, Ard Biesheuvel wrote:
> >> Like arm64, ARM supports position independent code sequences that
> >> produce symbol references with a greater reach than the ordinary
> >> adr/ldr instructions.
> >>
> >> Currently, we use open coded instruction sequences involving literals
> >> and arithmetic operations. Instead, we can use movw/movt pairs on v7
> >> CPUs, circumventing the D-cache entirely. For older CPUs, we can emit
> >> the literal into a subsection, allowing it to be emitted out of line
> >> while retaining the ability to perform arithmetic on label offsets.
> >>
> >> E.g., on pre-v7 CPUs, we can emit a PC-relative reference as follows:
> >>
> >> ldr <reg>, 222f
> >> 111: add <reg>, <reg>, pc
> >> .subsection 1
> >> 222: .long <sym> - (111b + 8)
> >> .previous
> >>
> >> This is allowed by the assembler because, unlike ordinary sections,
> >> subsections are combined into a single section into the object file,
> >> and so the label references are not true cross-section references that
> >> are visible as relocations. Note that we could even do something like
> >>
> >> add <reg>, pc, #(222f - 111f) & ~0xfff
> >> ldr <reg>, [<reg>, #(222f - 111f) & 0xfff]
> >> 111: add <reg>, <reg>, pc
> >> .subsection 1
> >> 222: .long <sym> - (111b + 8)
> >> .previous
> >
> > This is reinventing ldr=
> >
> > I seem to remember ldr= barfing on things that .long happily accepts
> > though, was this the reason?
> >
>
> Yes. ldr = does not accept expressions involving symbols, only plain
> symbols or expressions that evaluate to constants.
>
> So something like
>
> ldr <reg>, =<sym> - <label>
>
> is rejected while the equivalent
>
> ldr <reg>, 0f
> 0: .long <sym> - <label>
>
> does work.
I wouldn't bother trying to rationalise gas' behaviour here. I think
it's an accident of implementation rather than there being some
fundamental reason for it.
AFAICT gas could quite happily resolve ldr= in exactly the same way as
.long and thus not have this problem. But we can't rewrite history.
[...]
> >> + .macro __adldst_l, op, reg, sym, tmp, c
> >> + .if __LINUX_ARM_ARCH__ < 7
> >> + ldr\c \tmp, 111f
> >> + .subsection 1
> >> + .align 2
> >> +111: .long \sym - (222f + ARM_PC_BIAS)
> >
> > See above comment about ldr=.
> >
> >> + .previous
> >> + .else
> >> + W(movw\c\()) \tmp, #:lower16:\sym - (222f + ARM_PC_BIAS)
> >> + W(movt\c\()) \tmp, #:upper16:\sym - (222f + ARM_PC_BIAS)
> >
> > Why W()?
> >
> > There are no narrow forms of these instructions anyway -- if there were
> > then they couldn't accommodate a 16-bit immediate.
> >
>
> That's a trick, actually, which I failed to add a comment for.
>
> We use .arm sections in the thumb2 kernel, and using these macros
> there would result in the wrong offset to be used. Adding the .w
> suffix forces an error in the assembler which even results in a fairly
> meaningful error message complaining about using .w in ARM code.
Ewww... I think it'd be best to add a comment explaining that.
There's a fair change someone will trip over this at some point (or
worse, "fix" the assembly errors).
>
> >> + .endif
> >> +222:
> >> + .ifc \op, add
> >> + add\c \reg, \tmp, pc
> >> + .elseif CONFIG_THUMB2_KERNEL == 1
> >> + add \tmp, \tmp, pc
> >> + \op\c \reg, [\tmp]
> >
> > Shame
> > \op\c \reg, [pc, \tmp]
> > doesn't work.
> >
> > But it doesn't, apparently.
> >
>
> No, thumb2 does not allow that
Meh. Oh well.
[...]
Cheers
---Dave
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 15:40 ` Ard Biesheuvel
@ 2017-08-14 15:53 ` Dave Martin
0 siblings, 0 replies; 60+ messages in thread
From: Dave Martin @ 2017-08-14 15:53 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Mark Rutland, Kees Cook, Arnd Bergmann, Nicolas Pitre,
Marc Zyngier, Kernel Hardening, Russell King, Tony Lindgren,
linux-arm-kernel, Thomas Garnier, Matt Fleming
On Mon, Aug 14, 2017 at 04:40:55PM +0100, Ard Biesheuvel wrote:
> On 14 August 2017 at 16:32, Dave Martin <Dave.Martin@arm.com> wrote:
> > On Mon, Aug 14, 2017 at 01:53:43PM +0100, Ard Biesheuvel wrote:
[...]
> >> So use the above to implement the macros mov_l, adr_l, adrm_l (using ldm
> >
> > I don't see adrm_l in this patch.
> >
>
> Oops (2)
>
> Nico already mentioned that, and I failed to fix the commit log. I
> added it at some point, but it wasn't really useful
Thought it might be something like that.
> >> to load multiple literals at once), ldr_l and str_l, all of which will
> >> use movw/movt pairs on v7 and later CPUs, and use PC-relative literals
> >> otherwise.
> >
> > Also...
> >
> > By default, I'd assume that we should port _all_ uses of :upper16:/
> > :lower16: to use these. Does this series consciously do that? Are
> > there any exceptions?
> >
>
> There aren't that many. Anything that refers to absolute symbols will
> break under CONFIG_RELOCATABLE and I haven't noticed any issues (I
> tested extensively with Thumb2)
>
> I don't mind open coded movw/movt for relative references in code that
> is tightly coupled to a platform that guarantees v7+ so I didn't do a
> full sweep. Also, I started with 50+ patches and tried to remove the
> ones that are mostly orthogonal to the KASLR stuff.
OK, that sounds reasonable.
Cheers
---Dave
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 20/30] ARM: kernel: use PC relative symbol references in suspend/resume code
2017-08-14 12:54 ` [kernel-hardening] [PATCH 20/30] ARM: kernel: use PC relative symbol references in suspend/resume code Ard Biesheuvel
@ 2017-08-14 16:02 ` Nicolas Pitre
2017-08-14 18:14 ` Ard Biesheuvel
0 siblings, 1 reply; 60+ messages in thread
From: Nicolas Pitre @ 2017-08-14 16:02 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: kernel-hardening, linux-arm-kernel, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Mon, 14 Aug 2017, Ard Biesheuvel wrote:
> Replace some unnecessary absolute references with relative ones. Also,
> to prepare for runtime relocation, which occurs with the caches on,
> defer taking the absolute address of cpu_resume_after_mmu() until after
> the MMU is enabled.
>
> Cc: Russell King <linux@armlinux.org.uk>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> arch/arm/kernel/sleep.S | 11 +++++------
> 1 file changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> index 3026b119d3ff..9efd1c7d3552 100644
> --- a/arch/arm/kernel/sleep.S
> +++ b/arch/arm/kernel/sleep.S
> @@ -60,18 +60,17 @@
> ENTRY(__cpu_suspend)
> stmfd sp!, {r4 - r11, lr}
> #ifdef MULTI_CPU
> - ldr r10, =processor
> - ldr r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
> + ldr_l r4, processor + CPU_SLEEP_SIZE @ size of CPU sleep state
> #else
> - ldr r4, =cpu_suspend_size
> + adr_l r4, cpu_suspend_size
> #endif
> mov r5, sp @ current virtual SP
> add r4, r4, #12 @ Space for pgd, virt sp, phys resume fn
> sub sp, sp, r4 @ allocate CPU state on stack
> - ldr r3, =sleep_save_sp
> + adr_l r3, sleep_save_sp
> stmfd sp!, {r0, r1} @ save suspend func arg and pointer
> ldr r3, [r3, #SLEEP_SAVE_SP_VIRT]
> - ALT_SMP(ldr r0, =mpidr_hash)
> + ALT_SMP(adr_l r0, mpidr_hash)
> ALT_UP_B(1f)
The above is dangerous. adr_l expands to more than one instruction which
is not what ALT_SMP() was designed for. Here it might happen to work
anyway because it is combined with ALT_UP_B() but with ALT_UP() it
wouldn't. This is a mistake waiting to happen.
> /* This ldmia relies on the memory layout of the mpidr_hash struct */
> ldmia r0, {r1, r6-r8} @ r1 = mpidr mask (r6,r7,r8) = l[0,1,2] shifts
> @@ -100,13 +99,13 @@ ENDPROC(cpu_suspend_abort)
> .align 5
> .pushsection .idmap.text,"ax"
> ENTRY(cpu_resume_mmu)
> - ldr r3, =cpu_resume_after_mmu
> instr_sync
> mcr p15, 0, r0, c1, c0, 0 @ turn on MMU, I-cache, etc
> mrc p15, 0, r0, c0, c0, 0 @ read id reg
> instr_sync
> mov r0, r0
> mov r0, r0
> + ldr r3, =cpu_resume_after_mmu
> ret r3 @ jump to virtual address
> ENDPROC(cpu_resume_mmu)
> .popsection
> --
> 2.11.0
>
>
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM
2017-08-14 15:49 ` Ard Biesheuvel
@ 2017-08-14 16:03 ` Arnd Bergmann
2017-08-14 16:28 ` Nicolas Pitre
2017-08-14 16:16 ` Nicolas Pitre
1 sibling, 1 reply; 60+ messages in thread
From: Arnd Bergmann @ 2017-08-14 16:03 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Kernel Hardening, Linux ARM, Nicolas Pitre, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Mon, Aug 14, 2017 at 5:49 PM, Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:
> On 14 August 2017 at 16:30, Arnd Bergmann <arnd@arndb.de> wrote:
>> Can you explain how the random seed is passed from the bootloader
>> to the kernel when we don't use EFI? Is this implemented at all? I see
>> that you add a seed to "/chosen/kaslr-seed" in the EFI stub when using
>> the EFI boot services, but I don't see where that value gets read again
>> when we relocate the kernel.
> To allow other bootloaders to do the same, the kaslr metadata is
> exposed via a zImage header, containing the values of PAGE_OFFSET, the
> base of the vmalloc area and the randomization granularity. A
> bootloader can read these values, and taking the size of DRAM and the
> placement of initrd and DTB into account, it can choose a value for
> kaslr offset and write it back into the zImage header.
>
> This is a bit involved, but it is really difficult to make these
> things backward compatible, i.e., passing something in a register is
> not possible if that register was not mandated to be zero initially.
>
> Similarly, the decompressor passed the kaslr offset to the startup
> code in the core kernel. It does so by passing it in r3 and jumping 4
> bytes past the entry point. This way, we are backward compatible with
> configurations where the decompressor is not used, because in that
> case, you always jump to the first instruction, which zeroes r3.
There are two ideas we discussed in the past (but never implemented
them obviously):
- instead of reading the "kaslr-seed" in the decompressor, it could
simply hash all of the DT blob to get the seed. This way the bootloader
can put the random see anywhere it likes, and as an added bonus,
we also get a little bit more random behavior on machines that have
no entropy source at all but that do have things like a serial number or
mac address in DT. Obviously those would be constant across boots
but different between machines. The OS can also store a random
seed during shutdown in a location that the bootloader uses to
initialize /chosen/kaslr-seed or another property that we use to seed
the kernel PRNG at boot time.
- If we have a random number at boot but no way to pass it through
the DT, I think we actually /can/ pass it through registers: the
register state is undefined, so in the worst case using the XOR of
all registers gives us the same number on each boot, but the
if the loader is modified to store a random 32-bit number in any
of the registers that don't pass other information, we can use that
to calculate the kaslr-base.
Arnd
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM
2017-08-14 15:49 ` Ard Biesheuvel
2017-08-14 16:03 ` Arnd Bergmann
@ 2017-08-14 16:16 ` Nicolas Pitre
1 sibling, 0 replies; 60+ messages in thread
From: Nicolas Pitre @ 2017-08-14 16:16 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Arnd Bergmann, Kernel Hardening, Linux ARM, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Mon, 14 Aug 2017, Ard Biesheuvel wrote:
> On 14 August 2017 at 16:30, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Mon, Aug 14, 2017 at 2:53 PM, Ard Biesheuvel
> > <ard.biesheuvel@linaro.org> wrote:
> >> This series implements randomization of the placement of the core ARM kernel
> >> inside the lowmem region. It consists of the following parts:
> >>
> >> - changes that allow us to build vmlinux as a PIE executable which retains
> >> the metadata required to fix up all absolute symbol references at runtime
> >> - changes that eliminate absolute references from low-level code that may
> >> execute with the MMU off: this removes the need to perform explicit cache
> >> maintenance after the absolute references have been fixed up at runtime with
> >> the caches enabled
> >> - changes to the core kernel startup code to take the physical offset into
> >> account when creating the virtual mapping (the pa-to-va mapping remains
> >> unchanged)
> >> - changes to the decompressor to take the KASLR offset into account when
> >> placing the kernel in physical memory
> >> - changes to the UEFI stub code to choose the KASLR offset and communicate
> >> it to the decompressor
> >
> > Would it make sense to also randomize the pa-to-va mapping on top of this?
> > That can certainly be a later follow-up, I'm just trying to think of the options
> > we have, given that the kernel is now relocatable and we can support arbitrary
> > pa-to-va mappings already.
> >
>
> We could randomize PAGE_OFFSET as well. That allows you to build a
> 3g/1g split kernel and execute it as 2g/2g split. Pretty neat!
This is going to break existing user space binaries at some point. Some
applications pretty much always assumed 3g space and are likely to fail
otherwise. The 2g/2g config is good for people wanting to dispense with
highmem and the ability to test their user space with it before
deployment.
Also, this is a lot of complexity added to the kernel for a very
negligible security gain. It is trivial from user space to determine
what the actual PAGE_OFFSET is, so that won't be a serious deterrent.
> Randomizing the VA to PA mapping while keep PAGE_OFFSET constant will
> result in either memory to be thrown away (because it is virtually
> mapped below PAGE_OFFSET) or lowmem space to be wasted (because there
> is a hole between PAGE_OFFSET and the VA of the lowest lowmem address)
>
> So i think there may be opportunities, but I haven't quite figured
> them out myself yet.
>
> > Can you explain how the random seed is passed from the bootloader
> > to the kernel when we don't use EFI? Is this implemented at all? I see
> > that you add a seed to "/chosen/kaslr-seed" in the EFI stub when using
> > the EFI boot services, but I don't see where that value gets read again
> > when we relocate the kernel.
>
> /chosen/kaslr-seed is only used on arm64, not on ARM. We could add
> code to the decompressor that uses /chosen/kaslr-seed, but it is a bit
> fiddly because the execution environment is so constrained, and there
> is no simple access to symbols defined by the core kernel's linker
> script.
>
> On UEFI systems, the kaslr offset is calculated based on the UEFI
> memory map, which describes all of memory and has reservations for the
> DTB, the initrd etc. The EFI stub is linked together with the
> decompressor, so passing the kaslr offset simply involves setting a
> variable.
>
> To allow other bootloaders to do the same, the kaslr metadata is
> exposed via a zImage header, containing the values of PAGE_OFFSET, the
> base of the vmalloc area and the randomization granularity. A
> bootloader can read these values, and taking the size of DRAM and the
> placement of initrd and DTB into account, it can choose a value for
> kaslr offset and write it back into the zImage header.
>
> This is a bit involved, but it is really difficult to make these
> things backward compatible, i.e., passing something in a register is
> not possible if that register was not mandated to be zero initially.
>
> Similarly, the decompressor passed the kaslr offset to the startup
> code in the core kernel. It does so by passing it in r3 and jumping 4
> bytes past the entry point. This way, we are backward compatible with
> configurations where the decompressor is not used, because in that
> case, you always jump to the first instruction, which zeroes r3.
Please capture all this somewhere. Either in the commit log, or in the
Booting document, or both.
Nicolas
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 15:50 ` Dave Martin
@ 2017-08-14 16:18 ` Nicolas Pitre
2017-08-14 16:22 ` Ard Biesheuvel
0 siblings, 1 reply; 60+ messages in thread
From: Nicolas Pitre @ 2017-08-14 16:18 UTC (permalink / raw)
To: Dave Martin
Cc: Ard Biesheuvel, Mark Rutland, Kees Cook, Arnd Bergmann,
Marc Zyngier, Kernel Hardening, Russell King, Tony Lindgren,
linux-arm-kernel, Thomas Garnier, Matt Fleming
On Mon, 14 Aug 2017, Dave Martin wrote:
> On Mon, Aug 14, 2017 at 04:38:02PM +0100, Ard Biesheuvel wrote:
> > That's a trick, actually, which I failed to add a comment for.
Shame shame shame !
> > We use .arm sections in the thumb2 kernel, and using these macros
> > there would result in the wrong offset to be used. Adding the .w
> > suffix forces an error in the assembler which even results in a fairly
> > meaningful error message complaining about using .w in ARM code.
>
> Ewww... I think it'd be best to add a comment explaining that.
Absolutely!
Nicolas
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 16:18 ` Nicolas Pitre
@ 2017-08-14 16:22 ` Ard Biesheuvel
2017-08-14 16:33 ` Nicolas Pitre
2017-08-14 16:42 ` Russell King - ARM Linux
0 siblings, 2 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 16:22 UTC (permalink / raw)
To: Nicolas Pitre
Cc: Dave Martin, Mark Rutland, Kees Cook, Arnd Bergmann,
Marc Zyngier, Kernel Hardening, Russell King, Tony Lindgren,
linux-arm-kernel, Thomas Garnier, Matt Fleming
On 14 August 2017 at 17:18, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Mon, 14 Aug 2017, Dave Martin wrote:
>
>> On Mon, Aug 14, 2017 at 04:38:02PM +0100, Ard Biesheuvel wrote:
>> > That's a trick, actually, which I failed to add a comment for.
>
> Shame shame shame !
>
>> > We use .arm sections in the thumb2 kernel, and using these macros
>> > there would result in the wrong offset to be used. Adding the .w
>> > suffix forces an error in the assembler which even results in a fairly
>> > meaningful error message complaining about using .w in ARM code.
>>
>> Ewww... I think it'd be best to add a comment explaining that.
>
> Absolutely!
>
Yeah, mea culpa.
But if people have better ideas how to avoid this situation, I am all ears.
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM
2017-08-14 16:03 ` Arnd Bergmann
@ 2017-08-14 16:28 ` Nicolas Pitre
2017-08-14 17:28 ` Ard Biesheuvel
0 siblings, 1 reply; 60+ messages in thread
From: Nicolas Pitre @ 2017-08-14 16:28 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Ard Biesheuvel, Kernel Hardening, Linux ARM, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Mon, 14 Aug 2017, Arnd Bergmann wrote:
> On Mon, Aug 14, 2017 at 5:49 PM, Ard Biesheuvel
> <ard.biesheuvel@linaro.org> wrote:
> > On 14 August 2017 at 16:30, Arnd Bergmann <arnd@arndb.de> wrote:
>
>
> >> Can you explain how the random seed is passed from the bootloader
> >> to the kernel when we don't use EFI? Is this implemented at all? I see
> >> that you add a seed to "/chosen/kaslr-seed" in the EFI stub when using
> >> the EFI boot services, but I don't see where that value gets read again
> >> when we relocate the kernel.
>
> > To allow other bootloaders to do the same, the kaslr metadata is
> > exposed via a zImage header, containing the values of PAGE_OFFSET, the
> > base of the vmalloc area and the randomization granularity. A
> > bootloader can read these values, and taking the size of DRAM and the
> > placement of initrd and DTB into account, it can choose a value for
> > kaslr offset and write it back into the zImage header.
> >
> > This is a bit involved, but it is really difficult to make these
> > things backward compatible, i.e., passing something in a register is
> > not possible if that register was not mandated to be zero initially.
> >
> > Similarly, the decompressor passed the kaslr offset to the startup
> > code in the core kernel. It does so by passing it in r3 and jumping 4
> > bytes past the entry point. This way, we are backward compatible with
> > configurations where the decompressor is not used, because in that
> > case, you always jump to the first instruction, which zeroes r3.
>
> There are two ideas we discussed in the past (but never implemented
> them obviously):
>
> - instead of reading the "kaslr-seed" in the decompressor, it could
> simply hash all of the DT blob to get the seed. This way the bootloader
> can put the random see anywhere it likes, and as an added bonus,
> we also get a little bit more random behavior on machines that have
> no entropy source at all but that do have things like a serial number or
> mac address in DT. Obviously those would be constant across boots
> but different between machines. The OS can also store a random
> seed during shutdown in a location that the bootloader uses to
> initialize /chosen/kaslr-seed or another property that we use to seed
> the kernel PRNG at boot time.
>
> - If we have a random number at boot but no way to pass it through
> the DT, I think we actually /can/ pass it through registers: the
> register state is undefined, so in the worst case using the XOR of
> all registers gives us the same number on each boot, but the
> if the loader is modified to store a random 32-bit number in any
> of the registers that don't pass other information, we can use that
> to calculate the kaslr-base.
I really like the later. This way there is no hard protocol to define
and follow. The bootloader may exploit any source of randomness it can
find, including the RTC in addition to the serial number for example. So
doing both on the kernel side might actually be the best approach,
giving the boot environment all the flexibility it wants and being
compatible with all of them.
Nicolas
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 16:22 ` Ard Biesheuvel
@ 2017-08-14 16:33 ` Nicolas Pitre
2017-08-14 16:42 ` Russell King - ARM Linux
1 sibling, 0 replies; 60+ messages in thread
From: Nicolas Pitre @ 2017-08-14 16:33 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Dave Martin, Mark Rutland, Kees Cook, Arnd Bergmann,
Marc Zyngier, Kernel Hardening, Russell King, Tony Lindgren,
linux-arm-kernel, Thomas Garnier, Matt Fleming
On Mon, 14 Aug 2017, Ard Biesheuvel wrote:
> On 14 August 2017 at 17:18, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Mon, 14 Aug 2017, Dave Martin wrote:
> >
> >> On Mon, Aug 14, 2017 at 04:38:02PM +0100, Ard Biesheuvel wrote:
> >> > That's a trick, actually, which I failed to add a comment for.
> >
> > Shame shame shame !
> >
> >> > We use .arm sections in the thumb2 kernel, and using these macros
> >> > there would result in the wrong offset to be used. Adding the .w
> >> > suffix forces an error in the assembler which even results in a fairly
> >> > meaningful error message complaining about using .w in ARM code.
> >>
> >> Ewww... I think it'd be best to add a comment explaining that.
> >
> > Absolutely!
> >
>
> Yeah, mea culpa.
>
> But if people have better ideas how to avoid this situation, I am all ears.
Just document it. ;-)
Nicolas
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 16:22 ` Ard Biesheuvel
2017-08-14 16:33 ` Nicolas Pitre
@ 2017-08-14 16:42 ` Russell King - ARM Linux
2017-08-14 16:56 ` Ard Biesheuvel
1 sibling, 1 reply; 60+ messages in thread
From: Russell King - ARM Linux @ 2017-08-14 16:42 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Nicolas Pitre, Dave Martin, Mark Rutland, Kees Cook,
Arnd Bergmann, Marc Zyngier, Kernel Hardening, Tony Lindgren,
linux-arm-kernel, Thomas Garnier, Matt Fleming
On Mon, Aug 14, 2017 at 05:22:39PM +0100, Ard Biesheuvel wrote:
> On 14 August 2017 at 17:18, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Mon, 14 Aug 2017, Dave Martin wrote:
> >
> >> On Mon, Aug 14, 2017 at 04:38:02PM +0100, Ard Biesheuvel wrote:
> >> > That's a trick, actually, which I failed to add a comment for.
> >
> > Shame shame shame !
> >
> >> > We use .arm sections in the thumb2 kernel, and using these macros
> >> > there would result in the wrong offset to be used. Adding the .w
> >> > suffix forces an error in the assembler which even results in a fairly
> >> > meaningful error message complaining about using .w in ARM code.
> >>
> >> Ewww... I think it'd be best to add a comment explaining that.
> >
> > Absolutely!
> >
>
> Yeah, mea culpa.
>
> But if people have better ideas how to avoid this situation, I am all ears.
Have you tested building an ARMv7M kernel with your patches - ARMv7M is
Thumb only, so can't contain any ARM code. If not, please try
mps2_defconfig.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-08-14 16:42 ` Russell King - ARM Linux
@ 2017-08-14 16:56 ` Ard Biesheuvel
0 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 16:56 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Nicolas Pitre, Dave Martin, Mark Rutland, Kees Cook,
Arnd Bergmann, Marc Zyngier, Kernel Hardening, Tony Lindgren,
linux-arm-kernel, Thomas Garnier, Matt Fleming
On 14 August 2017 at 17:42, Russell King - ARM Linux
<linux@armlinux.org.uk> wrote:
> On Mon, Aug 14, 2017 at 05:22:39PM +0100, Ard Biesheuvel wrote:
>> On 14 August 2017 at 17:18, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> > On Mon, 14 Aug 2017, Dave Martin wrote:
>> >
>> >> On Mon, Aug 14, 2017 at 04:38:02PM +0100, Ard Biesheuvel wrote:
>> >> > That's a trick, actually, which I failed to add a comment for.
>> >
>> > Shame shame shame !
>> >
>> >> > We use .arm sections in the thumb2 kernel, and using these macros
>> >> > there would result in the wrong offset to be used. Adding the .w
>> >> > suffix forces an error in the assembler which even results in a fairly
>> >> > meaningful error message complaining about using .w in ARM code.
>> >>
>> >> Ewww... I think it'd be best to add a comment explaining that.
>> >
>> > Absolutely!
>> >
>>
>> Yeah, mea culpa.
>>
>> But if people have better ideas how to avoid this situation, I am all ears.
>
> Have you tested building an ARMv7M kernel with your patches - ARMv7M is
> Thumb only, so can't contain any ARM code. If not, please try
> mps2_defconfig.
>
mps2_defconfig builds without error with these patches. I don't have
the hardware so I can't boot it, unfortunately.
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM
2017-08-14 16:28 ` Nicolas Pitre
@ 2017-08-14 17:28 ` Ard Biesheuvel
2017-08-14 18:01 ` Nicolas Pitre
0 siblings, 1 reply; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 17:28 UTC (permalink / raw)
To: Nicolas Pitre
Cc: Arnd Bergmann, Kernel Hardening, Linux ARM, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 14 August 2017 at 17:28, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Mon, 14 Aug 2017, Arnd Bergmann wrote:
>
>> On Mon, Aug 14, 2017 at 5:49 PM, Ard Biesheuvel
>> <ard.biesheuvel@linaro.org> wrote:
>> > On 14 August 2017 at 16:30, Arnd Bergmann <arnd@arndb.de> wrote:
>>
>>
>> >> Can you explain how the random seed is passed from the bootloader
>> >> to the kernel when we don't use EFI? Is this implemented at all? I see
>> >> that you add a seed to "/chosen/kaslr-seed" in the EFI stub when using
>> >> the EFI boot services, but I don't see where that value gets read again
>> >> when we relocate the kernel.
>>
>> > To allow other bootloaders to do the same, the kaslr metadata is
>> > exposed via a zImage header, containing the values of PAGE_OFFSET, the
>> > base of the vmalloc area and the randomization granularity. A
>> > bootloader can read these values, and taking the size of DRAM and the
>> > placement of initrd and DTB into account, it can choose a value for
>> > kaslr offset and write it back into the zImage header.
>> >
>> > This is a bit involved, but it is really difficult to make these
>> > things backward compatible, i.e., passing something in a register is
>> > not possible if that register was not mandated to be zero initially.
>> >
>> > Similarly, the decompressor passed the kaslr offset to the startup
>> > code in the core kernel. It does so by passing it in r3 and jumping 4
>> > bytes past the entry point. This way, we are backward compatible with
>> > configurations where the decompressor is not used, because in that
>> > case, you always jump to the first instruction, which zeroes r3.
>>
>> There are two ideas we discussed in the past (but never implemented
>> them obviously):
>>
>> - instead of reading the "kaslr-seed" in the decompressor, it could
>> simply hash all of the DT blob to get the seed. This way the bootloader
>> can put the random see anywhere it likes, and as an added bonus,
>> we also get a little bit more random behavior on machines that have
>> no entropy source at all but that do have things like a serial number or
>> mac address in DT. Obviously those would be constant across boots
>> but different between machines. The OS can also store a random
>> seed during shutdown in a location that the bootloader uses to
>> initialize /chosen/kaslr-seed or another property that we use to seed
>> the kernel PRNG at boot time.
>>
>> - If we have a random number at boot but no way to pass it through
>> the DT, I think we actually /can/ pass it through registers: the
>> register state is undefined, so in the worst case using the XOR of
>> all registers gives us the same number on each boot, but the
>> if the loader is modified to store a random 32-bit number in any
>> of the registers that don't pass other information, we can use that
>> to calculate the kaslr-base.
>
> I really like the later. This way there is no hard protocol to define
> and follow. The bootloader may exploit any source of randomness it can
> find, including the RTC in addition to the serial number for example. So
> doing both on the kernel side might actually be the best approach,
> giving the boot environment all the flexibility it wants and being
> compatible with all of them.
>
Finding a source of entropy is not trivial, but it is not the difficult part.
So when we pass some random seed to the decompressor, what will it do
with it? In order to find a suitable KASLR offset, it needs to know
the size of DRAM, the placement of the DT and potentially an initrd,
and the size of the vmalloc region in order to decide where it can put
the kernel.
In my implementation, the decompressor simply receives the offset from
the bootloader, and exposes the value of PAGE_OFFSET, the base of the
vmalloc region and the kaslr granularity supported by the kernel. The
bootloader should already know the size of DRAM and where it loaded
the DT and initrd, so it can roll the dice in an informed manner.
Note that my UEFI stub implementation essentially does the same, which
was trivial to implement because UEFI already keeps track of all
allocations in DRAM. Note that this version simply disables KASLR if
it encounters a vmalloc= command line argument, given that it affects
the size of the lowmem region. We could enhance that to actually parse
the value, but I kept it simple for now.
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM
2017-08-14 17:28 ` Ard Biesheuvel
@ 2017-08-14 18:01 ` Nicolas Pitre
2017-08-14 18:08 ` Ard Biesheuvel
0 siblings, 1 reply; 60+ messages in thread
From: Nicolas Pitre @ 2017-08-14 18:01 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Arnd Bergmann, Kernel Hardening, Linux ARM, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Mon, 14 Aug 2017, Ard Biesheuvel wrote:
> On 14 August 2017 at 17:28, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Mon, 14 Aug 2017, Arnd Bergmann wrote:
> >
> >> On Mon, Aug 14, 2017 at 5:49 PM, Ard Biesheuvel
> >> <ard.biesheuvel@linaro.org> wrote:
> >> > On 14 August 2017 at 16:30, Arnd Bergmann <arnd@arndb.de> wrote:
> >>
> >>
> >> >> Can you explain how the random seed is passed from the bootloader
> >> >> to the kernel when we don't use EFI? Is this implemented at all? I see
> >> >> that you add a seed to "/chosen/kaslr-seed" in the EFI stub when using
> >> >> the EFI boot services, but I don't see where that value gets read again
> >> >> when we relocate the kernel.
> >>
> >> > To allow other bootloaders to do the same, the kaslr metadata is
> >> > exposed via a zImage header, containing the values of PAGE_OFFSET, the
> >> > base of the vmalloc area and the randomization granularity. A
> >> > bootloader can read these values, and taking the size of DRAM and the
> >> > placement of initrd and DTB into account, it can choose a value for
> >> > kaslr offset and write it back into the zImage header.
> >> >
> >> > This is a bit involved, but it is really difficult to make these
> >> > things backward compatible, i.e., passing something in a register is
> >> > not possible if that register was not mandated to be zero initially.
> >> >
> >> > Similarly, the decompressor passed the kaslr offset to the startup
> >> > code in the core kernel. It does so by passing it in r3 and jumping 4
> >> > bytes past the entry point. This way, we are backward compatible with
> >> > configurations where the decompressor is not used, because in that
> >> > case, you always jump to the first instruction, which zeroes r3.
> >>
> >> There are two ideas we discussed in the past (but never implemented
> >> them obviously):
> >>
> >> - instead of reading the "kaslr-seed" in the decompressor, it could
> >> simply hash all of the DT blob to get the seed. This way the bootloader
> >> can put the random see anywhere it likes, and as an added bonus,
> >> we also get a little bit more random behavior on machines that have
> >> no entropy source at all but that do have things like a serial number or
> >> mac address in DT. Obviously those would be constant across boots
> >> but different between machines. The OS can also store a random
> >> seed during shutdown in a location that the bootloader uses to
> >> initialize /chosen/kaslr-seed or another property that we use to seed
> >> the kernel PRNG at boot time.
> >>
> >> - If we have a random number at boot but no way to pass it through
> >> the DT, I think we actually /can/ pass it through registers: the
> >> register state is undefined, so in the worst case using the XOR of
> >> all registers gives us the same number on each boot, but the
> >> if the loader is modified to store a random 32-bit number in any
> >> of the registers that don't pass other information, we can use that
> >> to calculate the kaslr-base.
> >
> > I really like the later. This way there is no hard protocol to define
> > and follow. The bootloader may exploit any source of randomness it can
> > find, including the RTC in addition to the serial number for example. So
> > doing both on the kernel side might actually be the best approach,
> > giving the boot environment all the flexibility it wants and being
> > compatible with all of them.
> >
>
> Finding a source of entropy is not trivial, but it is not the difficult part.
>
> So when we pass some random seed to the decompressor, what will it do
> with it? In order to find a suitable KASLR offset, it needs to know
> the size of DRAM, the placement of the DT and potentially an initrd,
> and the size of the vmalloc region in order to decide where it can put
> the kernel.
>
> In my implementation, the decompressor simply receives the offset from
> the bootloader, and exposes the value of PAGE_OFFSET, the base of the
> vmalloc region and the kaslr granularity supported by the kernel. The
> bootloader should already know the size of DRAM and where it loaded
> the DT and initrd, so it can roll the dice in an informed manner.
>
> Note that my UEFI stub implementation essentially does the same, which
> was trivial to implement because UEFI already keeps track of all
> allocations in DRAM. Note that this version simply disables KASLR if
> it encounters a vmalloc= command line argument, given that it affects
> the size of the lowmem region. We could enhance that to actually parse
> the value, but I kept it simple for now.
What I dislike about such an arrangement (and I've brought up this
argument forward in a different context before) is that you create a lot
of additional dependencies between the kernel and the boot environment.
The kernel is no longer self-sufficient and all this boot preparation
has to be duplicated in all boot environments from UEFI to U-Boot to
qemu. The fact that the bootloader now has to care about very Linux
internal concepts such as vmalloc_start makes it rather inelegant to me.
I'm even wondering if, design wise, the best solution wouldn't be for
the actual kernel to move itself during the boot process and reboot
itself without any external help. Not necessarily go as far as the full
kexec danse , but boot far enough to parse the DT, initialize the
bootmem allocator, then find a new location for itself, move it there,
do the relocs and restart the boot process. For this to work well, you
would have to make a copy of the .data section so to reboot again with a
pristine version except for one flag indicating that the move has been
done.
Doing it this way gives you a full kernel environment to work from and
be completely self-sufficient with zero reliance on any boot
environment. This would even make it compatible with Image i.e. the
compressor-less kernel. And if the DT and/or initrd is in the way then
you could even go as far as moving them away if you wanted.
This would add some boot latency of course, but certainly in the
sub-second range. That is negligible for those systems where KASLR is
most relevant.
Nicolas
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM
2017-08-14 18:01 ` Nicolas Pitre
@ 2017-08-14 18:08 ` Ard Biesheuvel
0 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 18:08 UTC (permalink / raw)
To: Nicolas Pitre
Cc: Arnd Bergmann, Kernel Hardening, Linux ARM, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 14 August 2017 at 19:01, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Mon, 14 Aug 2017, Ard Biesheuvel wrote:
>
>> On 14 August 2017 at 17:28, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> > On Mon, 14 Aug 2017, Arnd Bergmann wrote:
>> >
>> >> On Mon, Aug 14, 2017 at 5:49 PM, Ard Biesheuvel
>> >> <ard.biesheuvel@linaro.org> wrote:
>> >> > On 14 August 2017 at 16:30, Arnd Bergmann <arnd@arndb.de> wrote:
>> >>
>> >>
>> >> >> Can you explain how the random seed is passed from the bootloader
>> >> >> to the kernel when we don't use EFI? Is this implemented at all? I see
>> >> >> that you add a seed to "/chosen/kaslr-seed" in the EFI stub when using
>> >> >> the EFI boot services, but I don't see where that value gets read again
>> >> >> when we relocate the kernel.
>> >>
>> >> > To allow other bootloaders to do the same, the kaslr metadata is
>> >> > exposed via a zImage header, containing the values of PAGE_OFFSET, the
>> >> > base of the vmalloc area and the randomization granularity. A
>> >> > bootloader can read these values, and taking the size of DRAM and the
>> >> > placement of initrd and DTB into account, it can choose a value for
>> >> > kaslr offset and write it back into the zImage header.
>> >> >
>> >> > This is a bit involved, but it is really difficult to make these
>> >> > things backward compatible, i.e., passing something in a register is
>> >> > not possible if that register was not mandated to be zero initially.
>> >> >
>> >> > Similarly, the decompressor passed the kaslr offset to the startup
>> >> > code in the core kernel. It does so by passing it in r3 and jumping 4
>> >> > bytes past the entry point. This way, we are backward compatible with
>> >> > configurations where the decompressor is not used, because in that
>> >> > case, you always jump to the first instruction, which zeroes r3.
>> >>
>> >> There are two ideas we discussed in the past (but never implemented
>> >> them obviously):
>> >>
>> >> - instead of reading the "kaslr-seed" in the decompressor, it could
>> >> simply hash all of the DT blob to get the seed. This way the bootloader
>> >> can put the random see anywhere it likes, and as an added bonus,
>> >> we also get a little bit more random behavior on machines that have
>> >> no entropy source at all but that do have things like a serial number or
>> >> mac address in DT. Obviously those would be constant across boots
>> >> but different between machines. The OS can also store a random
>> >> seed during shutdown in a location that the bootloader uses to
>> >> initialize /chosen/kaslr-seed or another property that we use to seed
>> >> the kernel PRNG at boot time.
>> >>
>> >> - If we have a random number at boot but no way to pass it through
>> >> the DT, I think we actually /can/ pass it through registers: the
>> >> register state is undefined, so in the worst case using the XOR of
>> >> all registers gives us the same number on each boot, but the
>> >> if the loader is modified to store a random 32-bit number in any
>> >> of the registers that don't pass other information, we can use that
>> >> to calculate the kaslr-base.
>> >
>> > I really like the later. This way there is no hard protocol to define
>> > and follow. The bootloader may exploit any source of randomness it can
>> > find, including the RTC in addition to the serial number for example. So
>> > doing both on the kernel side might actually be the best approach,
>> > giving the boot environment all the flexibility it wants and being
>> > compatible with all of them.
>> >
>>
>> Finding a source of entropy is not trivial, but it is not the difficult part.
>>
>> So when we pass some random seed to the decompressor, what will it do
>> with it? In order to find a suitable KASLR offset, it needs to know
>> the size of DRAM, the placement of the DT and potentially an initrd,
>> and the size of the vmalloc region in order to decide where it can put
>> the kernel.
>>
>> In my implementation, the decompressor simply receives the offset from
>> the bootloader, and exposes the value of PAGE_OFFSET, the base of the
>> vmalloc region and the kaslr granularity supported by the kernel. The
>> bootloader should already know the size of DRAM and where it loaded
>> the DT and initrd, so it can roll the dice in an informed manner.
>>
>> Note that my UEFI stub implementation essentially does the same, which
>> was trivial to implement because UEFI already keeps track of all
>> allocations in DRAM. Note that this version simply disables KASLR if
>> it encounters a vmalloc= command line argument, given that it affects
>> the size of the lowmem region. We could enhance that to actually parse
>> the value, but I kept it simple for now.
>
> What I dislike about such an arrangement (and I've brought up this
> argument forward in a different context before) is that you create a lot
> of additional dependencies between the kernel and the boot environment.
> The kernel is no longer self-sufficient and all this boot preparation
> has to be duplicated in all boot environments from UEFI to U-Boot to
> qemu. The fact that the bootloader now has to care about very Linux
> internal concepts such as vmalloc_start makes it rather inelegant to me.
>
> I'm even wondering if, design wise, the best solution wouldn't be for
> the actual kernel to move itself during the boot process and reboot
> itself without any external help. Not necessarily go as far as the full
> kexec danse , but boot far enough to parse the DT, initialize the
> bootmem allocator, then find a new location for itself, move it there,
> do the relocs and restart the boot process. For this to work well, you
> would have to make a copy of the .data section so to reboot again with a
> pristine version except for one flag indicating that the move has been
> done.
>
> Doing it this way gives you a full kernel environment to work from and
> be completely self-sufficient with zero reliance on any boot
> environment. This would even make it compatible with Image i.e. the
> compressor-less kernel. And if the DT and/or initrd is in the way then
> you could even go as far as moving them away if you wanted.
>
Interestingly, this is essentially how I implemented it for arm64. It
boots to the point where it can retrieve the kaslr-seed from the DT
(and the 'nokaslr' command line argument), and either proceeds (if
there is no seed or nokaslr is passed), or it returns to the startup
code and remaps the kernel at a randomized offset.
However, the configurations are very different. The arm64 kernel
mappings are disjoint from the kernel's direct mapping, and the
physical offset is under the control of the bootloader anyway. So when
it returns to the startup code, it only updates the virtual mapping
not the physical placement.
> This would add some boot latency of course, but certainly in the
> sub-second range. That is negligible for those systems where KASLR is
> most relevant.
>
I will try to come up with something that makes it more self contained.
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 20/30] ARM: kernel: use PC relative symbol references in suspend/resume code
2017-08-14 16:02 ` [kernel-hardening] " Nicolas Pitre
@ 2017-08-14 18:14 ` Ard Biesheuvel
2017-08-14 18:37 ` Nicolas Pitre
0 siblings, 1 reply; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-14 18:14 UTC (permalink / raw)
To: Nicolas Pitre
Cc: Kernel Hardening, linux-arm-kernel, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 14 August 2017 at 17:02, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Mon, 14 Aug 2017, Ard Biesheuvel wrote:
>
>> Replace some unnecessary absolute references with relative ones. Also,
>> to prepare for runtime relocation, which occurs with the caches on,
>> defer taking the absolute address of cpu_resume_after_mmu() until after
>> the MMU is enabled.
>>
>> Cc: Russell King <linux@armlinux.org.uk>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>> arch/arm/kernel/sleep.S | 11 +++++------
>> 1 file changed, 5 insertions(+), 6 deletions(-)
>>
>> diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
>> index 3026b119d3ff..9efd1c7d3552 100644
>> --- a/arch/arm/kernel/sleep.S
>> +++ b/arch/arm/kernel/sleep.S
>> @@ -60,18 +60,17 @@
>> ENTRY(__cpu_suspend)
>> stmfd sp!, {r4 - r11, lr}
>> #ifdef MULTI_CPU
>> - ldr r10, =processor
>> - ldr r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
>> + ldr_l r4, processor + CPU_SLEEP_SIZE @ size of CPU sleep state
>> #else
>> - ldr r4, =cpu_suspend_size
>> + adr_l r4, cpu_suspend_size
>> #endif
>> mov r5, sp @ current virtual SP
>> add r4, r4, #12 @ Space for pgd, virt sp, phys resume fn
>> sub sp, sp, r4 @ allocate CPU state on stack
>> - ldr r3, =sleep_save_sp
>> + adr_l r3, sleep_save_sp
>> stmfd sp!, {r0, r1} @ save suspend func arg and pointer
>> ldr r3, [r3, #SLEEP_SAVE_SP_VIRT]
>> - ALT_SMP(ldr r0, =mpidr_hash)
>> + ALT_SMP(adr_l r0, mpidr_hash)
>> ALT_UP_B(1f)
>
> The above is dangerous. adr_l expands to more than one instruction which
> is not what ALT_SMP() was designed for. Here it might happen to work
> anyway because it is combined with ALT_UP_B() but with ALT_UP() it
> wouldn't. This is a mistake waiting to happen.
>
OK. I will use the opencoded sequence instead in this case. I.e.,
- ALT_SMP(ldr r0, =mpidr_hash)
+0: ALT_SMP(adr r0, 2f)
ALT_UP_B(1f)
+ ldr r1, [r0]
+ add r0, r0, r1
and
ENDPROC(__cpu_suspend)
+ .align 2
+2: .long mpidr_hash - .
.ltorg
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 20/30] ARM: kernel: use PC relative symbol references in suspend/resume code
2017-08-14 18:14 ` Ard Biesheuvel
@ 2017-08-14 18:37 ` Nicolas Pitre
0 siblings, 0 replies; 60+ messages in thread
From: Nicolas Pitre @ 2017-08-14 18:37 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Kernel Hardening, linux-arm-kernel, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Mon, 14 Aug 2017, Ard Biesheuvel wrote:
> On 14 August 2017 at 17:02, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Mon, 14 Aug 2017, Ard Biesheuvel wrote:
> >
> >> Replace some unnecessary absolute references with relative ones. Also,
> >> to prepare for runtime relocation, which occurs with the caches on,
> >> defer taking the absolute address of cpu_resume_after_mmu() until after
> >> the MMU is enabled.
> >>
> >> Cc: Russell King <linux@armlinux.org.uk>
> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >> ---
> >> arch/arm/kernel/sleep.S | 11 +++++------
> >> 1 file changed, 5 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> >> index 3026b119d3ff..9efd1c7d3552 100644
> >> --- a/arch/arm/kernel/sleep.S
> >> +++ b/arch/arm/kernel/sleep.S
> >> @@ -60,18 +60,17 @@
> >> ENTRY(__cpu_suspend)
> >> stmfd sp!, {r4 - r11, lr}
> >> #ifdef MULTI_CPU
> >> - ldr r10, =processor
> >> - ldr r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
> >> + ldr_l r4, processor + CPU_SLEEP_SIZE @ size of CPU sleep state
> >> #else
> >> - ldr r4, =cpu_suspend_size
> >> + adr_l r4, cpu_suspend_size
> >> #endif
> >> mov r5, sp @ current virtual SP
> >> add r4, r4, #12 @ Space for pgd, virt sp, phys resume fn
> >> sub sp, sp, r4 @ allocate CPU state on stack
> >> - ldr r3, =sleep_save_sp
> >> + adr_l r3, sleep_save_sp
> >> stmfd sp!, {r0, r1} @ save suspend func arg and pointer
> >> ldr r3, [r3, #SLEEP_SAVE_SP_VIRT]
> >> - ALT_SMP(ldr r0, =mpidr_hash)
> >> + ALT_SMP(adr_l r0, mpidr_hash)
> >> ALT_UP_B(1f)
> >
> > The above is dangerous. adr_l expands to more than one instruction which
> > is not what ALT_SMP() was designed for. Here it might happen to work
> > anyway because it is combined with ALT_UP_B() but with ALT_UP() it
> > wouldn't. This is a mistake waiting to happen.
> >
>
> OK. I will use the opencoded sequence instead in this case. I.e.,
>
> - ALT_SMP(ldr r0, =mpidr_hash)
> +0: ALT_SMP(adr r0, 2f)
> ALT_UP_B(1f)
> + ldr r1, [r0]
> + add r0, r0, r1
>
> and
>
> ENDPROC(__cpu_suspend)
> + .align 2
> +2: .long mpidr_hash - .
> .ltorg
>
Yeah... I see no way around it.
And if you make this particular case into a commit of its own, then the
commit log may carry the above reasoning.
Nicolas
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 29/30] efi/libstub: arm: reserve bootloader supplied initrd in memory map
2017-08-14 12:54 ` [kernel-hardening] [PATCH 29/30] efi/libstub: arm: reserve bootloader supplied initrd in memory map Ard Biesheuvel
@ 2017-08-18 11:48 ` Ard Biesheuvel
2017-08-21 10:37 ` Mark Rutland
1 sibling, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-18 11:48 UTC (permalink / raw)
To: Kernel Hardening
Cc: linux-arm-kernel, Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Tony Lindgren, Matt Fleming, Dave Martin
On 14 August 2017 at 13:54, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> Under KASLR, the EFI stub may allocate the kernel anywhere in the
> physical address space, which could be right on top of an initrd
> if it was supplied by the bootloader (i.e., GRUB) in /chosen rather
> than passed via the initrd= command line option. So allocate the
> pages explicitly, this ensures that the random memory allocation
> routine will disregard the region.
>
> Note that this means that we need to defer the handle_kernel_image()
> call.
>
> Cc: Matt Fleming <matt@codeblueprint.co.uk>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
If nobody objects, I will take this patch through the EFI tree
separately for v4.14, given that it fixes an issue that may affect
arm64 as well.
> ---
> drivers/firmware/efi/libstub/arm-stub.c | 51 ++++++++++++--------
> drivers/firmware/efi/libstub/efistub.h | 3 ++
> drivers/firmware/efi/libstub/fdt.c | 42 ++++++++++++++++
> 3 files changed, 75 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
> index 8181ac179d14..f5ef5ccd5f45 100644
> --- a/drivers/firmware/efi/libstub/arm-stub.c
> +++ b/drivers/firmware/efi/libstub/arm-stub.c
> @@ -133,6 +133,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
> unsigned long reserve_size = 0;
> enum efi_secureboot_mode secure_boot;
> struct screen_info *si;
> + bool have_chosen_initrd;
>
> /* Check if we were booted by the EFI firmware */
> if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
> @@ -183,15 +184,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
>
> si = setup_graphics(sys_table);
>
> - status = handle_kernel_image(sys_table, image_addr, &image_size,
> - &reserve_addr,
> - &reserve_size,
> - dram_base, image);
> - if (status != EFI_SUCCESS) {
> - pr_efi_err(sys_table, "Failed to relocate kernel\n");
> - goto fail_free_cmdline;
> - }
> -
> secure_boot = efi_get_secureboot(sys_table);
>
> /*
> @@ -209,7 +201,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
>
> if (status != EFI_SUCCESS) {
> pr_efi_err(sys_table, "Failed to load device tree!\n");
> - goto fail_free_image;
> + goto fail_free_cmdline;
> }
> }
>
> @@ -222,16 +214,33 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
> pr_efi(sys_table, "Using DTB from configuration table\n");
> }
>
> - if (!fdt_addr)
> + if (!fdt_addr) {
> pr_efi(sys_table, "Generating empty DTB\n");
> + have_chosen_initrd = false;
> + } else {
> + status = efi_reserve_dtb_initrd(sys_table, (void *)fdt_addr);
> + have_chosen_initrd = (status != EFI_NOT_FOUND);
> + }
>
> - status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
> - efi_get_max_initrd_addr(dram_base,
> - *image_addr),
> - (unsigned long *)&initrd_addr,
> - (unsigned long *)&initrd_size);
> - if (status != EFI_SUCCESS)
> - pr_efi_err(sys_table, "Failed initrd from command line!\n");
> + status = handle_kernel_image(sys_table, image_addr, &image_size,
> + &reserve_addr, &reserve_size,
> + dram_base, image);
> + if (status != EFI_SUCCESS) {
> + pr_efi_err(sys_table, "Failed to relocate kernel\n");
> + goto fail_free_fdt;
> + }
> +
> + if (!have_chosen_initrd) {
> + status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> + "initrd=",
> + efi_get_max_initrd_addr(dram_base,
> + *image_addr),
> + (unsigned long *)&initrd_addr,
> + (unsigned long *)&initrd_size);
> + if (status != EFI_SUCCESS)
> + pr_efi_err(sys_table,
> + "Failed initrd from command line!\n");
> + }
>
> efi_random_get_seed(sys_table);
>
> @@ -272,11 +281,11 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
> pr_efi_err(sys_table, "Failed to update FDT and exit boot services\n");
>
> efi_free(sys_table, initrd_size, initrd_addr);
> - efi_free(sys_table, fdt_size, fdt_addr);
> -
> -fail_free_image:
> efi_free(sys_table, image_size, *image_addr);
> efi_free(sys_table, reserve_size, reserve_addr);
> +
> +fail_free_fdt:
> + efi_free(sys_table, fdt_size, fdt_addr);
> fail_free_cmdline:
> free_screen_info(sys_table, si);
> efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> index aaf2aeb785ea..35b514d7d962 100644
> --- a/drivers/firmware/efi/libstub/efistub.h
> +++ b/drivers/firmware/efi/libstub/efistub.h
> @@ -68,4 +68,7 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
>
> efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
>
> +efi_status_t efi_reserve_dtb_initrd(efi_system_table_t *sys_table_arg,
> + const void *fdt);
> +
> #endif
> diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
> index 8830fa601e45..54408c95e094 100644
> --- a/drivers/firmware/efi/libstub/fdt.c
> +++ b/drivers/firmware/efi/libstub/fdt.c
> @@ -385,3 +385,45 @@ void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size)
>
> return fdt;
> }
> +
> +efi_status_t efi_reserve_dtb_initrd(efi_system_table_t *sys_table_arg,
> + const void *fdt)
> +{
> + int chosen, len;
> + const void *prop;
> + efi_physical_addr_t start, end;
> + unsigned long num_pages;
> + efi_status_t status;
> +
> + chosen = fdt_path_offset(fdt, "/chosen");
> + if (chosen == -FDT_ERR_NOTFOUND)
> + return EFI_NOT_FOUND;
> +
> + prop = fdt_getprop(fdt, chosen, "linux,initrd-start", &len);
> + if (!prop)
> + return EFI_NOT_FOUND;
> +
> + start = (len == sizeof(fdt32_t)) ? fdt32_to_cpu(*(fdt32_t *)prop)
> + : fdt64_to_cpu(*(fdt64_t *)prop);
> +
> + prop = fdt_getprop(fdt, chosen, "linux,initrd-end", &len);
> + if (!prop)
> + return EFI_NOT_FOUND;
> +
> + end = (len == sizeof(fdt32_t)) ? fdt32_to_cpu(*(fdt32_t *)prop)
> + : fdt64_to_cpu(*(fdt64_t *)prop);
> +
> + start = round_down(start, EFI_PAGE_SIZE);
> + num_pages = round_up(end - start, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
> +
> + status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
> + EFI_LOADER_DATA, num_pages, &start);
> +
> + if (status != EFI_SUCCESS)
> + pr_efi_err(sys_table_arg,
> + "Failed to reserve initrd area found in /chosen\n");
> + else
> + pr_efi(sys_table_arg, "Using initrd found in /chosen\n");
> +
> + return status;
> +}
> --
> 2.11.0
>
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 29/30] efi/libstub: arm: reserve bootloader supplied initrd in memory map
2017-08-14 12:54 ` [kernel-hardening] [PATCH 29/30] efi/libstub: arm: reserve bootloader supplied initrd in memory map Ard Biesheuvel
2017-08-18 11:48 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-08-21 10:37 ` Mark Rutland
2017-08-21 10:39 ` Ard Biesheuvel
1 sibling, 1 reply; 60+ messages in thread
From: Mark Rutland @ 2017-08-21 10:37 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: kernel-hardening, linux-arm-kernel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Tony Lindgren, Matt Fleming, Dave Martin
On Mon, Aug 14, 2017 at 01:54:10PM +0100, Ard Biesheuvel wrote:
> Under KASLR, the EFI stub may allocate the kernel anywhere in the
> physical address space, which could be right on top of an initrd
> if it was supplied by the bootloader (i.e., GRUB) in /chosen rather
> than passed via the initrd= command line option. So allocate the
> pages explicitly, this ensures that the random memory allocation
> routine will disregard the region.
I'm a little confused. Shouldn't the bootloader have allocated that
memory, leaving it reserved?
If it hasn't, then that region could be allcoated by anything else at
any time (e.g. by the code which loads the kernel, or some EFI timer
callback), so that sounds like a bootloader bug that we can't fix.
Thanks,
Mark.
>
> Note that this means that we need to defer the handle_kernel_image()
> call.
>
> Cc: Matt Fleming <matt@codeblueprint.co.uk>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> drivers/firmware/efi/libstub/arm-stub.c | 51 ++++++++++++--------
> drivers/firmware/efi/libstub/efistub.h | 3 ++
> drivers/firmware/efi/libstub/fdt.c | 42 ++++++++++++++++
> 3 files changed, 75 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
> index 8181ac179d14..f5ef5ccd5f45 100644
> --- a/drivers/firmware/efi/libstub/arm-stub.c
> +++ b/drivers/firmware/efi/libstub/arm-stub.c
> @@ -133,6 +133,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
> unsigned long reserve_size = 0;
> enum efi_secureboot_mode secure_boot;
> struct screen_info *si;
> + bool have_chosen_initrd;
>
> /* Check if we were booted by the EFI firmware */
> if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
> @@ -183,15 +184,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
>
> si = setup_graphics(sys_table);
>
> - status = handle_kernel_image(sys_table, image_addr, &image_size,
> - &reserve_addr,
> - &reserve_size,
> - dram_base, image);
> - if (status != EFI_SUCCESS) {
> - pr_efi_err(sys_table, "Failed to relocate kernel\n");
> - goto fail_free_cmdline;
> - }
> -
> secure_boot = efi_get_secureboot(sys_table);
>
> /*
> @@ -209,7 +201,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
>
> if (status != EFI_SUCCESS) {
> pr_efi_err(sys_table, "Failed to load device tree!\n");
> - goto fail_free_image;
> + goto fail_free_cmdline;
> }
> }
>
> @@ -222,16 +214,33 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
> pr_efi(sys_table, "Using DTB from configuration table\n");
> }
>
> - if (!fdt_addr)
> + if (!fdt_addr) {
> pr_efi(sys_table, "Generating empty DTB\n");
> + have_chosen_initrd = false;
> + } else {
> + status = efi_reserve_dtb_initrd(sys_table, (void *)fdt_addr);
> + have_chosen_initrd = (status != EFI_NOT_FOUND);
> + }
>
> - status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
> - efi_get_max_initrd_addr(dram_base,
> - *image_addr),
> - (unsigned long *)&initrd_addr,
> - (unsigned long *)&initrd_size);
> - if (status != EFI_SUCCESS)
> - pr_efi_err(sys_table, "Failed initrd from command line!\n");
> + status = handle_kernel_image(sys_table, image_addr, &image_size,
> + &reserve_addr, &reserve_size,
> + dram_base, image);
> + if (status != EFI_SUCCESS) {
> + pr_efi_err(sys_table, "Failed to relocate kernel\n");
> + goto fail_free_fdt;
> + }
> +
> + if (!have_chosen_initrd) {
> + status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> + "initrd=",
> + efi_get_max_initrd_addr(dram_base,
> + *image_addr),
> + (unsigned long *)&initrd_addr,
> + (unsigned long *)&initrd_size);
> + if (status != EFI_SUCCESS)
> + pr_efi_err(sys_table,
> + "Failed initrd from command line!\n");
> + }
>
> efi_random_get_seed(sys_table);
>
> @@ -272,11 +281,11 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
> pr_efi_err(sys_table, "Failed to update FDT and exit boot services\n");
>
> efi_free(sys_table, initrd_size, initrd_addr);
> - efi_free(sys_table, fdt_size, fdt_addr);
> -
> -fail_free_image:
> efi_free(sys_table, image_size, *image_addr);
> efi_free(sys_table, reserve_size, reserve_addr);
> +
> +fail_free_fdt:
> + efi_free(sys_table, fdt_size, fdt_addr);
> fail_free_cmdline:
> free_screen_info(sys_table, si);
> efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> index aaf2aeb785ea..35b514d7d962 100644
> --- a/drivers/firmware/efi/libstub/efistub.h
> +++ b/drivers/firmware/efi/libstub/efistub.h
> @@ -68,4 +68,7 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
>
> efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
>
> +efi_status_t efi_reserve_dtb_initrd(efi_system_table_t *sys_table_arg,
> + const void *fdt);
> +
> #endif
> diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
> index 8830fa601e45..54408c95e094 100644
> --- a/drivers/firmware/efi/libstub/fdt.c
> +++ b/drivers/firmware/efi/libstub/fdt.c
> @@ -385,3 +385,45 @@ void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size)
>
> return fdt;
> }
> +
> +efi_status_t efi_reserve_dtb_initrd(efi_system_table_t *sys_table_arg,
> + const void *fdt)
> +{
> + int chosen, len;
> + const void *prop;
> + efi_physical_addr_t start, end;
> + unsigned long num_pages;
> + efi_status_t status;
> +
> + chosen = fdt_path_offset(fdt, "/chosen");
> + if (chosen == -FDT_ERR_NOTFOUND)
> + return EFI_NOT_FOUND;
> +
> + prop = fdt_getprop(fdt, chosen, "linux,initrd-start", &len);
> + if (!prop)
> + return EFI_NOT_FOUND;
> +
> + start = (len == sizeof(fdt32_t)) ? fdt32_to_cpu(*(fdt32_t *)prop)
> + : fdt64_to_cpu(*(fdt64_t *)prop);
> +
> + prop = fdt_getprop(fdt, chosen, "linux,initrd-end", &len);
> + if (!prop)
> + return EFI_NOT_FOUND;
> +
> + end = (len == sizeof(fdt32_t)) ? fdt32_to_cpu(*(fdt32_t *)prop)
> + : fdt64_to_cpu(*(fdt64_t *)prop);
> +
> + start = round_down(start, EFI_PAGE_SIZE);
> + num_pages = round_up(end - start, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
> +
> + status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
> + EFI_LOADER_DATA, num_pages, &start);
> +
> + if (status != EFI_SUCCESS)
> + pr_efi_err(sys_table_arg,
> + "Failed to reserve initrd area found in /chosen\n");
> + else
> + pr_efi(sys_table_arg, "Using initrd found in /chosen\n");
> +
> + return status;
> +}
> --
> 2.11.0
>
^ permalink raw reply [flat|nested] 60+ messages in thread
* [kernel-hardening] Re: [PATCH 29/30] efi/libstub: arm: reserve bootloader supplied initrd in memory map
2017-08-21 10:37 ` Mark Rutland
@ 2017-08-21 10:39 ` Ard Biesheuvel
0 siblings, 0 replies; 60+ messages in thread
From: Ard Biesheuvel @ 2017-08-21 10:39 UTC (permalink / raw)
To: Mark Rutland
Cc: Kernel Hardening, linux-arm-kernel, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Tony Lindgren, Matt Fleming, Dave Martin
On 21 August 2017 at 11:37, Mark Rutland <mark.rutland@arm.com> wrote:
> On Mon, Aug 14, 2017 at 01:54:10PM +0100, Ard Biesheuvel wrote:
>> Under KASLR, the EFI stub may allocate the kernel anywhere in the
>> physical address space, which could be right on top of an initrd
>> if it was supplied by the bootloader (i.e., GRUB) in /chosen rather
>> than passed via the initrd= command line option. So allocate the
>> pages explicitly, this ensures that the random memory allocation
>> routine will disregard the region.
>
> I'm a little confused. Shouldn't the bootloader have allocated that
> memory, leaving it reserved?
>
> If it hasn't, then that region could be allcoated by anything else at
> any time (e.g. by the code which loads the kernel, or some EFI timer
> callback), so that sounds like a bootloader bug that we can't fix.
>
Yeah, thinko on my part. Thanks for spotting that.
^ permalink raw reply [flat|nested] 60+ messages in thread
end of thread, other threads:[~2017-08-21 10:39 UTC | newest]
Thread overview: 60+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-14 12:53 [kernel-hardening] [PATCH 00/30] implement KASLR for ARM Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 01/30] asm-generic: add .data.rel.ro sections to __ro_after_init Ard Biesheuvel
2017-08-14 14:26 ` [kernel-hardening] " Arnd Bergmann
2017-08-14 12:53 ` [kernel-hardening] [PATCH 02/30] ARM: assembler: introduce adr_l, ldr_l and str_l macros Ard Biesheuvel
2017-08-14 15:29 ` [kernel-hardening] " Dave Martin
2017-08-14 15:38 ` Ard Biesheuvel
2017-08-14 15:50 ` Dave Martin
2017-08-14 16:18 ` Nicolas Pitre
2017-08-14 16:22 ` Ard Biesheuvel
2017-08-14 16:33 ` Nicolas Pitre
2017-08-14 16:42 ` Russell King - ARM Linux
2017-08-14 16:56 ` Ard Biesheuvel
2017-08-14 15:32 ` Dave Martin
2017-08-14 15:40 ` Ard Biesheuvel
2017-08-14 15:53 ` Dave Martin
2017-08-14 12:53 ` [kernel-hardening] [PATCH 03/30] ARM: head-common.S: use PC-relative insn sequence for __proc_info Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 04/30] ARM: head-common.S: use PC-relative insn sequence for idmap creation Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 05/30] ARM: head.S: use PC-relative insn sequence for secondary_data Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 06/30] ARM: kernel: use relative references for UP/SMP alternatives Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 07/30] ARM: head: use PC-relative insn sequence for __smp_alt Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 08/30] ARM: sleep.S: use PC-relative insn sequence for sleep_save_sp/mpidr_hash Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 09/30] ARM: head.S: use PC-relative insn sequences for __fixup_pv_table Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 10/30] ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 11/30] ARM: kvm: replace open coded VA->PA calculations with adr_l call Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 12/30] arm-soc: exynos: replace open coded VA->PA conversions Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 13/30] arm-soc: mvebu: replace open coded VA->PA conversion Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 14/30] arm-soc: various: replace open coded VA->PA calculation of pen_release Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 15/30] ARM: kernel: switch to relative exception tables Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 16/30] ARM: kernel: use relative phys-to-virt patch tables Ard Biesheuvel
2017-08-14 12:53 ` [kernel-hardening] [PATCH 17/30] arm-soc: tegra: make sleep asm code runtime relocatable Ard Biesheuvel
2017-08-14 14:42 ` [kernel-hardening] " Dave Martin
2017-08-14 14:49 ` Ard Biesheuvel
2017-08-14 15:29 ` Dave Martin
2017-08-14 12:53 ` [kernel-hardening] [PATCH 18/30] ARM: kernel: make vmlinux buildable as a PIE executable Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 19/30] ARM: kernel: use PC-relative symbol references in MMU switch code Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 20/30] ARM: kernel: use PC relative symbol references in suspend/resume code Ard Biesheuvel
2017-08-14 16:02 ` [kernel-hardening] " Nicolas Pitre
2017-08-14 18:14 ` Ard Biesheuvel
2017-08-14 18:37 ` Nicolas Pitre
2017-08-14 12:54 ` [kernel-hardening] [PATCH 21/30] ARM: mm: export default vmalloc base address Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 22/30] ARM: kernel: refer to swapper_pg_dir via its symbol Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 23/30] ARM: kernel: implement randomization of the kernel load address Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 24/30] ARM: decompressor: explicitly map decompressor binary cacheable Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 25/30] ARM: compressed: factor out zImage header and make it extensible Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 26/30] ARM: decompressor: add KASLR support Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 27/30] efi/libstub: add 'max' parameter to efi_random_alloc() Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 28/30] efi/libstub: check for vmalloc= command line argument Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 29/30] efi/libstub: arm: reserve bootloader supplied initrd in memory map Ard Biesheuvel
2017-08-18 11:48 ` [kernel-hardening] " Ard Biesheuvel
2017-08-21 10:37 ` Mark Rutland
2017-08-21 10:39 ` Ard Biesheuvel
2017-08-14 12:54 ` [kernel-hardening] [PATCH 30/30] efi/libstub: arm: implement KASLR Ard Biesheuvel
2017-08-14 15:30 ` [kernel-hardening] Re: [PATCH 00/30] implement KASLR for ARM Arnd Bergmann
2017-08-14 15:49 ` Ard Biesheuvel
2017-08-14 16:03 ` Arnd Bergmann
2017-08-14 16:28 ` Nicolas Pitre
2017-08-14 17:28 ` Ard Biesheuvel
2017-08-14 18:01 ` Nicolas Pitre
2017-08-14 18:08 ` Ard Biesheuvel
2017-08-14 16:16 ` Nicolas Pitre
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).