* [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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 collect some pseudo-entropy, and randomize
the physical offset of the decompressed kernel, taking placement of DTB,
initrd and reserved regions into account
- changes to the UEFI stub code to choose the KASLR offset and communicate
it to the decompressor
To test these changes, boot a multi_v7_defconfig+CONFIG_RANDOMIZE_BASE=y
build 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) <----
v2: - make adr_l/ldr_l/str_l macros work in .arm sections under Thumb2 builds,
and remove support for conditional execution, which is finicky when
building for Thumb2 with -mimplicit-it=always
- work around a section mismatch warning resulting from using the -fpic
switch
- drop bogus patch to reserve initrd memory in the UEFI stub
- add support to the decompressor to perform the randomization
autonomously; this also removes the need for the extended zImage
header, since the UEFI stub doesn't need it, and other bootloaders
no longer have to do anything to enable KASLR.
- avoid macros in ALT_SMP() calls (#9)
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 (29):
net/core: work around section mismatch warning for ptp_classifier
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: decompressor: add KASLR support
efi/libstub: add 'max' parameter to efi_random_alloc()
efi/libstub: check for vmalloc= command line argument
efi/libstub: arm: implement KASLR
arch/arm/Kconfig | 19 +
arch/arm/Makefile | 5 +
arch/arm/boot/compressed/Makefile | 8 +-
arch/arm/boot/compressed/head.S | 125 ++++--
arch/arm/boot/compressed/kaslr.c | 398 ++++++++++++++++++++
arch/arm/include/asm/Kbuild | 1 -
arch/arm/include/asm/assembler.h | 86 ++++-
arch/arm/include/asm/extable.h | 19 +
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/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 | 28 +-
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/arm32-stub.c | 47 ++-
drivers/firmware/efi/libstub/arm64-stub.c | 2 +-
drivers/firmware/efi/libstub/efi-stub-helper.c | 9 +
drivers/firmware/efi/libstub/efistub.h | 4 +-
drivers/firmware/efi/libstub/random.c | 11 +-
include/asm-generic/vmlinux.lds.h | 2 +-
include/linux/hidden.h | 20 +
net/core/ptp_classifier.c | 7 +-
scripts/module-common.lds | 1 +
scripts/sortextable.c | 2 +-
49 files changed, 982 insertions(+), 350 deletions(-)
create mode 100644 arch/arm/boot/compressed/kaslr.c
create mode 100644 arch/arm/include/asm/extable.h
create mode 100644 include/linux/hidden.h
--
2.11.0
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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 collect some pseudo-entropy, and randomize
the physical offset of the decompressed kernel, taking placement of DTB,
initrd and reserved regions into account
- changes to the UEFI stub code to choose the KASLR offset and communicate
it to the decompressor
To test these changes, boot a multi_v7_defconfig+CONFIG_RANDOMIZE_BASE=y
build 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) <----
v2: - make adr_l/ldr_l/str_l macros work in .arm sections under Thumb2 builds,
and remove support for conditional execution, which is finicky when
building for Thumb2 with -mimplicit-it=always
- work around a section mismatch warning resulting from using the -fpic
switch
- drop bogus patch to reserve initrd memory in the UEFI stub
- add support to the decompressor to perform the randomization
autonomously; this also removes the need for the extended zImage
header, since the UEFI stub doesn't need it, and other bootloaders
no longer have to do anything to enable KASLR.
- avoid macros in ALT_SMP() calls (#9)
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 (29):
net/core: work around section mismatch warning for ptp_classifier
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: decompressor: add KASLR support
efi/libstub: add 'max' parameter to efi_random_alloc()
efi/libstub: check for vmalloc= command line argument
efi/libstub: arm: implement KASLR
arch/arm/Kconfig | 19 +
arch/arm/Makefile | 5 +
arch/arm/boot/compressed/Makefile | 8 +-
arch/arm/boot/compressed/head.S | 125 ++++--
arch/arm/boot/compressed/kaslr.c | 398 ++++++++++++++++++++
arch/arm/include/asm/Kbuild | 1 -
arch/arm/include/asm/assembler.h | 86 ++++-
arch/arm/include/asm/extable.h | 19 +
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/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 | 28 +-
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/arm32-stub.c | 47 ++-
drivers/firmware/efi/libstub/arm64-stub.c | 2 +-
drivers/firmware/efi/libstub/efi-stub-helper.c | 9 +
drivers/firmware/efi/libstub/efistub.h | 4 +-
drivers/firmware/efi/libstub/random.c | 11 +-
include/asm-generic/vmlinux.lds.h | 2 +-
include/linux/hidden.h | 20 +
net/core/ptp_classifier.c | 7 +-
scripts/module-common.lds | 1 +
scripts/sortextable.c | 2 +-
49 files changed, 982 insertions(+), 350 deletions(-)
create mode 100644 arch/arm/boot/compressed/kaslr.c
create mode 100644 arch/arm/include/asm/extable.h
create mode 100644 include/linux/hidden.h
--
2.11.0
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 01/29] net/core: work around section mismatch warning for ptp_classifier
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
The routine ptp_classifier_init() uses an initializer for an
automatic struct type variable which refers to an __initdata
symbol. This is perfectly legal, but may trigger a section
mismatch warning when running the compiler in -fpic mode, due
to the fact that the initializer may be emitted into an anonymous
.data section thats lack the __init annotation. So work around it
by using assignments instead.
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
net/core/ptp_classifier.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/core/ptp_classifier.c b/net/core/ptp_classifier.c
index 703cf76aa7c2..7109c168b5e0 100644
--- a/net/core/ptp_classifier.c
+++ b/net/core/ptp_classifier.c
@@ -185,9 +185,10 @@ void __init ptp_classifier_init(void)
{ 0x16, 0, 0, 0x00000000 },
{ 0x06, 0, 0, 0x00000000 },
};
- struct sock_fprog_kern ptp_prog = {
- .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter,
- };
+ struct sock_fprog_kern ptp_prog;
+
+ ptp_prog.len = ARRAY_SIZE(ptp_filter);
+ ptp_prog.filter = ptp_filter;
BUG_ON(bpf_prog_create(&ptp_insns, &ptp_prog));
}
--
2.11.0
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [kernel-hardening] [PATCH v2 01/29] net/core: work around section mismatch warning for ptp_classifier
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: Ard Biesheuvel, Arnd Bergmann, Nicolas Pitre, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin, David S. Miller
The routine ptp_classifier_init() uses an initializer for an
automatic struct type variable which refers to an __initdata
symbol. This is perfectly legal, but may trigger a section
mismatch warning when running the compiler in -fpic mode, due
to the fact that the initializer may be emitted into an anonymous
.data section thats lack the __init annotation. So work around it
by using assignments instead.
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
net/core/ptp_classifier.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/core/ptp_classifier.c b/net/core/ptp_classifier.c
index 703cf76aa7c2..7109c168b5e0 100644
--- a/net/core/ptp_classifier.c
+++ b/net/core/ptp_classifier.c
@@ -185,9 +185,10 @@ void __init ptp_classifier_init(void)
{ 0x16, 0, 0, 0x00000000 },
{ 0x06, 0, 0, 0x00000000 },
};
- struct sock_fprog_kern ptp_prog = {
- .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter,
- };
+ struct sock_fprog_kern ptp_prog;
+
+ ptp_prog.len = ARRAY_SIZE(ptp_filter);
+ ptp_prog.filter = ptp_filter;
BUG_ON(bpf_prog_create(&ptp_insns, &ptp_prog));
}
--
2.11.0
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [PATCH v2 02/29] asm-generic: add .data.rel.ro sections to __ro_after_init
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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.
Acked-by: 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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 02/29] asm-generic: add .data.rel.ro sections to __ro_after_init
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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.
Acked-by: 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] 166+ messages in thread
* [PATCH v2 03/29] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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, 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 | 76 ++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index ad301f107dd2..341e4ed1ef84 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -518,4 +518,80 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
#endif
.endm
+ .macro __adldst_l, op, reg, sym, tmp
+ .if __LINUX_ARM_ARCH__ < 7
+ ldr \tmp, 111f
+ .subsection 1
+ .align 2
+111: .long \sym - (222f + 8)
+ .previous
+ .else
+ /*
+ * In Thumb-2 builds, the PC bias depends on whether we are currently
+ * emitting into a .arm or a .thumb section. So emit a nop and take
+ * its size, so we can infer the execution mode and PC bias from it.
+ */
+ ARM( .set .Lnopsize, 4 )
+ THUMB( .pushsection ".discard.nop", "x", %note )
+ THUMB( 111: nop )
+ THUMB( .set .Lnopsize, . - 111b )
+ THUMB( .popsection )
+
+ movw \tmp, #:lower16:\sym - (222f + 2 * .Lnopsize)
+ movt \tmp, #:upper16:\sym - (222f + 2 * .Lnopsize)
+ .endif
+222:
+ .ifc \op, add
+ add \reg, \tmp, pc
+ .elseif .Lnopsize == 2 @ Thumb-2 mode
+ add \tmp, \tmp, pc
+ \op \reg, [\tmp]
+ .else
+ \op \reg, [pc, \tmp]
+ .endif
+ .endm
+
+ /*
+ * mov_l - move a constant value or [relocated] address into a register
+ */
+ .macro mov_l, dst:req, imm:req
+ .if __LINUX_ARM_ARCH__ < 7
+ ldr \dst, =\imm
+ .else
+ movw \dst, #:lower16:\imm
+ movt \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
+ __adldst_l add, \dst, \sym, \dst
+ .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
+ __adldst_l ldr, \dst, \sym, \dst
+ .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
+ __adldst_l str, \src, \sym, \tmp
+ .endm
+
#endif /* __ASM_ASSEMBLER_H__ */
--
2.11.0
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [kernel-hardening] [PATCH v2 03/29] ARM: assembler: introduce adr_l, ldr_l and str_l macros
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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, 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 | 76 ++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index ad301f107dd2..341e4ed1ef84 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -518,4 +518,80 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
#endif
.endm
+ .macro __adldst_l, op, reg, sym, tmp
+ .if __LINUX_ARM_ARCH__ < 7
+ ldr \tmp, 111f
+ .subsection 1
+ .align 2
+111: .long \sym - (222f + 8)
+ .previous
+ .else
+ /*
+ * In Thumb-2 builds, the PC bias depends on whether we are currently
+ * emitting into a .arm or a .thumb section. So emit a nop and take
+ * its size, so we can infer the execution mode and PC bias from it.
+ */
+ ARM( .set .Lnopsize, 4 )
+ THUMB( .pushsection ".discard.nop", "x", %note )
+ THUMB( 111: nop )
+ THUMB( .set .Lnopsize, . - 111b )
+ THUMB( .popsection )
+
+ movw \tmp, #:lower16:\sym - (222f + 2 * .Lnopsize)
+ movt \tmp, #:upper16:\sym - (222f + 2 * .Lnopsize)
+ .endif
+222:
+ .ifc \op, add
+ add \reg, \tmp, pc
+ .elseif .Lnopsize == 2 @ Thumb-2 mode
+ add \tmp, \tmp, pc
+ \op \reg, [\tmp]
+ .else
+ \op \reg, [pc, \tmp]
+ .endif
+ .endm
+
+ /*
+ * mov_l - move a constant value or [relocated] address into a register
+ */
+ .macro mov_l, dst:req, imm:req
+ .if __LINUX_ARM_ARCH__ < 7
+ ldr \dst, =\imm
+ .else
+ movw \dst, #:lower16:\imm
+ movt \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
+ __adldst_l add, \dst, \sym, \dst
+ .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
+ __adldst_l ldr, \dst, \sym, \dst
+ .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
+ __adldst_l str, \src, \sym, \tmp
+ .endm
+
#endif /* __ASM_ASSEMBLER_H__ */
--
2.11.0
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [PATCH v2 04/29] ARM: head-common.S: use PC-relative insn sequence for __proc_info
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 04/29] ARM: head-common.S: use PC-relative insn sequence for __proc_info
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 05/29] ARM: head-common.S: use PC-relative insn sequence for idmap creation
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 05/29] ARM: head-common.S: use PC-relative insn sequence for idmap creation
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 06/29] ARM: head.S: use PC-relative insn sequence for secondary_data
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 06/29] ARM: head.S: use PC-relative insn sequence for secondary_data
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 07/29] ARM: kernel: use relative references for UP/SMP alternatives
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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 341e4ed1ef84..a0906c1fc65d 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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 07/29] ARM: kernel: use relative references for UP/SMP alternatives
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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 341e4ed1ef84..a0906c1fc65d 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] 166+ messages in thread
* [PATCH v2 08/29] ARM: head: use PC-relative insn sequence for __smp_alt
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 08/29] ARM: head: use PC-relative insn sequence for __smp_alt
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 09/29] ARM: sleep.S: use PC-relative insn sequence for sleep_save_sp/mpidr_hash
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
Replace the open coded PC relative offset calculations with adr_l and
ldr_l invocations. Note that ALT_SMP() expects a single instruction
so move the macro invocation after it.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/sleep.S | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 0f6c1000582c..f4920b5d0fc4 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -71,8 +71,9 @@ ENTRY(__cpu_suspend)
ldr 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(W(nop)) @ don't use adr_l inside ALT_SMP()
ALT_UP_B(1f)
+ adr_l r0, mpidr_hash
/* 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
compute_mpidr_hash r0, r6, r7, r8, r2, r1
@@ -137,9 +138,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 +147,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 +161,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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 09/29] ARM: sleep.S: use PC-relative insn sequence for sleep_save_sp/mpidr_hash
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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. Note that ALT_SMP() expects a single instruction
so move the macro invocation after it.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/kernel/sleep.S | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 0f6c1000582c..f4920b5d0fc4 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -71,8 +71,9 @@ ENTRY(__cpu_suspend)
ldr 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(W(nop)) @ don't use adr_l inside ALT_SMP()
ALT_UP_B(1f)
+ adr_l r0, mpidr_hash
/* 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
compute_mpidr_hash r0, r6, r7, r8, r2, r1
@@ -137,9 +138,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 +147,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 +161,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] 166+ messages in thread
* [PATCH v2 10/29] ARM: head.S: use PC-relative insn sequences for __fixup_pv_table
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 10/29] ARM: head.S: use PC-relative insn sequences for __fixup_pv_table
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 11/29] ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 11/29] ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 12/29] ARM: kvm: replace open coded VA->PA calculations with adr_l call
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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..3c2d1738d3f4 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 additional 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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 12/29] ARM: kvm: replace open coded VA->PA calculations with adr_l call
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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..3c2d1738d3f4 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 additional 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] 166+ messages in thread
* [PATCH v2 13/29] arm-soc: exynos: replace open coded VA->PA conversions
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 13/29] arm-soc: exynos: replace open coded VA->PA conversions
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 14/29] arm-soc: mvebu: replace open coded VA->PA conversion
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 14/29] arm-soc: mvebu: replace open coded VA->PA conversion
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 15/29] arm-soc: various: replace open coded VA->PA calculation of pen_release
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 15/29] arm-soc: various: replace open coded VA->PA calculation of pen_release
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 16/29] ARM: kernel: switch to relative exception tables
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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 | 19 +++++++++++++++++
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, 64 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 a0906c1fc65d..ae43859a9000 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..c85d1f4404b7
--- /dev/null
+++ b/arch/arm/include/asm/extable.h
@@ -0,0 +1,19 @@
+#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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 16/29] ARM: kernel: switch to relative exception tables
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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 | 19 +++++++++++++++++
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, 64 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 a0906c1fc65d..ae43859a9000 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..c85d1f4404b7
--- /dev/null
+++ b/arch/arm/include/asm/extable.h
@@ -0,0 +1,19 @@
+#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] 166+ messages in thread
* [PATCH v2 17/29] ARM: kernel: use relative phys-to-virt patch tables
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 17/29] ARM: kernel: use relative phys-to-virt patch tables
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 18/29] arm-soc: tegra: make sleep asm code runtime relocatable
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 18/29] arm-soc: tegra: make sleep asm code runtime relocatable
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 19/29] ARM: kernel: make vmlinux buildable as a PIE executable
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
Update the build flags and linker script to allow vmlinux to be built
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 | 2 +-
arch/arm/kernel/vmlinux.lds.S | 9 +++++++++
include/linux/hidden.h | 20 ++++++++++++++++++++
scripts/module-common.lds | 1 +
6 files changed, 40 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..8544c8148b9f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -52,6 +52,11 @@ AS += -EL
LD += -EL
endif
+ifeq ($(CONFIG_RELOCATABLE),y)
+KBUILD_CFLAGS += -fpic -include $(srctree)/include/linux/hidden.h
+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 ae43859a9000..0586e1c77a80 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -555,7 +555,7 @@ 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
- .if __LINUX_ARM_ARCH__ < 7
+ .if CONFIG_RELOCATABLE == 1 || __LINUX_ARM_ARCH__ < 7
ldr \dst, =\imm
.else
movw \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..781fb6f0c742
--- /dev/null
+++ b/include/linux/hidden.h
@@ -0,0 +1,20 @@
+/*
+ * 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)
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index d61b9e8678e8..55bb41f32c8a 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -7,6 +7,7 @@ SECTIONS {
/DISCARD/ : {
*(.discard)
*(.discard.*)
+ *(*.discard.*)
}
__ksymtab 0 : { *(SORT(___ksymtab+*)) }
--
2.11.0
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [kernel-hardening] [PATCH v2 19/29] ARM: kernel: make vmlinux buildable as a PIE executable
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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 built
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 | 2 +-
arch/arm/kernel/vmlinux.lds.S | 9 +++++++++
include/linux/hidden.h | 20 ++++++++++++++++++++
scripts/module-common.lds | 1 +
6 files changed, 40 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..8544c8148b9f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -52,6 +52,11 @@ AS += -EL
LD += -EL
endif
+ifeq ($(CONFIG_RELOCATABLE),y)
+KBUILD_CFLAGS += -fpic -include $(srctree)/include/linux/hidden.h
+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 ae43859a9000..0586e1c77a80 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -555,7 +555,7 @@ 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
- .if __LINUX_ARM_ARCH__ < 7
+ .if CONFIG_RELOCATABLE == 1 || __LINUX_ARM_ARCH__ < 7
ldr \dst, =\imm
.else
movw \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..781fb6f0c742
--- /dev/null
+++ b/include/linux/hidden.h
@@ -0,0 +1,20 @@
+/*
+ * 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)
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index d61b9e8678e8..55bb41f32c8a 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -7,6 +7,7 @@ SECTIONS {
/DISCARD/ : {
*(.discard)
*(.discard.*)
+ *(*.discard.*)
}
__ksymtab 0 : { *(SORT(___ksymtab+*)) }
--
2.11.0
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [PATCH v2 20/29] ARM: kernel: use PC-relative symbol references in MMU switch code
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 20/29] ARM: kernel: use PC-relative symbol references in MMU switch code
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 21/29] ARM: kernel: use PC relative symbol references in suspend/resume code
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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 | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index f4920b5d0fc4..5b02744f2f12 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -60,15 +60,14 @@
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(W(nop)) @ don't use adr_l inside ALT_SMP()
@@ -101,13 +100,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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 21/29] ARM: kernel: use PC relative symbol references in suspend/resume code
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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 | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index f4920b5d0fc4..5b02744f2f12 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -60,15 +60,14 @@
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(W(nop)) @ don't use adr_l inside ALT_SMP()
@@ -101,13 +100,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] 166+ messages in thread
* [PATCH v2 22/29] ARM: mm: export default vmalloc base address
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 22/29] ARM: mm: export default vmalloc base address
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 23/29] ARM: kernel: refer to swapper_pg_dir via its symbol
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 23/29] ARM: kernel: refer to swapper_pg_dir via its symbol
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 24/29] ARM: kernel: implement randomization of the kernel load address
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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..fe4a2cd1f15c 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
+ 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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 24/29] ARM: kernel: implement randomization of the kernel load address
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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..fe4a2cd1f15c 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
+ 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] 166+ messages in thread
* [PATCH v2 25/29] ARM: decompressor: explicitly map decompressor binary cacheable
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 25/29] ARM: decompressor: explicitly map decompressor binary cacheable
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 26/29] ARM: decompressor: add KASLR support
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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 will extract some pseudo-randomness from the low
bits of the generic timer (if available), and use CRC-16 to combine
it with the build ID string and the device tree binary (which ideally
has a /chosen/kaslr-seed property, but may also have other properties
that differ between boots). This seed is used to select one of the
candidate offsets in the lowmem region that don't overlap the zImage
itself, the DTB, the initrd and /memreserve/s and/or /reserved-memory
nodes that should be left alone.
When booting via the UEFI stub, it is left up to the firmware to supply
a suitable seed and select an offset.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/boot/compressed/Makefile | 8 +-
arch/arm/boot/compressed/head.S | 84 ++++-
arch/arm/boot/compressed/kaslr.c | 398 ++++++++++++++++++++
3 files changed, 484 insertions(+), 6 deletions(-)
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index d50430c40045..771b1ba1baa3 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -85,8 +85,14 @@ $(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/
$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
$(addprefix $(obj)/,$(libfdt_hdrs))
+ifneq ($(CONFIG_ARM_ATAG_DTB_COMPAT)$(CONFIG_RANDOMIZE_BASE),)
+OBJS += $(libfdt_objs)
ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
-OBJS += $(libfdt_objs) atags_to_fdt.o
+OBJS += atags_to_fdt.o
+endif
+ifeq ($(CONFIG_RANDOMIZE_BASE),y)
+OBJS += kaslr.o
+endif
endif
targets := vmlinux vmlinux.lds piggy_data piggy.o \
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 583cc6899d98..79b4033b0ed4 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -381,6 +381,42 @@ restart: adr r0, LC0
dtb_check_done:
#endif
+#ifdef CONFIG_RANDOMIZE_BASE
+ ldr r1, kaslr_offset @ check if the kaslr_offset is
+ cmp r1, #0 @ already set
+#ifdef CONFIG_EFI_STUB
+ ldreq r1, __efi_boot @ UEFI has its own KASLR init
+ cmpeq r1, #0 @ routine so skip over this one
+#endif
+ bne 1f
+
+ stmfd sp!, {r0-r3, ip, lr}
+ adr_l r2, _text @ start of zImage
+ stmfd sp!, {r2, r8, r10} @ pass stack arguments
+
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
+ /*
+ * Get some pseudo-entropy from the low bits of the generic
+ * timer if it is implemented.
+ */
+ mrc p15, 0, r1, c0, c1, 1 @ read ID_PFR1 register
+ tst r1, #0x10000 @ have generic timer?
+ beq 0f
+ mrrc p15, 1, r3, r1, c14 @ read CNTVCT
+#endif
+0: adr_l r0, kaslr_offset @ pass &kaslr_offset in r0
+ mov r1, r4 @ pass base address
+ mov r2, r9 @ pass decompressed image size
+ eor r3, r3, r3, ror #16 @ pass initial seed
+ bl kaslr_early_init
+ add sp, sp, #12
+ cmp r0, #0
+ addne r4, r4, r0 @ add offset to base address
+ ldmfd sp!, {r0-r3, ip, lr}
+ bne restart
+1:
+#endif
+
/*
* Check to see if we will overwrite ourselves.
* r4 = final kernel address (possibly with LSB set)
@@ -1356,25 +1392,63 @@ __hyp_reentry_vectors:
__enter_kernel:
mov r0, #0 @ must be 0
+#ifdef CONFIG_RANDOMIZE_BASE
+ ldr 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
+#ifdef CONFIG_RANDOMIZE_BASE
+ /*
+ * Minimal implementation of CRC-16 that does not use a
+ * lookup table and uses 32-bit wide loads, so it still
+ * performs reasonably well with the D-cache off. Equivalent
+ * to lib/crc16.c for input sizes that are 4 byte multiples.
+ */
+ENTRY(__crc16)
+ push {r4, lr}
+ ldr r3, =0xa001 @ CRC-16 polynomial
+0: subs r2, r2, #4
+ popmi {r4, pc}
+ ldr r4, [r1], #4
+#ifdef __ARMEB__
+ eor ip, r4, r4, ror #16 @ endian swap
+ bic ip, ip, #0x00ff0000
+ mov r4, r4, ror #8
+ eor r4, r4, ip, lsr #8
+#endif
+ eor r0, r0, r4
+ .rept 32
+ lsrs r0, r0, #1
+ eorcs r0, r0, r3
+ .endr
+ b 0b
+ENDPROC(__crc16)
+
+ .align 2
+kaslr_offset: .long 0
+#ifdef CONFIG_EFI_STUB
+__efi_boot: .long 0
+#endif
+#endif
+
reloc_code_end:
#ifdef CONFIG_EFI_STUB
.align 2
-_start: .long start - .
-
ENTRY(efi_stub_entry)
@ allocate space on stack for passing current zImage address
@ and for the EFI stub to return of new entry point of
@ zImage, as EFI stub may copy the kernel. Pointer address
@ is passed in r2. r0 and r1 are passed through from the
@ EFI firmware to efi_entry
- adr ip, _start
- ldr r3, [ip]
- add r3, r3, ip
+#ifdef CONFIG_RANDOMIZE_BASE
+ adr r3, __efi_boot
+ str r3, [r3] @ set __efi_boot != 0
+#endif
+ adr_l r3, start
stmfd sp!, {r3, lr}
mov r2, sp @ pass zImage address in r2
bl efi_entry
diff --git a/arch/arm/boot/compressed/kaslr.c b/arch/arm/boot/compressed/kaslr.c
new file mode 100644
index 000000000000..c68bdea764b6
--- /dev/null
+++ b/arch/arm/boot/compressed/kaslr.c
@@ -0,0 +1,398 @@
+/*
+ * 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.
+ *
+ */
+
+#include <libfdt.h>
+#include <linux/types.h>
+#include <generated/compile.h>
+#include <generated/utsrelease.h>
+#include <asm/pgtable.h>
+
+struct regions {
+ u32 pa_start;
+ u32 pa_end;
+ u32 image_size;
+ u32 zimage_start;
+ u32 zimage_size;
+ u32 dtb_start;
+ u32 dtb_size;
+ u32 initrd_start;
+ u32 initrd_size;
+ int reserved_mem;
+ int reserved_mem_addr_cells;
+ int reserved_mem_size_cells;
+};
+
+extern u32 __crc16(u32 crc, u32 const input[], int byte_count);
+
+static u32 __memparse(const char *val, const char **retptr)
+{
+ int base = 10;
+ u32 ret = 0;
+
+ if (*val == '0') {
+ val++;
+ if (*val == 'x' || *val == 'X') {
+ val++;
+ base = 16;
+ } else {
+ base = 8;
+ }
+ }
+
+ while (*val != ',' && *val != ' ' && *val != '\0') {
+ char c = *val++;
+
+ switch (c) {
+ case '0' ... '9':
+ ret = ret * base + (c - '0');
+ continue;
+ case 'a' ... 'f':
+ ret = ret * base + (c - 'a' + 10);
+ continue;
+ case 'A' ... 'F':
+ ret = ret * base + (c - 'A' + 10);
+ continue;
+ case 'g':
+ case 'G':
+ ret <<= 10;
+ case 'm':
+ case 'M':
+ ret <<= 10;
+ case 'k':
+ case 'K':
+ ret <<= 10;
+ break;
+ default:
+ if (retptr)
+ *retptr = NULL;
+ return 0;
+ }
+ }
+ if (retptr)
+ *retptr = val;
+ return ret;
+}
+
+static bool regions_intersect(u32 s1, u32 e1, u32 s2, u32 e2)
+{
+ return e1 >= s2 && e2 >= s1;
+}
+
+static bool intersects_reserved_region(const void *fdt, u32 start,
+ u32 end, struct regions *regions)
+{
+ int subnode, len, i;
+ u64 base, size;
+
+ /* check for overlap with /memreserve/ entries */
+ for (i = 0; i < fdt_num_mem_rsv(fdt); i++) {
+ if (fdt_get_mem_rsv(fdt, i, &base, &size) < 0)
+ continue;
+ if (regions_intersect(start, end, base, base + size))
+ return true;
+ }
+
+ if (regions->reserved_mem < 0)
+ return false;
+
+ /* check for overlap with static reservations in /reserved-memory */
+ for (subnode = fdt_first_subnode(fdt, regions->reserved_mem);
+ subnode >= 0;
+ subnode = fdt_next_subnode(fdt, subnode)) {
+ const fdt32_t *reg;
+
+ len = 0;
+ reg = fdt_getprop(fdt, subnode, "reg", &len);
+ while (len >= (regions->reserved_mem_addr_cells +
+ regions->reserved_mem_size_cells)) {
+
+ base = fdt32_to_cpu(reg[0]);
+ if (regions->reserved_mem_addr_cells == 2)
+ base = (base << 32) | fdt32_to_cpu(reg[1]);
+
+ reg += regions->reserved_mem_addr_cells;
+ len -= 4 * regions->reserved_mem_addr_cells;
+
+ size = fdt32_to_cpu(reg[0]);
+ if (regions->reserved_mem_size_cells == 2)
+ size = (size << 32) | fdt32_to_cpu(reg[1]);
+
+ reg += regions->reserved_mem_size_cells;
+ len -= 4 * regions->reserved_mem_size_cells;
+
+ if (base >= regions->pa_end)
+ continue;
+
+ if (regions_intersect(start, end, base,
+ min(base + size, (u64)U32_MAX)))
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool intersects_occupied_region(const void *fdt, u32 start,
+ u32 end, struct regions *regions)
+{
+ if (regions_intersect(start, end, regions->zimage_start,
+ regions->zimage_start + regions->zimage_size))
+ return true;
+
+ if (regions_intersect(start, end, regions->initrd_start,
+ regions->initrd_start + regions->initrd_size))
+ return true;
+
+ if (regions_intersect(start, end, regions->dtb_start,
+ regions->dtb_start + regions->dtb_size))
+ return true;
+
+ return intersects_reserved_region(fdt, start, end, regions);
+}
+
+static u32 count_suitable_regions(const void *fdt, struct regions *regions)
+{
+ u32 pa, ret = 0;
+
+ for (pa = regions->pa_start; pa < regions->pa_end; pa += SZ_2M) {
+ if (!intersects_occupied_region(fdt, pa,
+ pa + regions->image_size,
+ regions))
+ ret++;
+ }
+ return ret;
+}
+
+static u32 get_numbered_region(const void *fdt,
+ struct regions *regions,
+ int num)
+{
+ u32 pa;
+
+ for (pa = regions->pa_start; pa < regions->pa_end; pa += SZ_2M) {
+ if (!intersects_occupied_region(fdt, pa,
+ pa + regions->image_size,
+ regions))
+ if (num-- == 0)
+ return pa;
+ }
+ return regions->pa_start; /* should not happen */
+}
+
+static void get_cell_sizes(const void *fdt, int node, int *addr_cells,
+ int *size_cells)
+{
+ const int *prop;
+ int len;
+
+ /*
+ * Retrieve the #address-cells and #size-cells properties
+ * from the 'node', or use the default if not provided.
+ */
+ *addr_cells = *size_cells = 1;
+
+ prop = fdt_getprop(fdt, node, "#address-cells", &len);
+ if (len == 4)
+ *addr_cells = fdt32_to_cpu(*prop);
+ prop = fdt_getprop(fdt, node, "#size-cells", &len);
+ if (len == 4)
+ *size_cells = fdt32_to_cpu(*prop);
+}
+
+static u32 get_memory_end(const void *fdt)
+{
+ int mem_node, address_cells, size_cells, len;
+ const fdt32_t *reg;
+ u64 memory_end = 0;
+
+ /* Look for a node called "memory" at the lowest level of the tree */
+ mem_node = fdt_path_offset(fdt, "/memory");
+ if (mem_node <= 0)
+ return 0;
+
+ get_cell_sizes(fdt, 0, &address_cells, &size_cells);
+
+ /*
+ * Now find the 'reg' property of the /memory node, and iterate over
+ * the base/size pairs.
+ */
+ len = 0;
+ reg = fdt_getprop(fdt, mem_node, "reg", &len);
+ while (len >= 4 * (address_cells + size_cells)) {
+ u64 base, size;
+
+ base = fdt32_to_cpu(reg[0]);
+ if (address_cells == 2)
+ base = (base << 32) | fdt32_to_cpu(reg[1]);
+
+ reg += address_cells;
+ len -= 4 * address_cells;
+
+ size = fdt32_to_cpu(reg[0]);
+ if (size_cells == 2)
+ size = (size << 32) | fdt32_to_cpu(reg[1]);
+
+ reg += size_cells;
+ len -= 4 * size_cells;
+
+ memory_end = max(memory_end, base + size);
+ }
+ return min(memory_end, (u64)U32_MAX);
+}
+
+static char *__strstr(const char *s1, const char *s2, int l2)
+{
+ int l1;
+
+ l1 = strlen(s1);
+ while (l1 >= l2) {
+ l1--;
+ if (!memcmp(s1, s2, l2))
+ return (char *)s1;
+ s1++;
+ }
+ return NULL;
+}
+
+static const char *get_cmdline_param(const char *cmdline, const char *param,
+ int param_size)
+{
+ static const char default_cmdline[] = CONFIG_CMDLINE;
+ const char *p;
+
+ if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline != NULL) {
+ p = __strstr(cmdline, param, param_size);
+ if (p == cmdline ||
+ (p > cmdline && *(p - 1) == ' '))
+ return p;
+ }
+
+ if (IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+ IS_ENABLED(CONFIG_CMDLINE_EXTEND)) {
+ p = __strstr(default_cmdline, param, param_size);
+ if (p == default_cmdline ||
+ (p > default_cmdline && *(p - 1) == ' '))
+ return p;
+ }
+ return NULL;
+}
+
+u32 kaslr_early_init(u32 *kaslr_offset, u32 image_base, u32 image_size,
+ u32 seed, u32 zimage_start, const void *fdt,
+ u32 zimage_end)
+{
+ static const char __aligned(4) build_id[] = UTS_VERSION UTS_RELEASE;
+ struct regions regions;
+ const char *command_line;
+ const char *p;
+ int chosen, len;
+ u32 lowmem_top, num;
+
+ if (fdt_check_header(fdt))
+ return 0;
+
+ chosen = fdt_path_offset(fdt, "/chosen");
+ if (chosen < 0)
+ return 0;
+
+ command_line = fdt_getprop(fdt, chosen, "bootargs", &len);
+
+ /* check the command line for the presence of 'nokaslr' */
+ p = get_cmdline_param(command_line, "nokaslr", sizeof("nokaslr") - 1);
+ if (p != NULL)
+ return 0;
+
+ /* check the command line for the presence of 'vmalloc=' */
+ p = get_cmdline_param(command_line, "vmalloc=", sizeof("vmalloc=") - 1);
+ if (p != NULL)
+ lowmem_top = VMALLOC_END - __memparse(p + 8, NULL) -
+ VMALLOC_OFFSET;
+ else
+ lowmem_top = VMALLOC_DEFAULT_BASE;
+
+ regions.image_size = round_up(image_size, SZ_2M);
+ regions.pa_start = round_down(image_base, SZ_128M);
+ regions.pa_end = lowmem_top - PAGE_OFFSET + regions.pa_start -
+ regions.image_size;
+ regions.zimage_start = zimage_start;
+ regions.zimage_size = zimage_end - zimage_start;
+ regions.dtb_start = (u32)fdt;
+ regions.dtb_size = fdt_totalsize(fdt);
+
+ /*
+ * Stir up the seed a bit by taking the CRC of the DTB:
+ * hopefully there's a /chosen/kaslr-seed in there.
+ */
+ seed = __crc16(seed, fdt, regions.dtb_size);
+
+ /* stir a bit more using data that changes between builds */
+ seed = __crc16(seed, (u32 *)build_id, sizeof(build_id));
+
+ /* check for initrd on the command line */
+ regions.initrd_start = regions.initrd_size = 0;
+ p = get_cmdline_param(command_line, "initrd=", sizeof("initrd=") - 1);
+ if (p != NULL) {
+ regions.initrd_start = __memparse(p + 7, &p);
+ if (*p++ == ',')
+ regions.initrd_size = __memparse(p, NULL);
+ if (regions.initrd_size == 0)
+ regions.initrd_start = 0;
+ }
+
+ /* ... or in /chosen */
+ if (regions.initrd_size == 0) {
+ const fdt32_t *prop;
+ u64 start = 0, end = 0;
+
+ prop = fdt_getprop(fdt, chosen, "linux,initrd-start", &len);
+ if (prop) {
+ start = fdt32_to_cpu(prop[0]);
+ if (len == 8)
+ start = (start << 32) | fdt32_to_cpu(prop[1]);
+ }
+
+ prop = fdt_getprop(fdt, chosen, "linux,initrd-end", &len);
+ if (prop) {
+ end = fdt32_to_cpu(prop[0]);
+ if (len == 8)
+ end = (end << 32) | fdt32_to_cpu(prop[1]);
+ }
+ if (start != 0 && end != 0 && start < U32_MAX) {
+ regions.initrd_start = start;
+ regions.initrd_size = max_t(u64, end, U32_MAX) - start;
+ }
+ }
+
+ /* check the memory nodes for the size of the lowmem region */
+ regions.pa_end = min(regions.pa_end, get_memory_end(fdt));
+
+ /* check for a reserved-memory node and record its cell sizes */
+ regions.reserved_mem = fdt_path_offset(fdt, "/reserved-memory");
+ if (regions.reserved_mem >= 0)
+ get_cell_sizes(fdt, regions.reserved_mem,
+ ®ions.reserved_mem_addr_cells,
+ ®ions.reserved_mem_size_cells);
+
+ /*
+ * Iterate over the physical memory range covered by the lowmem region
+ * in 2 MB increments, and count each offset at which we don't overlap
+ * with any of the reserved regions for the zImage itself, the DTB,
+ * the initrd and any regions described as reserved in the device tree.
+ * This produces a count, which we will scale by multiplying by a 16-bit
+ * random value and shifting right by 16 places.
+ * Using this random value, we iterate over the physical memory range
+ * again until we counted enough iterations, and return the offset we
+ * ended up at.
+ */
+ num = ((u16)seed * count_suitable_regions(fdt, ®ions)) >> 16;
+
+ *kaslr_offset = get_numbered_region(fdt, ®ions, num) -
+ regions.pa_start;
+
+ return *kaslr_offset;
+}
--
2.11.0
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [kernel-hardening] [PATCH v2 26/29] ARM: decompressor: add KASLR support
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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 will extract some pseudo-randomness from the low
bits of the generic timer (if available), and use CRC-16 to combine
it with the build ID string and the device tree binary (which ideally
has a /chosen/kaslr-seed property, but may also have other properties
that differ between boots). This seed is used to select one of the
candidate offsets in the lowmem region that don't overlap the zImage
itself, the DTB, the initrd and /memreserve/s and/or /reserved-memory
nodes that should be left alone.
When booting via the UEFI stub, it is left up to the firmware to supply
a suitable seed and select an offset.
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/boot/compressed/Makefile | 8 +-
arch/arm/boot/compressed/head.S | 84 ++++-
arch/arm/boot/compressed/kaslr.c | 398 ++++++++++++++++++++
3 files changed, 484 insertions(+), 6 deletions(-)
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index d50430c40045..771b1ba1baa3 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -85,8 +85,14 @@ $(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/
$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
$(addprefix $(obj)/,$(libfdt_hdrs))
+ifneq ($(CONFIG_ARM_ATAG_DTB_COMPAT)$(CONFIG_RANDOMIZE_BASE),)
+OBJS += $(libfdt_objs)
ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
-OBJS += $(libfdt_objs) atags_to_fdt.o
+OBJS += atags_to_fdt.o
+endif
+ifeq ($(CONFIG_RANDOMIZE_BASE),y)
+OBJS += kaslr.o
+endif
endif
targets := vmlinux vmlinux.lds piggy_data piggy.o \
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 583cc6899d98..79b4033b0ed4 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -381,6 +381,42 @@ restart: adr r0, LC0
dtb_check_done:
#endif
+#ifdef CONFIG_RANDOMIZE_BASE
+ ldr r1, kaslr_offset @ check if the kaslr_offset is
+ cmp r1, #0 @ already set
+#ifdef CONFIG_EFI_STUB
+ ldreq r1, __efi_boot @ UEFI has its own KASLR init
+ cmpeq r1, #0 @ routine so skip over this one
+#endif
+ bne 1f
+
+ stmfd sp!, {r0-r3, ip, lr}
+ adr_l r2, _text @ start of zImage
+ stmfd sp!, {r2, r8, r10} @ pass stack arguments
+
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
+ /*
+ * Get some pseudo-entropy from the low bits of the generic
+ * timer if it is implemented.
+ */
+ mrc p15, 0, r1, c0, c1, 1 @ read ID_PFR1 register
+ tst r1, #0x10000 @ have generic timer?
+ beq 0f
+ mrrc p15, 1, r3, r1, c14 @ read CNTVCT
+#endif
+0: adr_l r0, kaslr_offset @ pass &kaslr_offset in r0
+ mov r1, r4 @ pass base address
+ mov r2, r9 @ pass decompressed image size
+ eor r3, r3, r3, ror #16 @ pass initial seed
+ bl kaslr_early_init
+ add sp, sp, #12
+ cmp r0, #0
+ addne r4, r4, r0 @ add offset to base address
+ ldmfd sp!, {r0-r3, ip, lr}
+ bne restart
+1:
+#endif
+
/*
* Check to see if we will overwrite ourselves.
* r4 = final kernel address (possibly with LSB set)
@@ -1356,25 +1392,63 @@ __hyp_reentry_vectors:
__enter_kernel:
mov r0, #0 @ must be 0
+#ifdef CONFIG_RANDOMIZE_BASE
+ ldr 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
+#ifdef CONFIG_RANDOMIZE_BASE
+ /*
+ * Minimal implementation of CRC-16 that does not use a
+ * lookup table and uses 32-bit wide loads, so it still
+ * performs reasonably well with the D-cache off. Equivalent
+ * to lib/crc16.c for input sizes that are 4 byte multiples.
+ */
+ENTRY(__crc16)
+ push {r4, lr}
+ ldr r3, =0xa001 @ CRC-16 polynomial
+0: subs r2, r2, #4
+ popmi {r4, pc}
+ ldr r4, [r1], #4
+#ifdef __ARMEB__
+ eor ip, r4, r4, ror #16 @ endian swap
+ bic ip, ip, #0x00ff0000
+ mov r4, r4, ror #8
+ eor r4, r4, ip, lsr #8
+#endif
+ eor r0, r0, r4
+ .rept 32
+ lsrs r0, r0, #1
+ eorcs r0, r0, r3
+ .endr
+ b 0b
+ENDPROC(__crc16)
+
+ .align 2
+kaslr_offset: .long 0
+#ifdef CONFIG_EFI_STUB
+__efi_boot: .long 0
+#endif
+#endif
+
reloc_code_end:
#ifdef CONFIG_EFI_STUB
.align 2
-_start: .long start - .
-
ENTRY(efi_stub_entry)
@ allocate space on stack for passing current zImage address
@ and for the EFI stub to return of new entry point of
@ zImage, as EFI stub may copy the kernel. Pointer address
@ is passed in r2. r0 and r1 are passed through from the
@ EFI firmware to efi_entry
- adr ip, _start
- ldr r3, [ip]
- add r3, r3, ip
+#ifdef CONFIG_RANDOMIZE_BASE
+ adr r3, __efi_boot
+ str r3, [r3] @ set __efi_boot != 0
+#endif
+ adr_l r3, start
stmfd sp!, {r3, lr}
mov r2, sp @ pass zImage address in r2
bl efi_entry
diff --git a/arch/arm/boot/compressed/kaslr.c b/arch/arm/boot/compressed/kaslr.c
new file mode 100644
index 000000000000..c68bdea764b6
--- /dev/null
+++ b/arch/arm/boot/compressed/kaslr.c
@@ -0,0 +1,398 @@
+/*
+ * 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.
+ *
+ */
+
+#include <libfdt.h>
+#include <linux/types.h>
+#include <generated/compile.h>
+#include <generated/utsrelease.h>
+#include <asm/pgtable.h>
+
+struct regions {
+ u32 pa_start;
+ u32 pa_end;
+ u32 image_size;
+ u32 zimage_start;
+ u32 zimage_size;
+ u32 dtb_start;
+ u32 dtb_size;
+ u32 initrd_start;
+ u32 initrd_size;
+ int reserved_mem;
+ int reserved_mem_addr_cells;
+ int reserved_mem_size_cells;
+};
+
+extern u32 __crc16(u32 crc, u32 const input[], int byte_count);
+
+static u32 __memparse(const char *val, const char **retptr)
+{
+ int base = 10;
+ u32 ret = 0;
+
+ if (*val == '0') {
+ val++;
+ if (*val == 'x' || *val == 'X') {
+ val++;
+ base = 16;
+ } else {
+ base = 8;
+ }
+ }
+
+ while (*val != ',' && *val != ' ' && *val != '\0') {
+ char c = *val++;
+
+ switch (c) {
+ case '0' ... '9':
+ ret = ret * base + (c - '0');
+ continue;
+ case 'a' ... 'f':
+ ret = ret * base + (c - 'a' + 10);
+ continue;
+ case 'A' ... 'F':
+ ret = ret * base + (c - 'A' + 10);
+ continue;
+ case 'g':
+ case 'G':
+ ret <<= 10;
+ case 'm':
+ case 'M':
+ ret <<= 10;
+ case 'k':
+ case 'K':
+ ret <<= 10;
+ break;
+ default:
+ if (retptr)
+ *retptr = NULL;
+ return 0;
+ }
+ }
+ if (retptr)
+ *retptr = val;
+ return ret;
+}
+
+static bool regions_intersect(u32 s1, u32 e1, u32 s2, u32 e2)
+{
+ return e1 >= s2 && e2 >= s1;
+}
+
+static bool intersects_reserved_region(const void *fdt, u32 start,
+ u32 end, struct regions *regions)
+{
+ int subnode, len, i;
+ u64 base, size;
+
+ /* check for overlap with /memreserve/ entries */
+ for (i = 0; i < fdt_num_mem_rsv(fdt); i++) {
+ if (fdt_get_mem_rsv(fdt, i, &base, &size) < 0)
+ continue;
+ if (regions_intersect(start, end, base, base + size))
+ return true;
+ }
+
+ if (regions->reserved_mem < 0)
+ return false;
+
+ /* check for overlap with static reservations in /reserved-memory */
+ for (subnode = fdt_first_subnode(fdt, regions->reserved_mem);
+ subnode >= 0;
+ subnode = fdt_next_subnode(fdt, subnode)) {
+ const fdt32_t *reg;
+
+ len = 0;
+ reg = fdt_getprop(fdt, subnode, "reg", &len);
+ while (len >= (regions->reserved_mem_addr_cells +
+ regions->reserved_mem_size_cells)) {
+
+ base = fdt32_to_cpu(reg[0]);
+ if (regions->reserved_mem_addr_cells == 2)
+ base = (base << 32) | fdt32_to_cpu(reg[1]);
+
+ reg += regions->reserved_mem_addr_cells;
+ len -= 4 * regions->reserved_mem_addr_cells;
+
+ size = fdt32_to_cpu(reg[0]);
+ if (regions->reserved_mem_size_cells == 2)
+ size = (size << 32) | fdt32_to_cpu(reg[1]);
+
+ reg += regions->reserved_mem_size_cells;
+ len -= 4 * regions->reserved_mem_size_cells;
+
+ if (base >= regions->pa_end)
+ continue;
+
+ if (regions_intersect(start, end, base,
+ min(base + size, (u64)U32_MAX)))
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool intersects_occupied_region(const void *fdt, u32 start,
+ u32 end, struct regions *regions)
+{
+ if (regions_intersect(start, end, regions->zimage_start,
+ regions->zimage_start + regions->zimage_size))
+ return true;
+
+ if (regions_intersect(start, end, regions->initrd_start,
+ regions->initrd_start + regions->initrd_size))
+ return true;
+
+ if (regions_intersect(start, end, regions->dtb_start,
+ regions->dtb_start + regions->dtb_size))
+ return true;
+
+ return intersects_reserved_region(fdt, start, end, regions);
+}
+
+static u32 count_suitable_regions(const void *fdt, struct regions *regions)
+{
+ u32 pa, ret = 0;
+
+ for (pa = regions->pa_start; pa < regions->pa_end; pa += SZ_2M) {
+ if (!intersects_occupied_region(fdt, pa,
+ pa + regions->image_size,
+ regions))
+ ret++;
+ }
+ return ret;
+}
+
+static u32 get_numbered_region(const void *fdt,
+ struct regions *regions,
+ int num)
+{
+ u32 pa;
+
+ for (pa = regions->pa_start; pa < regions->pa_end; pa += SZ_2M) {
+ if (!intersects_occupied_region(fdt, pa,
+ pa + regions->image_size,
+ regions))
+ if (num-- == 0)
+ return pa;
+ }
+ return regions->pa_start; /* should not happen */
+}
+
+static void get_cell_sizes(const void *fdt, int node, int *addr_cells,
+ int *size_cells)
+{
+ const int *prop;
+ int len;
+
+ /*
+ * Retrieve the #address-cells and #size-cells properties
+ * from the 'node', or use the default if not provided.
+ */
+ *addr_cells = *size_cells = 1;
+
+ prop = fdt_getprop(fdt, node, "#address-cells", &len);
+ if (len == 4)
+ *addr_cells = fdt32_to_cpu(*prop);
+ prop = fdt_getprop(fdt, node, "#size-cells", &len);
+ if (len == 4)
+ *size_cells = fdt32_to_cpu(*prop);
+}
+
+static u32 get_memory_end(const void *fdt)
+{
+ int mem_node, address_cells, size_cells, len;
+ const fdt32_t *reg;
+ u64 memory_end = 0;
+
+ /* Look for a node called "memory" at the lowest level of the tree */
+ mem_node = fdt_path_offset(fdt, "/memory");
+ if (mem_node <= 0)
+ return 0;
+
+ get_cell_sizes(fdt, 0, &address_cells, &size_cells);
+
+ /*
+ * Now find the 'reg' property of the /memory node, and iterate over
+ * the base/size pairs.
+ */
+ len = 0;
+ reg = fdt_getprop(fdt, mem_node, "reg", &len);
+ while (len >= 4 * (address_cells + size_cells)) {
+ u64 base, size;
+
+ base = fdt32_to_cpu(reg[0]);
+ if (address_cells == 2)
+ base = (base << 32) | fdt32_to_cpu(reg[1]);
+
+ reg += address_cells;
+ len -= 4 * address_cells;
+
+ size = fdt32_to_cpu(reg[0]);
+ if (size_cells == 2)
+ size = (size << 32) | fdt32_to_cpu(reg[1]);
+
+ reg += size_cells;
+ len -= 4 * size_cells;
+
+ memory_end = max(memory_end, base + size);
+ }
+ return min(memory_end, (u64)U32_MAX);
+}
+
+static char *__strstr(const char *s1, const char *s2, int l2)
+{
+ int l1;
+
+ l1 = strlen(s1);
+ while (l1 >= l2) {
+ l1--;
+ if (!memcmp(s1, s2, l2))
+ return (char *)s1;
+ s1++;
+ }
+ return NULL;
+}
+
+static const char *get_cmdline_param(const char *cmdline, const char *param,
+ int param_size)
+{
+ static const char default_cmdline[] = CONFIG_CMDLINE;
+ const char *p;
+
+ if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline != NULL) {
+ p = __strstr(cmdline, param, param_size);
+ if (p == cmdline ||
+ (p > cmdline && *(p - 1) == ' '))
+ return p;
+ }
+
+ if (IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+ IS_ENABLED(CONFIG_CMDLINE_EXTEND)) {
+ p = __strstr(default_cmdline, param, param_size);
+ if (p == default_cmdline ||
+ (p > default_cmdline && *(p - 1) == ' '))
+ return p;
+ }
+ return NULL;
+}
+
+u32 kaslr_early_init(u32 *kaslr_offset, u32 image_base, u32 image_size,
+ u32 seed, u32 zimage_start, const void *fdt,
+ u32 zimage_end)
+{
+ static const char __aligned(4) build_id[] = UTS_VERSION UTS_RELEASE;
+ struct regions regions;
+ const char *command_line;
+ const char *p;
+ int chosen, len;
+ u32 lowmem_top, num;
+
+ if (fdt_check_header(fdt))
+ return 0;
+
+ chosen = fdt_path_offset(fdt, "/chosen");
+ if (chosen < 0)
+ return 0;
+
+ command_line = fdt_getprop(fdt, chosen, "bootargs", &len);
+
+ /* check the command line for the presence of 'nokaslr' */
+ p = get_cmdline_param(command_line, "nokaslr", sizeof("nokaslr") - 1);
+ if (p != NULL)
+ return 0;
+
+ /* check the command line for the presence of 'vmalloc=' */
+ p = get_cmdline_param(command_line, "vmalloc=", sizeof("vmalloc=") - 1);
+ if (p != NULL)
+ lowmem_top = VMALLOC_END - __memparse(p + 8, NULL) -
+ VMALLOC_OFFSET;
+ else
+ lowmem_top = VMALLOC_DEFAULT_BASE;
+
+ regions.image_size = round_up(image_size, SZ_2M);
+ regions.pa_start = round_down(image_base, SZ_128M);
+ regions.pa_end = lowmem_top - PAGE_OFFSET + regions.pa_start -
+ regions.image_size;
+ regions.zimage_start = zimage_start;
+ regions.zimage_size = zimage_end - zimage_start;
+ regions.dtb_start = (u32)fdt;
+ regions.dtb_size = fdt_totalsize(fdt);
+
+ /*
+ * Stir up the seed a bit by taking the CRC of the DTB:
+ * hopefully there's a /chosen/kaslr-seed in there.
+ */
+ seed = __crc16(seed, fdt, regions.dtb_size);
+
+ /* stir a bit more using data that changes between builds */
+ seed = __crc16(seed, (u32 *)build_id, sizeof(build_id));
+
+ /* check for initrd on the command line */
+ regions.initrd_start = regions.initrd_size = 0;
+ p = get_cmdline_param(command_line, "initrd=", sizeof("initrd=") - 1);
+ if (p != NULL) {
+ regions.initrd_start = __memparse(p + 7, &p);
+ if (*p++ == ',')
+ regions.initrd_size = __memparse(p, NULL);
+ if (regions.initrd_size == 0)
+ regions.initrd_start = 0;
+ }
+
+ /* ... or in /chosen */
+ if (regions.initrd_size == 0) {
+ const fdt32_t *prop;
+ u64 start = 0, end = 0;
+
+ prop = fdt_getprop(fdt, chosen, "linux,initrd-start", &len);
+ if (prop) {
+ start = fdt32_to_cpu(prop[0]);
+ if (len == 8)
+ start = (start << 32) | fdt32_to_cpu(prop[1]);
+ }
+
+ prop = fdt_getprop(fdt, chosen, "linux,initrd-end", &len);
+ if (prop) {
+ end = fdt32_to_cpu(prop[0]);
+ if (len == 8)
+ end = (end << 32) | fdt32_to_cpu(prop[1]);
+ }
+ if (start != 0 && end != 0 && start < U32_MAX) {
+ regions.initrd_start = start;
+ regions.initrd_size = max_t(u64, end, U32_MAX) - start;
+ }
+ }
+
+ /* check the memory nodes for the size of the lowmem region */
+ regions.pa_end = min(regions.pa_end, get_memory_end(fdt));
+
+ /* check for a reserved-memory node and record its cell sizes */
+ regions.reserved_mem = fdt_path_offset(fdt, "/reserved-memory");
+ if (regions.reserved_mem >= 0)
+ get_cell_sizes(fdt, regions.reserved_mem,
+ ®ions.reserved_mem_addr_cells,
+ ®ions.reserved_mem_size_cells);
+
+ /*
+ * Iterate over the physical memory range covered by the lowmem region
+ * in 2 MB increments, and count each offset at which we don't overlap
+ * with any of the reserved regions for the zImage itself, the DTB,
+ * the initrd and any regions described as reserved in the device tree.
+ * This produces a count, which we will scale by multiplying by a 16-bit
+ * random value and shifting right by 16 places.
+ * Using this random value, we iterate over the physical memory range
+ * again until we counted enough iterations, and return the offset we
+ * ended up at.
+ */
+ num = ((u16)seed * count_suitable_regions(fdt, ®ions)) >> 16;
+
+ *kaslr_offset = get_numbered_region(fdt, ®ions, num) -
+ regions.pa_start;
+
+ return *kaslr_offset;
+}
--
2.11.0
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [PATCH v2 27/29] efi/libstub: add 'max' parameter to efi_random_alloc()
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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 | 11 +++++++----
3 files changed, 10 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..810e60e76211 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,8 @@ 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_t(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 +75,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 +104,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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 27/29] efi/libstub: add 'max' parameter to efi_random_alloc()
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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 | 11 +++++++----
3 files changed, 10 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..810e60e76211 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,8 @@ 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_t(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 +75,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 +104,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] 166+ messages in thread
* [PATCH v2 28/29] efi/libstub: check for vmalloc= command line argument
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 28/29] efi/libstub: check for vmalloc= command line argument
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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] 166+ messages in thread
* [PATCH v2 29/29] efi/libstub: arm: implement KASLR
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-03 12:07 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel
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>
---
arch/arm/boot/compressed/head.S | 12 ++++-
drivers/firmware/efi/libstub/arm32-stub.c | 47 +++++++++++++++++++-
2 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 79b4033b0ed4..68d803dfdf3f 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -203,6 +203,15 @@ not_angel:
*/
mov r4, pc
and r4, r4, #0xf8000000
+#if defined(CONFIG_RANDOMIZE_BASE) && defined(CONFIG_EFI_STUB)
+ /*
+ * The KASLR randomization may have already been performed by
+ * the UEFI stub, in which case kaslr_offset will already have
+ * a value.
+ */
+ ldr r0, kaslr_offset
+ add r4, r4, r0
+#endif
/* Determine final kernel image address. */
add r4, r4, #TEXT_OFFSET
#else
@@ -1428,7 +1437,8 @@ ENTRY(__crc16)
ENDPROC(__crc16)
.align 2
-kaslr_offset: .long 0
+ENTRY(kaslr_offset)
+ .long 0
#ifdef CONFIG_EFI_STUB
__efi_boot: .long 0
#endif
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
index becbda445913..73d3694d2fbb 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -8,9 +8,12 @@
*/
#include <linux/efi.h>
#include <asm/efi.h>
+#include <asm/pgtable.h>
#include "efistub.h"
+extern u32 kaslr_offset;
+
efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
{
int block;
@@ -200,6 +203,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 +236,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] 166+ messages in thread
* [kernel-hardening] [PATCH v2 29/29] efi/libstub: arm: implement KASLR
@ 2017-09-03 12:07 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-03 12:07 UTC (permalink / raw)
To: linux-arm-kernel, kernel-hardening
Cc: 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>
---
arch/arm/boot/compressed/head.S | 12 ++++-
drivers/firmware/efi/libstub/arm32-stub.c | 47 +++++++++++++++++++-
2 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 79b4033b0ed4..68d803dfdf3f 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -203,6 +203,15 @@ not_angel:
*/
mov r4, pc
and r4, r4, #0xf8000000
+#if defined(CONFIG_RANDOMIZE_BASE) && defined(CONFIG_EFI_STUB)
+ /*
+ * The KASLR randomization may have already been performed by
+ * the UEFI stub, in which case kaslr_offset will already have
+ * a value.
+ */
+ ldr r0, kaslr_offset
+ add r4, r4, r0
+#endif
/* Determine final kernel image address. */
add r4, r4, #TEXT_OFFSET
#else
@@ -1428,7 +1437,8 @@ ENTRY(__crc16)
ENDPROC(__crc16)
.align 2
-kaslr_offset: .long 0
+ENTRY(kaslr_offset)
+ .long 0
#ifdef CONFIG_EFI_STUB
__efi_boot: .long 0
#endif
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
index becbda445913..73d3694d2fbb 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -8,9 +8,12 @@
*/
#include <linux/efi.h>
#include <asm/efi.h>
+#include <asm/pgtable.h>
#include "efistub.h"
+extern u32 kaslr_offset;
+
efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
{
int block;
@@ -200,6 +203,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 +236,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] 166+ messages in thread
* [PATCH v2 02/29] asm-generic: add .data.rel.ro sections to __ro_after_init
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 15:59 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 15:59 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel 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.
>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 02/29] asm-generic: add .data.rel.ro sections to __ro_after_init
@ 2017-09-04 15:59 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 15:59 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel 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.
>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 03/29] ARM: assembler: introduce adr_l, ldr_l and str_l macros
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:05 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:05 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, 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, 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>
REviewed-by: Nicolas Pitre <nico@linaro.org>
> ---
> arch/arm/include/asm/assembler.h | 76 ++++++++++++++++++++
> 1 file changed, 76 insertions(+)
>
> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> index ad301f107dd2..341e4ed1ef84 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -518,4 +518,80 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
> #endif
> .endm
>
> + .macro __adldst_l, op, reg, sym, tmp
> + .if __LINUX_ARM_ARCH__ < 7
> + ldr \tmp, 111f
> + .subsection 1
> + .align 2
> +111: .long \sym - (222f + 8)
> + .previous
> + .else
> + /*
> + * In Thumb-2 builds, the PC bias depends on whether we are currently
> + * emitting into a .arm or a .thumb section. So emit a nop and take
> + * its size, so we can infer the execution mode and PC bias from it.
> + */
> + ARM( .set .Lnopsize, 4 )
> + THUMB( .pushsection ".discard.nop", "x", %note )
> + THUMB( 111: nop )
> + THUMB( .set .Lnopsize, . - 111b )
> + THUMB( .popsection )
> +
> + movw \tmp, #:lower16:\sym - (222f + 2 * .Lnopsize)
> + movt \tmp, #:upper16:\sym - (222f + 2 * .Lnopsize)
> + .endif
> +222:
> + .ifc \op, add
> + add \reg, \tmp, pc
> + .elseif .Lnopsize == 2 @ Thumb-2 mode
> + add \tmp, \tmp, pc
> + \op \reg, [\tmp]
> + .else
> + \op \reg, [pc, \tmp]
> + .endif
> + .endm
> +
> + /*
> + * mov_l - move a constant value or [relocated] address into a register
> + */
> + .macro mov_l, dst:req, imm:req
> + .if __LINUX_ARM_ARCH__ < 7
> + ldr \dst, =\imm
> + .else
> + movw \dst, #:lower16:\imm
> + movt \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
> + __adldst_l add, \dst, \sym, \dst
> + .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
> + __adldst_l ldr, \dst, \sym, \dst
> + .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
> + __adldst_l str, \src, \sym, \tmp
> + .endm
> +
> #endif /* __ASM_ASSEMBLER_H__ */
> --
> 2.11.0
>
>
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 03/29] ARM: assembler: introduce adr_l, ldr_l and str_l macros
@ 2017-09-04 16:05 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:05 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, 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, 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>
REviewed-by: Nicolas Pitre <nico@linaro.org>
> ---
> arch/arm/include/asm/assembler.h | 76 ++++++++++++++++++++
> 1 file changed, 76 insertions(+)
>
> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> index ad301f107dd2..341e4ed1ef84 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -518,4 +518,80 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
> #endif
> .endm
>
> + .macro __adldst_l, op, reg, sym, tmp
> + .if __LINUX_ARM_ARCH__ < 7
> + ldr \tmp, 111f
> + .subsection 1
> + .align 2
> +111: .long \sym - (222f + 8)
> + .previous
> + .else
> + /*
> + * In Thumb-2 builds, the PC bias depends on whether we are currently
> + * emitting into a .arm or a .thumb section. So emit a nop and take
> + * its size, so we can infer the execution mode and PC bias from it.
> + */
> + ARM( .set .Lnopsize, 4 )
> + THUMB( .pushsection ".discard.nop", "x", %note )
> + THUMB( 111: nop )
> + THUMB( .set .Lnopsize, . - 111b )
> + THUMB( .popsection )
> +
> + movw \tmp, #:lower16:\sym - (222f + 2 * .Lnopsize)
> + movt \tmp, #:upper16:\sym - (222f + 2 * .Lnopsize)
> + .endif
> +222:
> + .ifc \op, add
> + add \reg, \tmp, pc
> + .elseif .Lnopsize == 2 @ Thumb-2 mode
> + add \tmp, \tmp, pc
> + \op \reg, [\tmp]
> + .else
> + \op \reg, [pc, \tmp]
> + .endif
> + .endm
> +
> + /*
> + * mov_l - move a constant value or [relocated] address into a register
> + */
> + .macro mov_l, dst:req, imm:req
> + .if __LINUX_ARM_ARCH__ < 7
> + ldr \dst, =\imm
> + .else
> + movw \dst, #:lower16:\imm
> + movt \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
> + __adldst_l add, \dst, \sym, \dst
> + .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
> + __adldst_l ldr, \dst, \sym, \dst
> + .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
> + __adldst_l str, \src, \sym, \tmp
> + .endm
> +
> #endif /* __ASM_ASSEMBLER_H__ */
> --
> 2.11.0
>
>
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 04/29] ARM: head-common.S: use PC-relative insn sequence for __proc_info
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:06 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:06 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 04/29] ARM: head-common.S: use PC-relative insn sequence for __proc_info
@ 2017-09-04 16:06 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:06 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 05/29] ARM: head-common.S: use PC-relative insn sequence for idmap creation
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:08 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:08 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 05/29] ARM: head-common.S: use PC-relative insn sequence for idmap creation
@ 2017-09-04 16:08 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:08 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 06/29] ARM: head.S: use PC-relative insn sequence for secondary_data
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:09 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:09 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 06/29] ARM: head.S: use PC-relative insn sequence for secondary_data
@ 2017-09-04 16:09 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:09 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 07/29] ARM: kernel: use relative references for UP/SMP alternatives
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:15 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:15 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 341e4ed1ef84..a0906c1fc65d 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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 07/29] ARM: kernel: use relative references for UP/SMP alternatives
@ 2017-09-04 16:15 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:15 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 341e4ed1ef84..a0906c1fc65d 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 [flat|nested] 166+ messages in thread
* [PATCH v2 08/29] ARM: head: use PC-relative insn sequence for __smp_alt
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:19 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:19 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> Replace the open coded PC relative offset calculations with a pair
> of adr_l invocations. This ensures these quantities are invariant
> under runtime relocation.
You probably should add that this patch must be applied on top of "ARM:
kernel: use relative references for UP/SMP alternatives" because of the
expected r3 value prior to that patch.
Acked-by: Nicolas Pitre <nico@linaro.org>
> 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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 08/29] ARM: head: use PC-relative insn sequence for __smp_alt
@ 2017-09-04 16:19 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:19 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> Replace the open coded PC relative offset calculations with a pair
> of adr_l invocations. This ensures these quantities are invariant
> under runtime relocation.
You probably should add that this patch must be applied on top of "ARM:
kernel: use relative references for UP/SMP alternatives" because of the
expected r3 value prior to that patch.
Acked-by: Nicolas Pitre <nico@linaro.org>
> 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 [flat|nested] 166+ messages in thread
* [PATCH v2 08/29] ARM: head: use PC-relative insn sequence for __smp_alt
2017-09-04 16:19 ` [kernel-hardening] " Nicolas Pitre
@ 2017-09-04 16:20 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 16:20 UTC (permalink / raw)
To: linux-arm-kernel
On 4 September 2017 at 17:19, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> Replace the open coded PC relative offset calculations with a pair
>> of adr_l invocations. This ensures these quantities are invariant
>> under runtime relocation.
>
> You probably should add that this patch must be applied on top of "ARM:
> kernel: use relative references for UP/SMP alternatives" because of the
> expected r3 value prior to that patch.
>
> Acked-by: Nicolas Pitre <nico@linaro.org>
>
Yes, that is why I needed to reorder them. I will add a mention to the
commit log.
Thanks,
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 08/29] ARM: head: use PC-relative insn sequence for __smp_alt
@ 2017-09-04 16:20 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 16:20 UTC (permalink / raw)
To: Nicolas Pitre
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 4 September 2017 at 17:19, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> Replace the open coded PC relative offset calculations with a pair
>> of adr_l invocations. This ensures these quantities are invariant
>> under runtime relocation.
>
> You probably should add that this patch must be applied on top of "ARM:
> kernel: use relative references for UP/SMP alternatives" because of the
> expected r3 value prior to that patch.
>
> Acked-by: Nicolas Pitre <nico@linaro.org>
>
Yes, that is why I needed to reorder them. I will add a mention to the
commit log.
Thanks,
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 09/29] ARM: sleep.S: use PC-relative insn sequence for sleep_save_sp/mpidr_hash
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:20 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:20 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> Replace the open coded PC relative offset calculations with adr_l and
> ldr_l invocations. Note that ALT_SMP() expects a single instruction
> so move the macro invocation after it.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
> ---
> arch/arm/kernel/sleep.S | 19 +++++--------------
> 1 file changed, 5 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> index 0f6c1000582c..f4920b5d0fc4 100644
> --- a/arch/arm/kernel/sleep.S
> +++ b/arch/arm/kernel/sleep.S
> @@ -71,8 +71,9 @@ ENTRY(__cpu_suspend)
> ldr 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(W(nop)) @ don't use adr_l inside ALT_SMP()
> ALT_UP_B(1f)
> + adr_l r0, mpidr_hash
> /* 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
> compute_mpidr_hash r0, r6, r7, r8, r2, r1
> @@ -137,9 +138,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 +147,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 +161,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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 09/29] ARM: sleep.S: use PC-relative insn sequence for sleep_save_sp/mpidr_hash
@ 2017-09-04 16:20 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:20 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> Replace the open coded PC relative offset calculations with adr_l and
> ldr_l invocations. Note that ALT_SMP() expects a single instruction
> so move the macro invocation after it.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
> ---
> arch/arm/kernel/sleep.S | 19 +++++--------------
> 1 file changed, 5 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> index 0f6c1000582c..f4920b5d0fc4 100644
> --- a/arch/arm/kernel/sleep.S
> +++ b/arch/arm/kernel/sleep.S
> @@ -71,8 +71,9 @@ ENTRY(__cpu_suspend)
> ldr 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(W(nop)) @ don't use adr_l inside ALT_SMP()
> ALT_UP_B(1f)
> + adr_l r0, mpidr_hash
> /* 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
> compute_mpidr_hash r0, r6, r7, r8, r2, r1
> @@ -137,9 +138,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 +147,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 +161,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 [flat|nested] 166+ messages in thread
* [PATCH v2 10/29] ARM: head.S: use PC-relative insn sequences for __fixup_pv_table
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:47 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:47 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 10/29] ARM: head.S: use PC-relative insn sequences for __fixup_pv_table
@ 2017-09-04 16:47 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:47 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 11/29] ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:50 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:50 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Of course there won't be anything to relocate in a XIP kernel. But
consistency is good and this looks nicer.
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 11/29] ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET
@ 2017-09-04 16:50 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:50 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Of course there won't be anything to relocate in a XIP kernel. But
consistency is good and this looks nicer.
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 12/29] ARM: kvm: replace open coded VA->PA calculations with adr_l call
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:57 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:57 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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..3c2d1738d3f4 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 additional 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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 12/29] ARM: kvm: replace open coded VA->PA calculations with adr_l call
@ 2017-09-04 16:57 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:57 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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..3c2d1738d3f4 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 additional 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 [flat|nested] 166+ messages in thread
* [PATCH v2 13/29] arm-soc: exynos: replace open coded VA->PA conversions
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 16:59 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:59 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 13/29] arm-soc: exynos: replace open coded VA->PA conversions
@ 2017-09-04 16:59 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 16:59 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 14/29] arm-soc: mvebu: replace open coded VA->PA conversion
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 17:00 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 17:00 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 14/29] arm-soc: mvebu: replace open coded VA->PA conversion
@ 2017-09-04 17:00 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 17:00 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 15/29] arm-soc: various: replace open coded VA->PA calculation of pen_release
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 17:01 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 17:01 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 15/29] arm-soc: various: replace open coded VA->PA calculation of pen_release
@ 2017-09-04 17:01 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 17:01 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 02/29] asm-generic: add .data.rel.ro sections to __ro_after_init
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 17:09 ` Kees Cook
-1 siblings, 0 replies; 166+ messages in thread
From: Kees Cook @ 2017-09-04 17:09 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Sep 3, 2017 at 5:07 AM, 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.
>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Kees Cook <keescook@chromium.org>
-Kees
> ---
> 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
>
--
Kees Cook
Pixel Security
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 02/29] asm-generic: add .data.rel.ro sections to __ro_after_init
@ 2017-09-04 17:09 ` Kees Cook
0 siblings, 0 replies; 166+ messages in thread
From: Kees Cook @ 2017-09-04 17:09 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, Sep 3, 2017 at 5:07 AM, 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.
>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Kees Cook <keescook@chromium.org>
-Kees
> ---
> 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
>
--
Kees Cook
Pixel Security
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 16/29] ARM: kernel: switch to relative exception tables
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 17:17 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 17:17 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Could it be better to have a macro that encapsulates exception entries
e.g.:
.macro ex_entry insn fixup
.long \insn - ., \fixup - .
.endif
so that if ever this changes again or for whatever reason someone needs
absolute entries then this won't have to be done everywhere. The section
switch could be included in such a macro too. And it is so easy to
forget to do the "- ." when adding new entries.
> ---
> arch/arm/include/asm/Kbuild | 1 -
> arch/arm/include/asm/assembler.h | 6 +++---
> arch/arm/include/asm/extable.h | 19 +++++++++++++++++
> 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, 64 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 a0906c1fc65d..ae43859a9000 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..c85d1f4404b7
> --- /dev/null
> +++ b/arch/arm/include/asm/extable.h
> @@ -0,0 +1,19 @@
> +#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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 16/29] ARM: kernel: switch to relative exception tables
@ 2017-09-04 17:17 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 17:17 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Could it be better to have a macro that encapsulates exception entries
e.g.:
.macro ex_entry insn fixup
.long \insn - ., \fixup - .
.endif
so that if ever this changes again or for whatever reason someone needs
absolute entries then this won't have to be done everywhere. The section
switch could be included in such a macro too. And it is so easy to
forget to do the "- ." when adding new entries.
> ---
> arch/arm/include/asm/Kbuild | 1 -
> arch/arm/include/asm/assembler.h | 6 +++---
> arch/arm/include/asm/extable.h | 19 +++++++++++++++++
> 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, 64 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 a0906c1fc65d..ae43859a9000 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..c85d1f4404b7
> --- /dev/null
> +++ b/arch/arm/include/asm/extable.h
> @@ -0,0 +1,19 @@
> +#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 [flat|nested] 166+ messages in thread
* [PATCH v2 16/29] ARM: kernel: switch to relative exception tables
2017-09-04 17:17 ` [kernel-hardening] " Nicolas Pitre
@ 2017-09-04 17:30 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 17:30 UTC (permalink / raw)
To: linux-arm-kernel
On 4 September 2017 at 18:17, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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>
>
> Could it be better to have a macro that encapsulates exception entries
> e.g.:
>
> .macro ex_entry insn fixup
> .long \insn - ., \fixup - .
> .endif
>
> so that if ever this changes again or for whatever reason someone needs
> absolute entries then this won't have to be done everywhere. The section
> switch could be included in such a macro too. And it is so easy to
> forget to do the "- ." when adding new entries.
>
Good point. I will change that.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 16/29] ARM: kernel: switch to relative exception tables
@ 2017-09-04 17:30 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 17:30 UTC (permalink / raw)
To: Nicolas Pitre
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 4 September 2017 at 18:17, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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>
>
> Could it be better to have a macro that encapsulates exception entries
> e.g.:
>
> .macro ex_entry insn fixup
> .long \insn - ., \fixup - .
> .endif
>
> so that if ever this changes again or for whatever reason someone needs
> absolute entries then this won't have to be done everywhere. The section
> switch could be included in such a macro too. And it is so easy to
> forget to do the "- ." when adding new entries.
>
Good point. I will change that.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 17/29] ARM: kernel: use relative phys-to-virt patch tables
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 18:03 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:03 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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" \
[...]
> --- a/arch/arm/kernel/head.S
> +++ b/arch/arm/kernel/head.S
> @@ -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]
Please use "ldrh ip, [r7, #(-4 + 2)]" so the -4 offset is clearly
spelled out. The #-2 gave me a pause of confusion.
> 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]
Ditto here.
> bne 2f
> - ldrh ip, [r7]
> + ldrh ip, [r7, #-4]
And to be clear, here I'd use "#(-4 + 0)" to be explicit.
> 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]
And so here.
With that:
Reviewed-by: Nicolas Pitre <nico@linaro.org>
> 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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 17/29] ARM: kernel: use relative phys-to-virt patch tables
@ 2017-09-04 18:03 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:03 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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" \
[...]
> --- a/arch/arm/kernel/head.S
> +++ b/arch/arm/kernel/head.S
> @@ -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]
Please use "ldrh ip, [r7, #(-4 + 2)]" so the -4 offset is clearly
spelled out. The #-2 gave me a pause of confusion.
> 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]
Ditto here.
> bne 2f
> - ldrh ip, [r7]
> + ldrh ip, [r7, #-4]
And to be clear, here I'd use "#(-4 + 0)" to be explicit.
> 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]
And so here.
With that:
Reviewed-by: Nicolas Pitre <nico@linaro.org>
> 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 [flat|nested] 166+ messages in thread
* [PATCH v2 19/29] ARM: kernel: make vmlinux buildable as a PIE executable
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 18:11 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:11 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> Update the build flags and linker script to allow vmlinux to be built
> 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 | 2 +-
> arch/arm/kernel/vmlinux.lds.S | 9 +++++++++
> include/linux/hidden.h | 20 ++++++++++++++++++++
> scripts/module-common.lds | 1 +
> 6 files changed, 40 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
> +
You should probably make it depend on !XIP_KERNEL.
Other than that
Acked-by: Nicolas Pitre <nico@linaro.org>
>
> menu "CPU Power Management"
> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
> index 47d3a1ab08d2..8544c8148b9f 100644
> --- a/arch/arm/Makefile
> +++ b/arch/arm/Makefile
> @@ -52,6 +52,11 @@ AS += -EL
> LD += -EL
> endif
>
> +ifeq ($(CONFIG_RELOCATABLE),y)
> +KBUILD_CFLAGS += -fpic -include $(srctree)/include/linux/hidden.h
> +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 ae43859a9000..0586e1c77a80 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -555,7 +555,7 @@ 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
> - .if __LINUX_ARM_ARCH__ < 7
> + .if CONFIG_RELOCATABLE == 1 || __LINUX_ARM_ARCH__ < 7
> ldr \dst, =\imm
> .else
> movw \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..781fb6f0c742
> --- /dev/null
> +++ b/include/linux/hidden.h
> @@ -0,0 +1,20 @@
> +/*
> + * 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)
> diff --git a/scripts/module-common.lds b/scripts/module-common.lds
> index d61b9e8678e8..55bb41f32c8a 100644
> --- a/scripts/module-common.lds
> +++ b/scripts/module-common.lds
> @@ -7,6 +7,7 @@ SECTIONS {
> /DISCARD/ : {
> *(.discard)
> *(.discard.*)
> + *(*.discard.*)
> }
>
> __ksymtab 0 : { *(SORT(___ksymtab+*)) }
> --
> 2.11.0
>
>
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 19/29] ARM: kernel: make vmlinux buildable as a PIE executable
@ 2017-09-04 18:11 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:11 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> Update the build flags and linker script to allow vmlinux to be built
> 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 | 2 +-
> arch/arm/kernel/vmlinux.lds.S | 9 +++++++++
> include/linux/hidden.h | 20 ++++++++++++++++++++
> scripts/module-common.lds | 1 +
> 6 files changed, 40 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
> +
You should probably make it depend on !XIP_KERNEL.
Other than that
Acked-by: Nicolas Pitre <nico@linaro.org>
>
> menu "CPU Power Management"
> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
> index 47d3a1ab08d2..8544c8148b9f 100644
> --- a/arch/arm/Makefile
> +++ b/arch/arm/Makefile
> @@ -52,6 +52,11 @@ AS += -EL
> LD += -EL
> endif
>
> +ifeq ($(CONFIG_RELOCATABLE),y)
> +KBUILD_CFLAGS += -fpic -include $(srctree)/include/linux/hidden.h
> +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 ae43859a9000..0586e1c77a80 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -555,7 +555,7 @@ 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
> - .if __LINUX_ARM_ARCH__ < 7
> + .if CONFIG_RELOCATABLE == 1 || __LINUX_ARM_ARCH__ < 7
> ldr \dst, =\imm
> .else
> movw \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..781fb6f0c742
> --- /dev/null
> +++ b/include/linux/hidden.h
> @@ -0,0 +1,20 @@
> +/*
> + * 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)
> diff --git a/scripts/module-common.lds b/scripts/module-common.lds
> index d61b9e8678e8..55bb41f32c8a 100644
> --- a/scripts/module-common.lds
> +++ b/scripts/module-common.lds
> @@ -7,6 +7,7 @@ SECTIONS {
> /DISCARD/ : {
> *(.discard)
> *(.discard.*)
> + *(*.discard.*)
> }
>
> __ksymtab 0 : { *(SORT(___ksymtab+*)) }
> --
> 2.11.0
>
>
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 20/29] ARM: kernel: use PC-relative symbol references in MMU switch code
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 18:15 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:15 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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
The code that follows is testing for a non-zero r7 value to store r0 so
you could make that code conditional rather than loading 0 here.
> +
> 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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 20/29] ARM: kernel: use PC-relative symbol references in MMU switch code
@ 2017-09-04 18:15 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:15 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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
The code that follows is testing for a non-zero r7 value to store r0 so
you could make that code conditional rather than loading 0 here.
> +
> 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 [flat|nested] 166+ messages in thread
* [PATCH v2 21/29] ARM: kernel: use PC relative symbol references in suspend/resume code
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 18:24 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:24 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 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>
What's the point of that last hunk? I understand you load the address
after the mMU is on. But you should be coming back from a sleep and
caches ought to be clean at that point. Not that it is a bad thing to do
but I don't understand your reason for it.
> ---
> arch/arm/kernel/sleep.S | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> index f4920b5d0fc4..5b02744f2f12 100644
> --- a/arch/arm/kernel/sleep.S
> +++ b/arch/arm/kernel/sleep.S
> @@ -60,15 +60,14 @@
> 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(W(nop)) @ don't use adr_l inside ALT_SMP()
> @@ -101,13 +100,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] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 21/29] ARM: kernel: use PC relative symbol references in suspend/resume code
@ 2017-09-04 18:24 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:24 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 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>
What's the point of that last hunk? I understand you load the address
after the mMU is on. But you should be coming back from a sleep and
caches ought to be clean at that point. Not that it is a bad thing to do
but I don't understand your reason for it.
> ---
> arch/arm/kernel/sleep.S | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> index f4920b5d0fc4..5b02744f2f12 100644
> --- a/arch/arm/kernel/sleep.S
> +++ b/arch/arm/kernel/sleep.S
> @@ -60,15 +60,14 @@
> 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(W(nop)) @ don't use adr_l inside ALT_SMP()
> @@ -101,13 +100,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] 166+ messages in thread
* [PATCH v2 22/29] ARM: mm: export default vmalloc base address
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 18:25 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:25 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 22/29] ARM: mm: export default vmalloc base address
@ 2017-09-04 18:25 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:25 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 23/29] ARM: kernel: refer to swapper_pg_dir via its symbol
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 18:30 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:30 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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.
Could it cause a section access mismatch if defined in the __HEAD
section?
Otherwise
Acked-by: Nicolas Pitre <nico@linaro.org>
>
> 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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 23/29] ARM: kernel: refer to swapper_pg_dir via its symbol
@ 2017-09-04 18:30 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:30 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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.
Could it cause a section access mismatch if defined in the __HEAD
section?
Otherwise
Acked-by: Nicolas Pitre <nico@linaro.org>
>
> 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 [flat|nested] 166+ messages in thread
* [PATCH v2 24/29] ARM: kernel: implement randomization of the kernel load address
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 18:44 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:44 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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..fe4a2cd1f15c 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
This should work even if ZBOOT_ROM is selected. The ZBOOT_ROM option
allows for the decompressor executing directly from ROM and
decompressing the kernel anywhere in RAM.
> + 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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 24/29] ARM: kernel: implement randomization of the kernel load address
@ 2017-09-04 18:44 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:44 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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..fe4a2cd1f15c 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
This should work even if ZBOOT_ROM is selected. The ZBOOT_ROM option
allows for the decompressor executing directly from ROM and
decompressing the kernel anywhere in RAM.
> + 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 [flat|nested] 166+ messages in thread
* [PATCH v2 25/29] ARM: decompressor: explicitly map decompressor binary cacheable
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 18:47 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:47 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 25/29] ARM: decompressor: explicitly map decompressor binary cacheable
@ 2017-09-04 18:47 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:47 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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>
Acked-by: Nicolas Pitre <nico@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 [flat|nested] 166+ messages in thread
* [PATCH v2 26/29] ARM: decompressor: add KASLR support
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-04 18:53 ` Nicolas Pitre
-1 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:53 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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 will extract some pseudo-randomness from the low
> bits of the generic timer (if available), and use CRC-16 to combine
> it with the build ID string and the device tree binary (which ideally
> has a /chosen/kaslr-seed property, but may also have other properties
> that differ between boots). This seed is used to select one of the
> candidate offsets in the lowmem region that don't overlap the zImage
> itself, the DTB, the initrd and /memreserve/s and/or /reserved-memory
> nodes that should be left alone.
>
> When booting via the UEFI stub, it is left up to the firmware to supply
> a suitable seed and select an offset.
Why did you remove the entropy contribution from general regs upon
entry? That was an easy way to enable KASLR on those platforms not using
DT as they would simply have to put some random value in any of the
regs.
>
> Cc: Russell King <linux@armlinux.org.uk>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> arch/arm/boot/compressed/Makefile | 8 +-
> arch/arm/boot/compressed/head.S | 84 ++++-
> arch/arm/boot/compressed/kaslr.c | 398 ++++++++++++++++++++
> 3 files changed, 484 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
> index d50430c40045..771b1ba1baa3 100644
> --- a/arch/arm/boot/compressed/Makefile
> +++ b/arch/arm/boot/compressed/Makefile
> @@ -85,8 +85,14 @@ $(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/
> $(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
> $(addprefix $(obj)/,$(libfdt_hdrs))
>
> +ifneq ($(CONFIG_ARM_ATAG_DTB_COMPAT)$(CONFIG_RANDOMIZE_BASE),)
> +OBJS += $(libfdt_objs)
> ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
> -OBJS += $(libfdt_objs) atags_to_fdt.o
> +OBJS += atags_to_fdt.o
> +endif
> +ifeq ($(CONFIG_RANDOMIZE_BASE),y)
> +OBJS += kaslr.o
> +endif
> endif
>
> targets := vmlinux vmlinux.lds piggy_data piggy.o \
> diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
> index 583cc6899d98..79b4033b0ed4 100644
> --- a/arch/arm/boot/compressed/head.S
> +++ b/arch/arm/boot/compressed/head.S
> @@ -381,6 +381,42 @@ restart: adr r0, LC0
> dtb_check_done:
> #endif
>
> +#ifdef CONFIG_RANDOMIZE_BASE
> + ldr r1, kaslr_offset @ check if the kaslr_offset is
> + cmp r1, #0 @ already set
> +#ifdef CONFIG_EFI_STUB
> + ldreq r1, __efi_boot @ UEFI has its own KASLR init
> + cmpeq r1, #0 @ routine so skip over this one
> +#endif
> + bne 1f
> +
> + stmfd sp!, {r0-r3, ip, lr}
> + adr_l r2, _text @ start of zImage
> + stmfd sp!, {r2, r8, r10} @ pass stack arguments
> +
> +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
> + /*
> + * Get some pseudo-entropy from the low bits of the generic
> + * timer if it is implemented.
> + */
> + mrc p15, 0, r1, c0, c1, 1 @ read ID_PFR1 register
> + tst r1, #0x10000 @ have generic timer?
> + beq 0f
> + mrrc p15, 1, r3, r1, c14 @ read CNTVCT
> +#endif
> +0: adr_l r0, kaslr_offset @ pass &kaslr_offset in r0
> + mov r1, r4 @ pass base address
> + mov r2, r9 @ pass decompressed image size
> + eor r3, r3, r3, ror #16 @ pass initial seed
> + bl kaslr_early_init
> + add sp, sp, #12
> + cmp r0, #0
> + addne r4, r4, r0 @ add offset to base address
> + ldmfd sp!, {r0-r3, ip, lr}
> + bne restart
> +1:
> +#endif
> +
> /*
> * Check to see if we will overwrite ourselves.
> * r4 = final kernel address (possibly with LSB set)
> @@ -1356,25 +1392,63 @@ __hyp_reentry_vectors:
>
> __enter_kernel:
> mov r0, #0 @ must be 0
> +#ifdef CONFIG_RANDOMIZE_BASE
> + ldr 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
>
> +#ifdef CONFIG_RANDOMIZE_BASE
> + /*
> + * Minimal implementation of CRC-16 that does not use a
> + * lookup table and uses 32-bit wide loads, so it still
> + * performs reasonably well with the D-cache off. Equivalent
> + * to lib/crc16.c for input sizes that are 4 byte multiples.
> + */
> +ENTRY(__crc16)
> + push {r4, lr}
> + ldr r3, =0xa001 @ CRC-16 polynomial
> +0: subs r2, r2, #4
> + popmi {r4, pc}
> + ldr r4, [r1], #4
> +#ifdef __ARMEB__
> + eor ip, r4, r4, ror #16 @ endian swap
> + bic ip, ip, #0x00ff0000
> + mov r4, r4, ror #8
> + eor r4, r4, ip, lsr #8
> +#endif
> + eor r0, r0, r4
> + .rept 32
> + lsrs r0, r0, #1
> + eorcs r0, r0, r3
> + .endr
> + b 0b
> +ENDPROC(__crc16)
> +
> + .align 2
> +kaslr_offset: .long 0
> +#ifdef CONFIG_EFI_STUB
> +__efi_boot: .long 0
> +#endif
> +#endif
> +
> reloc_code_end:
>
> #ifdef CONFIG_EFI_STUB
> .align 2
> -_start: .long start - .
> -
> ENTRY(efi_stub_entry)
> @ allocate space on stack for passing current zImage address
> @ and for the EFI stub to return of new entry point of
> @ zImage, as EFI stub may copy the kernel. Pointer address
> @ is passed in r2. r0 and r1 are passed through from the
> @ EFI firmware to efi_entry
> - adr ip, _start
> - ldr r3, [ip]
> - add r3, r3, ip
> +#ifdef CONFIG_RANDOMIZE_BASE
> + adr r3, __efi_boot
> + str r3, [r3] @ set __efi_boot != 0
> +#endif
> + adr_l r3, start
> stmfd sp!, {r3, lr}
> mov r2, sp @ pass zImage address in r2
> bl efi_entry
> diff --git a/arch/arm/boot/compressed/kaslr.c b/arch/arm/boot/compressed/kaslr.c
> new file mode 100644
> index 000000000000..c68bdea764b6
> --- /dev/null
> +++ b/arch/arm/boot/compressed/kaslr.c
> @@ -0,0 +1,398 @@
> +/*
> + * 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.
> + *
> + */
> +
> +#include <libfdt.h>
> +#include <linux/types.h>
> +#include <generated/compile.h>
> +#include <generated/utsrelease.h>
> +#include <asm/pgtable.h>
> +
> +struct regions {
> + u32 pa_start;
> + u32 pa_end;
> + u32 image_size;
> + u32 zimage_start;
> + u32 zimage_size;
> + u32 dtb_start;
> + u32 dtb_size;
> + u32 initrd_start;
> + u32 initrd_size;
> + int reserved_mem;
> + int reserved_mem_addr_cells;
> + int reserved_mem_size_cells;
> +};
> +
> +extern u32 __crc16(u32 crc, u32 const input[], int byte_count);
> +
> +static u32 __memparse(const char *val, const char **retptr)
> +{
> + int base = 10;
> + u32 ret = 0;
> +
> + if (*val == '0') {
> + val++;
> + if (*val == 'x' || *val == 'X') {
> + val++;
> + base = 16;
> + } else {
> + base = 8;
> + }
> + }
> +
> + while (*val != ',' && *val != ' ' && *val != '\0') {
> + char c = *val++;
> +
> + switch (c) {
> + case '0' ... '9':
> + ret = ret * base + (c - '0');
> + continue;
> + case 'a' ... 'f':
> + ret = ret * base + (c - 'a' + 10);
> + continue;
> + case 'A' ... 'F':
> + ret = ret * base + (c - 'A' + 10);
> + continue;
> + case 'g':
> + case 'G':
> + ret <<= 10;
> + case 'm':
> + case 'M':
> + ret <<= 10;
> + case 'k':
> + case 'K':
> + ret <<= 10;
> + break;
> + default:
> + if (retptr)
> + *retptr = NULL;
> + return 0;
> + }
> + }
> + if (retptr)
> + *retptr = val;
> + return ret;
> +}
> +
> +static bool regions_intersect(u32 s1, u32 e1, u32 s2, u32 e2)
> +{
> + return e1 >= s2 && e2 >= s1;
> +}
> +
> +static bool intersects_reserved_region(const void *fdt, u32 start,
> + u32 end, struct regions *regions)
> +{
> + int subnode, len, i;
> + u64 base, size;
> +
> + /* check for overlap with /memreserve/ entries */
> + for (i = 0; i < fdt_num_mem_rsv(fdt); i++) {
> + if (fdt_get_mem_rsv(fdt, i, &base, &size) < 0)
> + continue;
> + if (regions_intersect(start, end, base, base + size))
> + return true;
> + }
> +
> + if (regions->reserved_mem < 0)
> + return false;
> +
> + /* check for overlap with static reservations in /reserved-memory */
> + for (subnode = fdt_first_subnode(fdt, regions->reserved_mem);
> + subnode >= 0;
> + subnode = fdt_next_subnode(fdt, subnode)) {
> + const fdt32_t *reg;
> +
> + len = 0;
> + reg = fdt_getprop(fdt, subnode, "reg", &len);
> + while (len >= (regions->reserved_mem_addr_cells +
> + regions->reserved_mem_size_cells)) {
> +
> + base = fdt32_to_cpu(reg[0]);
> + if (regions->reserved_mem_addr_cells == 2)
> + base = (base << 32) | fdt32_to_cpu(reg[1]);
> +
> + reg += regions->reserved_mem_addr_cells;
> + len -= 4 * regions->reserved_mem_addr_cells;
> +
> + size = fdt32_to_cpu(reg[0]);
> + if (regions->reserved_mem_size_cells == 2)
> + size = (size << 32) | fdt32_to_cpu(reg[1]);
> +
> + reg += regions->reserved_mem_size_cells;
> + len -= 4 * regions->reserved_mem_size_cells;
> +
> + if (base >= regions->pa_end)
> + continue;
> +
> + if (regions_intersect(start, end, base,
> + min(base + size, (u64)U32_MAX)))
> + return true;
> + }
> + }
> + return false;
> +}
> +
> +static bool intersects_occupied_region(const void *fdt, u32 start,
> + u32 end, struct regions *regions)
> +{
> + if (regions_intersect(start, end, regions->zimage_start,
> + regions->zimage_start + regions->zimage_size))
> + return true;
> +
> + if (regions_intersect(start, end, regions->initrd_start,
> + regions->initrd_start + regions->initrd_size))
> + return true;
> +
> + if (regions_intersect(start, end, regions->dtb_start,
> + regions->dtb_start + regions->dtb_size))
> + return true;
> +
> + return intersects_reserved_region(fdt, start, end, regions);
> +}
> +
> +static u32 count_suitable_regions(const void *fdt, struct regions *regions)
> +{
> + u32 pa, ret = 0;
> +
> + for (pa = regions->pa_start; pa < regions->pa_end; pa += SZ_2M) {
> + if (!intersects_occupied_region(fdt, pa,
> + pa + regions->image_size,
> + regions))
> + ret++;
> + }
> + return ret;
> +}
> +
> +static u32 get_numbered_region(const void *fdt,
> + struct regions *regions,
> + int num)
> +{
> + u32 pa;
> +
> + for (pa = regions->pa_start; pa < regions->pa_end; pa += SZ_2M) {
> + if (!intersects_occupied_region(fdt, pa,
> + pa + regions->image_size,
> + regions))
> + if (num-- == 0)
> + return pa;
> + }
> + return regions->pa_start; /* should not happen */
> +}
> +
> +static void get_cell_sizes(const void *fdt, int node, int *addr_cells,
> + int *size_cells)
> +{
> + const int *prop;
> + int len;
> +
> + /*
> + * Retrieve the #address-cells and #size-cells properties
> + * from the 'node', or use the default if not provided.
> + */
> + *addr_cells = *size_cells = 1;
> +
> + prop = fdt_getprop(fdt, node, "#address-cells", &len);
> + if (len == 4)
> + *addr_cells = fdt32_to_cpu(*prop);
> + prop = fdt_getprop(fdt, node, "#size-cells", &len);
> + if (len == 4)
> + *size_cells = fdt32_to_cpu(*prop);
> +}
> +
> +static u32 get_memory_end(const void *fdt)
> +{
> + int mem_node, address_cells, size_cells, len;
> + const fdt32_t *reg;
> + u64 memory_end = 0;
> +
> + /* Look for a node called "memory" at the lowest level of the tree */
> + mem_node = fdt_path_offset(fdt, "/memory");
> + if (mem_node <= 0)
> + return 0;
> +
> + get_cell_sizes(fdt, 0, &address_cells, &size_cells);
> +
> + /*
> + * Now find the 'reg' property of the /memory node, and iterate over
> + * the base/size pairs.
> + */
> + len = 0;
> + reg = fdt_getprop(fdt, mem_node, "reg", &len);
> + while (len >= 4 * (address_cells + size_cells)) {
> + u64 base, size;
> +
> + base = fdt32_to_cpu(reg[0]);
> + if (address_cells == 2)
> + base = (base << 32) | fdt32_to_cpu(reg[1]);
> +
> + reg += address_cells;
> + len -= 4 * address_cells;
> +
> + size = fdt32_to_cpu(reg[0]);
> + if (size_cells == 2)
> + size = (size << 32) | fdt32_to_cpu(reg[1]);
> +
> + reg += size_cells;
> + len -= 4 * size_cells;
> +
> + memory_end = max(memory_end, base + size);
> + }
> + return min(memory_end, (u64)U32_MAX);
> +}
> +
> +static char *__strstr(const char *s1, const char *s2, int l2)
> +{
> + int l1;
> +
> + l1 = strlen(s1);
> + while (l1 >= l2) {
> + l1--;
> + if (!memcmp(s1, s2, l2))
> + return (char *)s1;
> + s1++;
> + }
> + return NULL;
> +}
> +
> +static const char *get_cmdline_param(const char *cmdline, const char *param,
> + int param_size)
> +{
> + static const char default_cmdline[] = CONFIG_CMDLINE;
> + const char *p;
> +
> + if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline != NULL) {
> + p = __strstr(cmdline, param, param_size);
> + if (p == cmdline ||
> + (p > cmdline && *(p - 1) == ' '))
> + return p;
> + }
> +
> + if (IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
> + IS_ENABLED(CONFIG_CMDLINE_EXTEND)) {
> + p = __strstr(default_cmdline, param, param_size);
> + if (p == default_cmdline ||
> + (p > default_cmdline && *(p - 1) == ' '))
> + return p;
> + }
> + return NULL;
> +}
> +
> +u32 kaslr_early_init(u32 *kaslr_offset, u32 image_base, u32 image_size,
> + u32 seed, u32 zimage_start, const void *fdt,
> + u32 zimage_end)
> +{
> + static const char __aligned(4) build_id[] = UTS_VERSION UTS_RELEASE;
> + struct regions regions;
> + const char *command_line;
> + const char *p;
> + int chosen, len;
> + u32 lowmem_top, num;
> +
> + if (fdt_check_header(fdt))
> + return 0;
> +
> + chosen = fdt_path_offset(fdt, "/chosen");
> + if (chosen < 0)
> + return 0;
> +
> + command_line = fdt_getprop(fdt, chosen, "bootargs", &len);
> +
> + /* check the command line for the presence of 'nokaslr' */
> + p = get_cmdline_param(command_line, "nokaslr", sizeof("nokaslr") - 1);
> + if (p != NULL)
> + return 0;
> +
> + /* check the command line for the presence of 'vmalloc=' */
> + p = get_cmdline_param(command_line, "vmalloc=", sizeof("vmalloc=") - 1);
> + if (p != NULL)
> + lowmem_top = VMALLOC_END - __memparse(p + 8, NULL) -
> + VMALLOC_OFFSET;
> + else
> + lowmem_top = VMALLOC_DEFAULT_BASE;
> +
> + regions.image_size = round_up(image_size, SZ_2M);
> + regions.pa_start = round_down(image_base, SZ_128M);
> + regions.pa_end = lowmem_top - PAGE_OFFSET + regions.pa_start -
> + regions.image_size;
> + regions.zimage_start = zimage_start;
> + regions.zimage_size = zimage_end - zimage_start;
> + regions.dtb_start = (u32)fdt;
> + regions.dtb_size = fdt_totalsize(fdt);
> +
> + /*
> + * Stir up the seed a bit by taking the CRC of the DTB:
> + * hopefully there's a /chosen/kaslr-seed in there.
> + */
> + seed = __crc16(seed, fdt, regions.dtb_size);
> +
> + /* stir a bit more using data that changes between builds */
> + seed = __crc16(seed, (u32 *)build_id, sizeof(build_id));
> +
> + /* check for initrd on the command line */
> + regions.initrd_start = regions.initrd_size = 0;
> + p = get_cmdline_param(command_line, "initrd=", sizeof("initrd=") - 1);
> + if (p != NULL) {
> + regions.initrd_start = __memparse(p + 7, &p);
> + if (*p++ == ',')
> + regions.initrd_size = __memparse(p, NULL);
> + if (regions.initrd_size == 0)
> + regions.initrd_start = 0;
> + }
> +
> + /* ... or in /chosen */
> + if (regions.initrd_size == 0) {
> + const fdt32_t *prop;
> + u64 start = 0, end = 0;
> +
> + prop = fdt_getprop(fdt, chosen, "linux,initrd-start", &len);
> + if (prop) {
> + start = fdt32_to_cpu(prop[0]);
> + if (len == 8)
> + start = (start << 32) | fdt32_to_cpu(prop[1]);
> + }
> +
> + prop = fdt_getprop(fdt, chosen, "linux,initrd-end", &len);
> + if (prop) {
> + end = fdt32_to_cpu(prop[0]);
> + if (len == 8)
> + end = (end << 32) | fdt32_to_cpu(prop[1]);
> + }
> + if (start != 0 && end != 0 && start < U32_MAX) {
> + regions.initrd_start = start;
> + regions.initrd_size = max_t(u64, end, U32_MAX) - start;
> + }
> + }
> +
> + /* check the memory nodes for the size of the lowmem region */
> + regions.pa_end = min(regions.pa_end, get_memory_end(fdt));
> +
> + /* check for a reserved-memory node and record its cell sizes */
> + regions.reserved_mem = fdt_path_offset(fdt, "/reserved-memory");
> + if (regions.reserved_mem >= 0)
> + get_cell_sizes(fdt, regions.reserved_mem,
> + ®ions.reserved_mem_addr_cells,
> + ®ions.reserved_mem_size_cells);
> +
> + /*
> + * Iterate over the physical memory range covered by the lowmem region
> + * in 2 MB increments, and count each offset at which we don't overlap
> + * with any of the reserved regions for the zImage itself, the DTB,
> + * the initrd and any regions described as reserved in the device tree.
> + * This produces a count, which we will scale by multiplying by a 16-bit
> + * random value and shifting right by 16 places.
> + * Using this random value, we iterate over the physical memory range
> + * again until we counted enough iterations, and return the offset we
> + * ended up at.
> + */
> + num = ((u16)seed * count_suitable_regions(fdt, ®ions)) >> 16;
> +
> + *kaslr_offset = get_numbered_region(fdt, ®ions, num) -
> + regions.pa_start;
> +
> + return *kaslr_offset;
> +}
> --
> 2.11.0
>
>
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 26/29] ARM: decompressor: add KASLR support
@ 2017-09-04 18:53 ` Nicolas Pitre
0 siblings, 0 replies; 166+ messages in thread
From: Nicolas Pitre @ 2017-09-04 18:53 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
> 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 will extract some pseudo-randomness from the low
> bits of the generic timer (if available), and use CRC-16 to combine
> it with the build ID string and the device tree binary (which ideally
> has a /chosen/kaslr-seed property, but may also have other properties
> that differ between boots). This seed is used to select one of the
> candidate offsets in the lowmem region that don't overlap the zImage
> itself, the DTB, the initrd and /memreserve/s and/or /reserved-memory
> nodes that should be left alone.
>
> When booting via the UEFI stub, it is left up to the firmware to supply
> a suitable seed and select an offset.
Why did you remove the entropy contribution from general regs upon
entry? That was an easy way to enable KASLR on those platforms not using
DT as they would simply have to put some random value in any of the
regs.
>
> Cc: Russell King <linux@armlinux.org.uk>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> arch/arm/boot/compressed/Makefile | 8 +-
> arch/arm/boot/compressed/head.S | 84 ++++-
> arch/arm/boot/compressed/kaslr.c | 398 ++++++++++++++++++++
> 3 files changed, 484 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
> index d50430c40045..771b1ba1baa3 100644
> --- a/arch/arm/boot/compressed/Makefile
> +++ b/arch/arm/boot/compressed/Makefile
> @@ -85,8 +85,14 @@ $(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/
> $(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
> $(addprefix $(obj)/,$(libfdt_hdrs))
>
> +ifneq ($(CONFIG_ARM_ATAG_DTB_COMPAT)$(CONFIG_RANDOMIZE_BASE),)
> +OBJS += $(libfdt_objs)
> ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
> -OBJS += $(libfdt_objs) atags_to_fdt.o
> +OBJS += atags_to_fdt.o
> +endif
> +ifeq ($(CONFIG_RANDOMIZE_BASE),y)
> +OBJS += kaslr.o
> +endif
> endif
>
> targets := vmlinux vmlinux.lds piggy_data piggy.o \
> diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
> index 583cc6899d98..79b4033b0ed4 100644
> --- a/arch/arm/boot/compressed/head.S
> +++ b/arch/arm/boot/compressed/head.S
> @@ -381,6 +381,42 @@ restart: adr r0, LC0
> dtb_check_done:
> #endif
>
> +#ifdef CONFIG_RANDOMIZE_BASE
> + ldr r1, kaslr_offset @ check if the kaslr_offset is
> + cmp r1, #0 @ already set
> +#ifdef CONFIG_EFI_STUB
> + ldreq r1, __efi_boot @ UEFI has its own KASLR init
> + cmpeq r1, #0 @ routine so skip over this one
> +#endif
> + bne 1f
> +
> + stmfd sp!, {r0-r3, ip, lr}
> + adr_l r2, _text @ start of zImage
> + stmfd sp!, {r2, r8, r10} @ pass stack arguments
> +
> +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
> + /*
> + * Get some pseudo-entropy from the low bits of the generic
> + * timer if it is implemented.
> + */
> + mrc p15, 0, r1, c0, c1, 1 @ read ID_PFR1 register
> + tst r1, #0x10000 @ have generic timer?
> + beq 0f
> + mrrc p15, 1, r3, r1, c14 @ read CNTVCT
> +#endif
> +0: adr_l r0, kaslr_offset @ pass &kaslr_offset in r0
> + mov r1, r4 @ pass base address
> + mov r2, r9 @ pass decompressed image size
> + eor r3, r3, r3, ror #16 @ pass initial seed
> + bl kaslr_early_init
> + add sp, sp, #12
> + cmp r0, #0
> + addne r4, r4, r0 @ add offset to base address
> + ldmfd sp!, {r0-r3, ip, lr}
> + bne restart
> +1:
> +#endif
> +
> /*
> * Check to see if we will overwrite ourselves.
> * r4 = final kernel address (possibly with LSB set)
> @@ -1356,25 +1392,63 @@ __hyp_reentry_vectors:
>
> __enter_kernel:
> mov r0, #0 @ must be 0
> +#ifdef CONFIG_RANDOMIZE_BASE
> + ldr 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
>
> +#ifdef CONFIG_RANDOMIZE_BASE
> + /*
> + * Minimal implementation of CRC-16 that does not use a
> + * lookup table and uses 32-bit wide loads, so it still
> + * performs reasonably well with the D-cache off. Equivalent
> + * to lib/crc16.c for input sizes that are 4 byte multiples.
> + */
> +ENTRY(__crc16)
> + push {r4, lr}
> + ldr r3, =0xa001 @ CRC-16 polynomial
> +0: subs r2, r2, #4
> + popmi {r4, pc}
> + ldr r4, [r1], #4
> +#ifdef __ARMEB__
> + eor ip, r4, r4, ror #16 @ endian swap
> + bic ip, ip, #0x00ff0000
> + mov r4, r4, ror #8
> + eor r4, r4, ip, lsr #8
> +#endif
> + eor r0, r0, r4
> + .rept 32
> + lsrs r0, r0, #1
> + eorcs r0, r0, r3
> + .endr
> + b 0b
> +ENDPROC(__crc16)
> +
> + .align 2
> +kaslr_offset: .long 0
> +#ifdef CONFIG_EFI_STUB
> +__efi_boot: .long 0
> +#endif
> +#endif
> +
> reloc_code_end:
>
> #ifdef CONFIG_EFI_STUB
> .align 2
> -_start: .long start - .
> -
> ENTRY(efi_stub_entry)
> @ allocate space on stack for passing current zImage address
> @ and for the EFI stub to return of new entry point of
> @ zImage, as EFI stub may copy the kernel. Pointer address
> @ is passed in r2. r0 and r1 are passed through from the
> @ EFI firmware to efi_entry
> - adr ip, _start
> - ldr r3, [ip]
> - add r3, r3, ip
> +#ifdef CONFIG_RANDOMIZE_BASE
> + adr r3, __efi_boot
> + str r3, [r3] @ set __efi_boot != 0
> +#endif
> + adr_l r3, start
> stmfd sp!, {r3, lr}
> mov r2, sp @ pass zImage address in r2
> bl efi_entry
> diff --git a/arch/arm/boot/compressed/kaslr.c b/arch/arm/boot/compressed/kaslr.c
> new file mode 100644
> index 000000000000..c68bdea764b6
> --- /dev/null
> +++ b/arch/arm/boot/compressed/kaslr.c
> @@ -0,0 +1,398 @@
> +/*
> + * 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.
> + *
> + */
> +
> +#include <libfdt.h>
> +#include <linux/types.h>
> +#include <generated/compile.h>
> +#include <generated/utsrelease.h>
> +#include <asm/pgtable.h>
> +
> +struct regions {
> + u32 pa_start;
> + u32 pa_end;
> + u32 image_size;
> + u32 zimage_start;
> + u32 zimage_size;
> + u32 dtb_start;
> + u32 dtb_size;
> + u32 initrd_start;
> + u32 initrd_size;
> + int reserved_mem;
> + int reserved_mem_addr_cells;
> + int reserved_mem_size_cells;
> +};
> +
> +extern u32 __crc16(u32 crc, u32 const input[], int byte_count);
> +
> +static u32 __memparse(const char *val, const char **retptr)
> +{
> + int base = 10;
> + u32 ret = 0;
> +
> + if (*val == '0') {
> + val++;
> + if (*val == 'x' || *val == 'X') {
> + val++;
> + base = 16;
> + } else {
> + base = 8;
> + }
> + }
> +
> + while (*val != ',' && *val != ' ' && *val != '\0') {
> + char c = *val++;
> +
> + switch (c) {
> + case '0' ... '9':
> + ret = ret * base + (c - '0');
> + continue;
> + case 'a' ... 'f':
> + ret = ret * base + (c - 'a' + 10);
> + continue;
> + case 'A' ... 'F':
> + ret = ret * base + (c - 'A' + 10);
> + continue;
> + case 'g':
> + case 'G':
> + ret <<= 10;
> + case 'm':
> + case 'M':
> + ret <<= 10;
> + case 'k':
> + case 'K':
> + ret <<= 10;
> + break;
> + default:
> + if (retptr)
> + *retptr = NULL;
> + return 0;
> + }
> + }
> + if (retptr)
> + *retptr = val;
> + return ret;
> +}
> +
> +static bool regions_intersect(u32 s1, u32 e1, u32 s2, u32 e2)
> +{
> + return e1 >= s2 && e2 >= s1;
> +}
> +
> +static bool intersects_reserved_region(const void *fdt, u32 start,
> + u32 end, struct regions *regions)
> +{
> + int subnode, len, i;
> + u64 base, size;
> +
> + /* check for overlap with /memreserve/ entries */
> + for (i = 0; i < fdt_num_mem_rsv(fdt); i++) {
> + if (fdt_get_mem_rsv(fdt, i, &base, &size) < 0)
> + continue;
> + if (regions_intersect(start, end, base, base + size))
> + return true;
> + }
> +
> + if (regions->reserved_mem < 0)
> + return false;
> +
> + /* check for overlap with static reservations in /reserved-memory */
> + for (subnode = fdt_first_subnode(fdt, regions->reserved_mem);
> + subnode >= 0;
> + subnode = fdt_next_subnode(fdt, subnode)) {
> + const fdt32_t *reg;
> +
> + len = 0;
> + reg = fdt_getprop(fdt, subnode, "reg", &len);
> + while (len >= (regions->reserved_mem_addr_cells +
> + regions->reserved_mem_size_cells)) {
> +
> + base = fdt32_to_cpu(reg[0]);
> + if (regions->reserved_mem_addr_cells == 2)
> + base = (base << 32) | fdt32_to_cpu(reg[1]);
> +
> + reg += regions->reserved_mem_addr_cells;
> + len -= 4 * regions->reserved_mem_addr_cells;
> +
> + size = fdt32_to_cpu(reg[0]);
> + if (regions->reserved_mem_size_cells == 2)
> + size = (size << 32) | fdt32_to_cpu(reg[1]);
> +
> + reg += regions->reserved_mem_size_cells;
> + len -= 4 * regions->reserved_mem_size_cells;
> +
> + if (base >= regions->pa_end)
> + continue;
> +
> + if (regions_intersect(start, end, base,
> + min(base + size, (u64)U32_MAX)))
> + return true;
> + }
> + }
> + return false;
> +}
> +
> +static bool intersects_occupied_region(const void *fdt, u32 start,
> + u32 end, struct regions *regions)
> +{
> + if (regions_intersect(start, end, regions->zimage_start,
> + regions->zimage_start + regions->zimage_size))
> + return true;
> +
> + if (regions_intersect(start, end, regions->initrd_start,
> + regions->initrd_start + regions->initrd_size))
> + return true;
> +
> + if (regions_intersect(start, end, regions->dtb_start,
> + regions->dtb_start + regions->dtb_size))
> + return true;
> +
> + return intersects_reserved_region(fdt, start, end, regions);
> +}
> +
> +static u32 count_suitable_regions(const void *fdt, struct regions *regions)
> +{
> + u32 pa, ret = 0;
> +
> + for (pa = regions->pa_start; pa < regions->pa_end; pa += SZ_2M) {
> + if (!intersects_occupied_region(fdt, pa,
> + pa + regions->image_size,
> + regions))
> + ret++;
> + }
> + return ret;
> +}
> +
> +static u32 get_numbered_region(const void *fdt,
> + struct regions *regions,
> + int num)
> +{
> + u32 pa;
> +
> + for (pa = regions->pa_start; pa < regions->pa_end; pa += SZ_2M) {
> + if (!intersects_occupied_region(fdt, pa,
> + pa + regions->image_size,
> + regions))
> + if (num-- == 0)
> + return pa;
> + }
> + return regions->pa_start; /* should not happen */
> +}
> +
> +static void get_cell_sizes(const void *fdt, int node, int *addr_cells,
> + int *size_cells)
> +{
> + const int *prop;
> + int len;
> +
> + /*
> + * Retrieve the #address-cells and #size-cells properties
> + * from the 'node', or use the default if not provided.
> + */
> + *addr_cells = *size_cells = 1;
> +
> + prop = fdt_getprop(fdt, node, "#address-cells", &len);
> + if (len == 4)
> + *addr_cells = fdt32_to_cpu(*prop);
> + prop = fdt_getprop(fdt, node, "#size-cells", &len);
> + if (len == 4)
> + *size_cells = fdt32_to_cpu(*prop);
> +}
> +
> +static u32 get_memory_end(const void *fdt)
> +{
> + int mem_node, address_cells, size_cells, len;
> + const fdt32_t *reg;
> + u64 memory_end = 0;
> +
> + /* Look for a node called "memory" at the lowest level of the tree */
> + mem_node = fdt_path_offset(fdt, "/memory");
> + if (mem_node <= 0)
> + return 0;
> +
> + get_cell_sizes(fdt, 0, &address_cells, &size_cells);
> +
> + /*
> + * Now find the 'reg' property of the /memory node, and iterate over
> + * the base/size pairs.
> + */
> + len = 0;
> + reg = fdt_getprop(fdt, mem_node, "reg", &len);
> + while (len >= 4 * (address_cells + size_cells)) {
> + u64 base, size;
> +
> + base = fdt32_to_cpu(reg[0]);
> + if (address_cells == 2)
> + base = (base << 32) | fdt32_to_cpu(reg[1]);
> +
> + reg += address_cells;
> + len -= 4 * address_cells;
> +
> + size = fdt32_to_cpu(reg[0]);
> + if (size_cells == 2)
> + size = (size << 32) | fdt32_to_cpu(reg[1]);
> +
> + reg += size_cells;
> + len -= 4 * size_cells;
> +
> + memory_end = max(memory_end, base + size);
> + }
> + return min(memory_end, (u64)U32_MAX);
> +}
> +
> +static char *__strstr(const char *s1, const char *s2, int l2)
> +{
> + int l1;
> +
> + l1 = strlen(s1);
> + while (l1 >= l2) {
> + l1--;
> + if (!memcmp(s1, s2, l2))
> + return (char *)s1;
> + s1++;
> + }
> + return NULL;
> +}
> +
> +static const char *get_cmdline_param(const char *cmdline, const char *param,
> + int param_size)
> +{
> + static const char default_cmdline[] = CONFIG_CMDLINE;
> + const char *p;
> +
> + if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline != NULL) {
> + p = __strstr(cmdline, param, param_size);
> + if (p == cmdline ||
> + (p > cmdline && *(p - 1) == ' '))
> + return p;
> + }
> +
> + if (IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
> + IS_ENABLED(CONFIG_CMDLINE_EXTEND)) {
> + p = __strstr(default_cmdline, param, param_size);
> + if (p == default_cmdline ||
> + (p > default_cmdline && *(p - 1) == ' '))
> + return p;
> + }
> + return NULL;
> +}
> +
> +u32 kaslr_early_init(u32 *kaslr_offset, u32 image_base, u32 image_size,
> + u32 seed, u32 zimage_start, const void *fdt,
> + u32 zimage_end)
> +{
> + static const char __aligned(4) build_id[] = UTS_VERSION UTS_RELEASE;
> + struct regions regions;
> + const char *command_line;
> + const char *p;
> + int chosen, len;
> + u32 lowmem_top, num;
> +
> + if (fdt_check_header(fdt))
> + return 0;
> +
> + chosen = fdt_path_offset(fdt, "/chosen");
> + if (chosen < 0)
> + return 0;
> +
> + command_line = fdt_getprop(fdt, chosen, "bootargs", &len);
> +
> + /* check the command line for the presence of 'nokaslr' */
> + p = get_cmdline_param(command_line, "nokaslr", sizeof("nokaslr") - 1);
> + if (p != NULL)
> + return 0;
> +
> + /* check the command line for the presence of 'vmalloc=' */
> + p = get_cmdline_param(command_line, "vmalloc=", sizeof("vmalloc=") - 1);
> + if (p != NULL)
> + lowmem_top = VMALLOC_END - __memparse(p + 8, NULL) -
> + VMALLOC_OFFSET;
> + else
> + lowmem_top = VMALLOC_DEFAULT_BASE;
> +
> + regions.image_size = round_up(image_size, SZ_2M);
> + regions.pa_start = round_down(image_base, SZ_128M);
> + regions.pa_end = lowmem_top - PAGE_OFFSET + regions.pa_start -
> + regions.image_size;
> + regions.zimage_start = zimage_start;
> + regions.zimage_size = zimage_end - zimage_start;
> + regions.dtb_start = (u32)fdt;
> + regions.dtb_size = fdt_totalsize(fdt);
> +
> + /*
> + * Stir up the seed a bit by taking the CRC of the DTB:
> + * hopefully there's a /chosen/kaslr-seed in there.
> + */
> + seed = __crc16(seed, fdt, regions.dtb_size);
> +
> + /* stir a bit more using data that changes between builds */
> + seed = __crc16(seed, (u32 *)build_id, sizeof(build_id));
> +
> + /* check for initrd on the command line */
> + regions.initrd_start = regions.initrd_size = 0;
> + p = get_cmdline_param(command_line, "initrd=", sizeof("initrd=") - 1);
> + if (p != NULL) {
> + regions.initrd_start = __memparse(p + 7, &p);
> + if (*p++ == ',')
> + regions.initrd_size = __memparse(p, NULL);
> + if (regions.initrd_size == 0)
> + regions.initrd_start = 0;
> + }
> +
> + /* ... or in /chosen */
> + if (regions.initrd_size == 0) {
> + const fdt32_t *prop;
> + u64 start = 0, end = 0;
> +
> + prop = fdt_getprop(fdt, chosen, "linux,initrd-start", &len);
> + if (prop) {
> + start = fdt32_to_cpu(prop[0]);
> + if (len == 8)
> + start = (start << 32) | fdt32_to_cpu(prop[1]);
> + }
> +
> + prop = fdt_getprop(fdt, chosen, "linux,initrd-end", &len);
> + if (prop) {
> + end = fdt32_to_cpu(prop[0]);
> + if (len == 8)
> + end = (end << 32) | fdt32_to_cpu(prop[1]);
> + }
> + if (start != 0 && end != 0 && start < U32_MAX) {
> + regions.initrd_start = start;
> + regions.initrd_size = max_t(u64, end, U32_MAX) - start;
> + }
> + }
> +
> + /* check the memory nodes for the size of the lowmem region */
> + regions.pa_end = min(regions.pa_end, get_memory_end(fdt));
> +
> + /* check for a reserved-memory node and record its cell sizes */
> + regions.reserved_mem = fdt_path_offset(fdt, "/reserved-memory");
> + if (regions.reserved_mem >= 0)
> + get_cell_sizes(fdt, regions.reserved_mem,
> + ®ions.reserved_mem_addr_cells,
> + ®ions.reserved_mem_size_cells);
> +
> + /*
> + * Iterate over the physical memory range covered by the lowmem region
> + * in 2 MB increments, and count each offset at which we don't overlap
> + * with any of the reserved regions for the zImage itself, the DTB,
> + * the initrd and any regions described as reserved in the device tree.
> + * This produces a count, which we will scale by multiplying by a 16-bit
> + * random value and shifting right by 16 places.
> + * Using this random value, we iterate over the physical memory range
> + * again until we counted enough iterations, and return the offset we
> + * ended up at.
> + */
> + num = ((u16)seed * count_suitable_regions(fdt, ®ions)) >> 16;
> +
> + *kaslr_offset = get_numbered_region(fdt, ®ions, num) -
> + regions.pa_start;
> +
> + return *kaslr_offset;
> +}
> --
> 2.11.0
>
>
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 17/29] ARM: kernel: use relative phys-to-virt patch tables
2017-09-04 18:03 ` [kernel-hardening] " Nicolas Pitre
@ 2017-09-04 19:09 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:09 UTC (permalink / raw)
To: linux-arm-kernel
On 4 September 2017 at 19:03, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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" \
>
> [...]
>
>> --- a/arch/arm/kernel/head.S
>> +++ b/arch/arm/kernel/head.S
>> @@ -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]
>
> Please use "ldrh ip, [r7, #(-4 + 2)]" so the -4 offset is clearly
> spelled out. The #-2 gave me a pause of confusion.
>
>> 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]
>
> Ditto here.
>
>> bne 2f
>> - ldrh ip, [r7]
>> + ldrh ip, [r7, #-4]
>
> And to be clear, here I'd use "#(-4 + 0)" to be explicit.
>
>> 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]
>
> And so here.
>
OK
>
> With that:
>
> Reviewed-by: Nicolas Pitre <nico@linaro.org>
Thanks.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 17/29] ARM: kernel: use relative phys-to-virt patch tables
@ 2017-09-04 19:09 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:09 UTC (permalink / raw)
To: Nicolas Pitre
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 4 September 2017 at 19:03, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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" \
>
> [...]
>
>> --- a/arch/arm/kernel/head.S
>> +++ b/arch/arm/kernel/head.S
>> @@ -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]
>
> Please use "ldrh ip, [r7, #(-4 + 2)]" so the -4 offset is clearly
> spelled out. The #-2 gave me a pause of confusion.
>
>> 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]
>
> Ditto here.
>
>> bne 2f
>> - ldrh ip, [r7]
>> + ldrh ip, [r7, #-4]
>
> And to be clear, here I'd use "#(-4 + 0)" to be explicit.
>
>> 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]
>
> And so here.
>
OK
>
> With that:
>
> Reviewed-by: Nicolas Pitre <nico@linaro.org>
Thanks.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 19/29] ARM: kernel: make vmlinux buildable as a PIE executable
2017-09-04 18:11 ` [kernel-hardening] " Nicolas Pitre
@ 2017-09-04 19:10 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:10 UTC (permalink / raw)
To: linux-arm-kernel
On 4 September 2017 at 19:11, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> Update the build flags and linker script to allow vmlinux to be built
>> 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 | 2 +-
>> arch/arm/kernel/vmlinux.lds.S | 9 +++++++++
>> include/linux/hidden.h | 20 ++++++++++++++++++++
>> scripts/module-common.lds | 1 +
>> 6 files changed, 40 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
>> +
>
> You should probably make it depend on !XIP_KERNEL.
>
Indeed.
> Other than that
>
> Acked-by: Nicolas Pitre <nico@linaro.org>
>
Thanks.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 19/29] ARM: kernel: make vmlinux buildable as a PIE executable
@ 2017-09-04 19:10 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:10 UTC (permalink / raw)
To: Nicolas Pitre
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 4 September 2017 at 19:11, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> Update the build flags and linker script to allow vmlinux to be built
>> 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 | 2 +-
>> arch/arm/kernel/vmlinux.lds.S | 9 +++++++++
>> include/linux/hidden.h | 20 ++++++++++++++++++++
>> scripts/module-common.lds | 1 +
>> 6 files changed, 40 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
>> +
>
> You should probably make it depend on !XIP_KERNEL.
>
Indeed.
> Other than that
>
> Acked-by: Nicolas Pitre <nico@linaro.org>
>
Thanks.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 20/29] ARM: kernel: use PC-relative symbol references in MMU switch code
2017-09-04 18:15 ` [kernel-hardening] " Nicolas Pitre
@ 2017-09-04 19:14 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:14 UTC (permalink / raw)
To: linux-arm-kernel
On 4 September 2017 at 19:15, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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
>
> The code that follows is testing for a non-zero r7 value to store r0 so
> you could make that code conditional rather than loading 0 here.
>
OK, I will look into that.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 20/29] ARM: kernel: use PC-relative symbol references in MMU switch code
@ 2017-09-04 19:14 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:14 UTC (permalink / raw)
To: Nicolas Pitre
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 4 September 2017 at 19:15, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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
>
> The code that follows is testing for a non-zero r7 value to store r0 so
> you could make that code conditional rather than loading 0 here.
>
OK, I will look into that.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 21/29] ARM: kernel: use PC relative symbol references in suspend/resume code
2017-09-04 18:24 ` [kernel-hardening] " Nicolas Pitre
@ 2017-09-04 19:17 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:17 UTC (permalink / raw)
To: linux-arm-kernel
On 4 September 2017 at 19:24, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 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>
>
> What's the point of that last hunk? I understand you load the address
> after the mMU is on. But you should be coming back from a sleep and
> caches ought to be clean at that point. Not that it is a bad thing to do
> but I don't understand your reason for it.
>
I simply attempted to eliminate all uses of relocated quantities with
the caches off, but you are correct that this is only necessary for
boot and not for suspend/resume. This is actually somewhat of a
relief, since there is so much SOC specific suspend/resume code under
arch/arm, and the boot code is mostly shared.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 21/29] ARM: kernel: use PC relative symbol references in suspend/resume code
@ 2017-09-04 19:17 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:17 UTC (permalink / raw)
To: Nicolas Pitre
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 4 September 2017 at 19:24, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 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>
>
> What's the point of that last hunk? I understand you load the address
> after the mMU is on. But you should be coming back from a sleep and
> caches ought to be clean at that point. Not that it is a bad thing to do
> but I don't understand your reason for it.
>
I simply attempted to eliminate all uses of relocated quantities with
the caches off, but you are correct that this is only necessary for
boot and not for suspend/resume. This is actually somewhat of a
relief, since there is so much SOC specific suspend/resume code under
arch/arm, and the boot code is mostly shared.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 23/29] ARM: kernel: refer to swapper_pg_dir via its symbol
2017-09-04 18:30 ` [kernel-hardening] " Nicolas Pitre
@ 2017-09-04 19:26 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:26 UTC (permalink / raw)
To: linux-arm-kernel
On 4 September 2017 at 19:30, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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.
>
> Could it cause a section access mismatch if defined in the __HEAD
> section?
>
No, I never saw any mismatch warnings building this code, and I don't
think .head.text is treated as an __init section.
> Otherwise
>
> Acked-by: Nicolas Pitre <nico@linaro.org>
>
Thanks
>>
>> 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 [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 23/29] ARM: kernel: refer to swapper_pg_dir via its symbol
@ 2017-09-04 19:26 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:26 UTC (permalink / raw)
To: Nicolas Pitre
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 4 September 2017 at 19:30, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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.
>
> Could it cause a section access mismatch if defined in the __HEAD
> section?
>
No, I never saw any mismatch warnings building this code, and I don't
think .head.text is treated as an __init section.
> Otherwise
>
> Acked-by: Nicolas Pitre <nico@linaro.org>
>
Thanks
>>
>> 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 [flat|nested] 166+ messages in thread
* [PATCH v2 24/29] ARM: kernel: implement randomization of the kernel load address
2017-09-04 18:44 ` [kernel-hardening] " Nicolas Pitre
@ 2017-09-04 19:29 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:29 UTC (permalink / raw)
To: linux-arm-kernel
On 4 September 2017 at 19:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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..fe4a2cd1f15c 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
>
> This should work even if ZBOOT_ROM is selected. The ZBOOT_ROM option
> allows for the decompressor executing directly from ROM and
> decompressing the kernel anywhere in RAM.
>
In principle, yes. But currently, the code is not entirely XIP clean,
i.e., the kaslr_offset and __efi_boot variables are in .text but
assumed to be writable.
For UEFI, this does not really matter, because that implies !XIP.
However, I agree it would be nice if ZBOOT_ROM could run this code as
well, but it requires a global variable. I will try to make that work.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 24/29] ARM: kernel: implement randomization of the kernel load address
@ 2017-09-04 19:29 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:29 UTC (permalink / raw)
To: Nicolas Pitre
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 4 September 2017 at 19:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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..fe4a2cd1f15c 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
>
> This should work even if ZBOOT_ROM is selected. The ZBOOT_ROM option
> allows for the decompressor executing directly from ROM and
> decompressing the kernel anywhere in RAM.
>
In principle, yes. But currently, the code is not entirely XIP clean,
i.e., the kaslr_offset and __efi_boot variables are in .text but
assumed to be writable.
For UEFI, this does not really matter, because that implies !XIP.
However, I agree it would be nice if ZBOOT_ROM could run this code as
well, but it requires a global variable. I will try to make that work.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 26/29] ARM: decompressor: add KASLR support
2017-09-04 18:53 ` [kernel-hardening] " Nicolas Pitre
@ 2017-09-04 19:33 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:33 UTC (permalink / raw)
To: linux-arm-kernel
On 4 September 2017 at 19:53, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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 will extract some pseudo-randomness from the low
>> bits of the generic timer (if available), and use CRC-16 to combine
>> it with the build ID string and the device tree binary (which ideally
>> has a /chosen/kaslr-seed property, but may also have other properties
>> that differ between boots). This seed is used to select one of the
>> candidate offsets in the lowmem region that don't overlap the zImage
>> itself, the DTB, the initrd and /memreserve/s and/or /reserved-memory
>> nodes that should be left alone.
>>
>> When booting via the UEFI stub, it is left up to the firmware to supply
>> a suitable seed and select an offset.
>
> Why did you remove the entropy contribution from general regs upon
> entry? That was an easy way to enable KASLR on those platforms not using
> DT as they would simply have to put some random value in any of the
> regs.
>
I simply did not consider non-DTB, to be honest. I implemented the
suggestion to stir the entropy using some build time data and the DTB
contents, and given that the kaslr entry code parses the command line
and other DTB structures (/memreserve/, /reserved-memory,
/chosen/initrd-xxx) to decide where to uncompress the kernel, the
thought never crossed my mind to add support for !DTB as well. And to
be perfectly honest, I'd rather rely on the ATAG to DTB compat code so
I don't have to implement an ATAGS version of kaslr_early_init()
Of course, that still does not rule out eor'ing all the register
together instead of only r3, so I will add that back.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 26/29] ARM: decompressor: add KASLR support
@ 2017-09-04 19:33 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-04 19:33 UTC (permalink / raw)
To: Nicolas Pitre
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Russell King,
Kees Cook, Thomas Garnier, Marc Zyngier, Mark Rutland,
Tony Lindgren, Matt Fleming, Dave Martin
On 4 September 2017 at 19:53, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Sun, 3 Sep 2017, Ard Biesheuvel wrote:
>
>> 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 will extract some pseudo-randomness from the low
>> bits of the generic timer (if available), and use CRC-16 to combine
>> it with the build ID string and the device tree binary (which ideally
>> has a /chosen/kaslr-seed property, but may also have other properties
>> that differ between boots). This seed is used to select one of the
>> candidate offsets in the lowmem region that don't overlap the zImage
>> itself, the DTB, the initrd and /memreserve/s and/or /reserved-memory
>> nodes that should be left alone.
>>
>> When booting via the UEFI stub, it is left up to the firmware to supply
>> a suitable seed and select an offset.
>
> Why did you remove the entropy contribution from general regs upon
> entry? That was an easy way to enable KASLR on those platforms not using
> DT as they would simply have to put some random value in any of the
> regs.
>
I simply did not consider non-DTB, to be honest. I implemented the
suggestion to stir the entropy using some build time data and the DTB
contents, and given that the kaslr entry code parses the command line
and other DTB structures (/memreserve/, /reserved-memory,
/chosen/initrd-xxx) to decide where to uncompress the kernel, the
thought never crossed my mind to add support for !DTB as well. And to
be perfectly honest, I'd rather rely on the ATAG to DTB compat code so
I don't have to implement an ATAGS version of kaslr_early_init()
Of course, that still does not rule out eor'ing all the register
together instead of only r3, so I will add that back.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-05 16:45 ` Tony Lindgren
-1 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-05 16:45 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170903 05:08]:
> 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 collect some pseudo-entropy, and randomize
> the physical offset of the decompressed kernel, taking placement of DTB,
> initrd and reserved regions into account
> - changes to the UEFI stub code to choose the KASLR offset and communicate
> it to the decompressor
>
> To test these changes, boot a multi_v7_defconfig+CONFIG_RANDOMIZE_BASE=y
I gave a quick try using your arm-kaslr-v3 branch, hopefully that's
the right one.
The good news is that now omap3 boots with omap2plus_defconfig with
and without CONFIG_RANDOMIZE_BASE=y and I did not see any compiler
errors with my gcc 6.2.0 like earlier :)
I did see boot attempts fail with randomize enable where no output
was produced. It seems this is happening for me maybe 1 out of 5 boots.
Enabling DEBUG_LL did not show anything either.
Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
$ sudo modprobe rtc-twl
rtc_twl: disagrees about version of symbol module_layout
modprobe: ERROR: could not insert 'rtc_twl': Exec format error
Regards,
Tony
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-05 16:45 ` Tony Lindgren
0 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-05 16:45 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, kernel-hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
Hi,
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170903 05:08]:
> 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 collect some pseudo-entropy, and randomize
> the physical offset of the decompressed kernel, taking placement of DTB,
> initrd and reserved regions into account
> - changes to the UEFI stub code to choose the KASLR offset and communicate
> it to the decompressor
>
> To test these changes, boot a multi_v7_defconfig+CONFIG_RANDOMIZE_BASE=y
I gave a quick try using your arm-kaslr-v3 branch, hopefully that's
the right one.
The good news is that now omap3 boots with omap2plus_defconfig with
and without CONFIG_RANDOMIZE_BASE=y and I did not see any compiler
errors with my gcc 6.2.0 like earlier :)
I did see boot attempts fail with randomize enable where no output
was produced. It seems this is happening for me maybe 1 out of 5 boots.
Enabling DEBUG_LL did not show anything either.
Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
$ sudo modprobe rtc-twl
rtc_twl: disagrees about version of symbol module_layout
modprobe: ERROR: could not insert 'rtc_twl': Exec format error
Regards,
Tony
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-05 16:45 ` [kernel-hardening] " Tony Lindgren
@ 2017-09-05 16:48 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-05 16:48 UTC (permalink / raw)
To: linux-arm-kernel
On 5 September 2017 at 17:45, Tony Lindgren <tony@atomide.com> wrote:
> Hi,
>
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170903 05:08]:
>> 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 collect some pseudo-entropy, and randomize
>> the physical offset of the decompressed kernel, taking placement of DTB,
>> initrd and reserved regions into account
>> - changes to the UEFI stub code to choose the KASLR offset and communicate
>> it to the decompressor
>>
>> To test these changes, boot a multi_v7_defconfig+CONFIG_RANDOMIZE_BASE=y
>
> I gave a quick try using your arm-kaslr-v3 branch, hopefully that's
> the right one.
>
> The good news is that now omap3 boots with omap2plus_defconfig with
> and without CONFIG_RANDOMIZE_BASE=y and I did not see any compiler
> errors with my gcc 6.2.0 like earlier :)
>
Good! Thanks a lot for taking the time to test this stuff.
> I did see boot attempts fail with randomize enable where no output
> was produced. It seems this is happening for me maybe 1 out of 5 boots.
> Enabling DEBUG_LL did not show anything either.
>
Yes. I am looking into a couple of kernelci boot reports that look
suspicious, but it is rather difficult to reproduce, for obvious
reasons :-)
Which hardware are you testing this on?
> Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
>
> $ sudo modprobe rtc-twl
> rtc_twl: disagrees about version of symbol module_layout
> modprobe: ERROR: could not insert 'rtc_twl': Exec format error
>
Is this with CONFIG_MODVERSIONS enabled?
Thanks,
Ard.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-05 16:48 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-05 16:48 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
On 5 September 2017 at 17:45, Tony Lindgren <tony@atomide.com> wrote:
> Hi,
>
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170903 05:08]:
>> 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 collect some pseudo-entropy, and randomize
>> the physical offset of the decompressed kernel, taking placement of DTB,
>> initrd and reserved regions into account
>> - changes to the UEFI stub code to choose the KASLR offset and communicate
>> it to the decompressor
>>
>> To test these changes, boot a multi_v7_defconfig+CONFIG_RANDOMIZE_BASE=y
>
> I gave a quick try using your arm-kaslr-v3 branch, hopefully that's
> the right one.
>
> The good news is that now omap3 boots with omap2plus_defconfig with
> and without CONFIG_RANDOMIZE_BASE=y and I did not see any compiler
> errors with my gcc 6.2.0 like earlier :)
>
Good! Thanks a lot for taking the time to test this stuff.
> I did see boot attempts fail with randomize enable where no output
> was produced. It seems this is happening for me maybe 1 out of 5 boots.
> Enabling DEBUG_LL did not show anything either.
>
Yes. I am looking into a couple of kernelci boot reports that look
suspicious, but it is rather difficult to reproduce, for obvious
reasons :-)
Which hardware are you testing this on?
> Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
>
> $ sudo modprobe rtc-twl
> rtc_twl: disagrees about version of symbol module_layout
> modprobe: ERROR: could not insert 'rtc_twl': Exec format error
>
Is this with CONFIG_MODVERSIONS enabled?
Thanks,
Ard.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-05 16:48 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-05 19:37 ` Tony Lindgren
-1 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-05 19:37 UTC (permalink / raw)
To: linux-arm-kernel
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 09:49]:
> On 5 September 2017 at 17:45, Tony Lindgren <tony@atomide.com> wrote:
> > I did see boot attempts fail with randomize enable where no output
> > was produced. It seems this is happening for me maybe 1 out of 5 boots.
> > Enabling DEBUG_LL did not show anything either.
> >
>
> Yes. I am looking into a couple of kernelci boot reports that look
> suspicious, but it is rather difficult to reproduce, for obvious
> reasons :-)
>
> Which hardware are you testing this on?
For testing on omap3, I'm mostly using logicpd torpedo devkit as
it works out of box with PM with mainline Linux and has NFSroot
usable too.
> > Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
> >
> > $ sudo modprobe rtc-twl
> > rtc_twl: disagrees about version of symbol module_layout
> > modprobe: ERROR: could not insert 'rtc_twl': Exec format error
> >
>
> Is this with CONFIG_MODVERSIONS enabled?
Yes, but disabling that did not seem to make any difference
based on just one test.
Regards,
Tony
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-05 19:37 ` Tony Lindgren
0 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-05 19:37 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 09:49]:
> On 5 September 2017 at 17:45, Tony Lindgren <tony@atomide.com> wrote:
> > I did see boot attempts fail with randomize enable where no output
> > was produced. It seems this is happening for me maybe 1 out of 5 boots.
> > Enabling DEBUG_LL did not show anything either.
> >
>
> Yes. I am looking into a couple of kernelci boot reports that look
> suspicious, but it is rather difficult to reproduce, for obvious
> reasons :-)
>
> Which hardware are you testing this on?
For testing on omap3, I'm mostly using logicpd torpedo devkit as
it works out of box with PM with mainline Linux and has NFSroot
usable too.
> > Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
> >
> > $ sudo modprobe rtc-twl
> > rtc_twl: disagrees about version of symbol module_layout
> > modprobe: ERROR: could not insert 'rtc_twl': Exec format error
> >
>
> Is this with CONFIG_MODVERSIONS enabled?
Yes, but disabling that did not seem to make any difference
based on just one test.
Regards,
Tony
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-05 19:37 ` [kernel-hardening] " Tony Lindgren
@ 2017-09-05 19:42 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-05 19:42 UTC (permalink / raw)
To: linux-arm-kernel
On 5 September 2017 at 20:37, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 09:49]:
>> On 5 September 2017 at 17:45, Tony Lindgren <tony@atomide.com> wrote:
>> > I did see boot attempts fail with randomize enable where no output
>> > was produced. It seems this is happening for me maybe 1 out of 5 boots.
>> > Enabling DEBUG_LL did not show anything either.
>> >
>>
>> Yes. I am looking into a couple of kernelci boot reports that look
>> suspicious, but it is rather difficult to reproduce, for obvious
>> reasons :-)
>>
>> Which hardware are you testing this on?
>
> For testing on omap3, I'm mostly using logicpd torpedo devkit as
> it works out of box with PM with mainline Linux and has NFSroot
> usable too.
>
Right. Well, I will try to reproduce with the BB white I have.
Are you booting with an initrd?
>> > Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
>> >
>> > $ sudo modprobe rtc-twl
>> > rtc_twl: disagrees about version of symbol module_layout
>> > modprobe: ERROR: could not insert 'rtc_twl': Exec format error
>> >
>>
>> Is this with CONFIG_MODVERSIONS enabled?
>
> Yes, but disabling that did not seem to make any difference
> based on just one test.
>
Yeah, well, it appears I missed a couple of details :-)
This should fix the module loading issues:
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1a0304dd388d..bbefd5f32ec2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1830,6 +1830,8 @@ config RANDOMIZE_BASE
depends on MMU && AUTO_ZRELADDR
depends on !XIP_KERNEL && !ZBOOT_ROM
select RELOCATABLE
+ select ARM_MODULE_PLTS if MODULES
+ select MODULE_REL_CRCS if MODVERSIONS
help
Randomizes the virtual and physical address at which the kernel
image is loaded, as a security feature that deters exploit attempts
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index f13ae153fb24..b56fc4dd27b6 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t;
#define R_ARM_NONE 0
#define R_ARM_PC24 1
#define R_ARM_ABS32 2
+#define R_ARM_REL32 3
#define R_ARM_CALL 28
#define R_ARM_JUMP24 29
#define R_ARM_TARGET1 38
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 3ff571c2c71c..aa4d72837cd5 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -175,6 +175,10 @@
*(u32 *)loc |= offset & 0x7fffffff;
break;
+ case R_ARM_REL32:
+ *(u32 *)loc += sym->st_value - loc;
+ break;
+
case R_ARM_MOVW_ABS_NC:
case R_ARM_MOVT_ABS:
offset = tmp = __mem_to_opcode_arm(*(u32 *)loc);
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-05 19:42 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-05 19:42 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
On 5 September 2017 at 20:37, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 09:49]:
>> On 5 September 2017 at 17:45, Tony Lindgren <tony@atomide.com> wrote:
>> > I did see boot attempts fail with randomize enable where no output
>> > was produced. It seems this is happening for me maybe 1 out of 5 boots.
>> > Enabling DEBUG_LL did not show anything either.
>> >
>>
>> Yes. I am looking into a couple of kernelci boot reports that look
>> suspicious, but it is rather difficult to reproduce, for obvious
>> reasons :-)
>>
>> Which hardware are you testing this on?
>
> For testing on omap3, I'm mostly using logicpd torpedo devkit as
> it works out of box with PM with mainline Linux and has NFSroot
> usable too.
>
Right. Well, I will try to reproduce with the BB white I have.
Are you booting with an initrd?
>> > Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
>> >
>> > $ sudo modprobe rtc-twl
>> > rtc_twl: disagrees about version of symbol module_layout
>> > modprobe: ERROR: could not insert 'rtc_twl': Exec format error
>> >
>>
>> Is this with CONFIG_MODVERSIONS enabled?
>
> Yes, but disabling that did not seem to make any difference
> based on just one test.
>
Yeah, well, it appears I missed a couple of details :-)
This should fix the module loading issues:
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1a0304dd388d..bbefd5f32ec2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1830,6 +1830,8 @@ config RANDOMIZE_BASE
depends on MMU && AUTO_ZRELADDR
depends on !XIP_KERNEL && !ZBOOT_ROM
select RELOCATABLE
+ select ARM_MODULE_PLTS if MODULES
+ select MODULE_REL_CRCS if MODVERSIONS
help
Randomizes the virtual and physical address at which the kernel
image is loaded, as a security feature that deters exploit attempts
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index f13ae153fb24..b56fc4dd27b6 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t;
#define R_ARM_NONE 0
#define R_ARM_PC24 1
#define R_ARM_ABS32 2
+#define R_ARM_REL32 3
#define R_ARM_CALL 28
#define R_ARM_JUMP24 29
#define R_ARM_TARGET1 38
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 3ff571c2c71c..aa4d72837cd5 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -175,6 +175,10 @@
*(u32 *)loc |= offset & 0x7fffffff;
break;
+ case R_ARM_REL32:
+ *(u32 *)loc += sym->st_value - loc;
+ break;
+
case R_ARM_MOVW_ABS_NC:
case R_ARM_MOVT_ABS:
offset = tmp = __mem_to_opcode_arm(*(u32 *)loc);
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-05 19:42 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-05 21:27 ` Tony Lindgren
-1 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-05 21:27 UTC (permalink / raw)
To: linux-arm-kernel
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 12:43]:
> Right. Well, I will try to reproduce with the BB white I have.
Yeah that should be reproducable, I got it to happen on BBB here
after about 5 boots.
> Are you booting with an initrd?
Not on this one, on beagleboard xm I do.
> >> > Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
> >> >
> >> > $ sudo modprobe rtc-twl
> >> > rtc_twl: disagrees about version of symbol module_layout
> >> > modprobe: ERROR: could not insert 'rtc_twl': Exec format error
> >> >
> >>
> >> Is this with CONFIG_MODVERSIONS enabled?
> >
> > Yes, but disabling that did not seem to make any difference
> > based on just one test.
> >
>
> Yeah, well, it appears I missed a couple of details :-)
>
> This should fix the module loading issues:
Yeah now modprobe works :) That's after manually applying
it as the tabs got munched in your patch somewhere, see below.
Regards,
Tony
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 1a0304dd388d..bbefd5f32ec2 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1830,6 +1830,8 @@ config RANDOMIZE_BASE
> depends on MMU && AUTO_ZRELADDR
> depends on !XIP_KERNEL && !ZBOOT_ROM
> select RELOCATABLE
> + select ARM_MODULE_PLTS if MODULES
> + select MODULE_REL_CRCS if MODVERSIONS
> help
> Randomizes the virtual and physical address at which the kernel
> image is loaded, as a security feature that deters exploit attempts
> diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
> index f13ae153fb24..b56fc4dd27b6 100644
> --- a/arch/arm/include/asm/elf.h
> +++ b/arch/arm/include/asm/elf.h
> @@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t;
> #define R_ARM_NONE 0
> #define R_ARM_PC24 1
> #define R_ARM_ABS32 2
> +#define R_ARM_REL32 3
> #define R_ARM_CALL 28
> #define R_ARM_JUMP24 29
> #define R_ARM_TARGET1 38
> diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
> index 3ff571c2c71c..aa4d72837cd5 100644
> --- a/arch/arm/kernel/module.c
> +++ b/arch/arm/kernel/module.c
> @@ -175,6 +175,10 @@
> *(u32 *)loc |= offset & 0x7fffffff;
> break;
>
> + case R_ARM_REL32:
> + *(u32 *)loc += sym->st_value - loc;
> + break;
> +
> case R_ARM_MOVW_ABS_NC:
> case R_ARM_MOVT_ABS:
> offset = tmp = __mem_to_opcode_arm(*(u32 *)loc);
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-05 21:27 ` Tony Lindgren
0 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-05 21:27 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 12:43]:
> Right. Well, I will try to reproduce with the BB white I have.
Yeah that should be reproducable, I got it to happen on BBB here
after about 5 boots.
> Are you booting with an initrd?
Not on this one, on beagleboard xm I do.
> >> > Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
> >> >
> >> > $ sudo modprobe rtc-twl
> >> > rtc_twl: disagrees about version of symbol module_layout
> >> > modprobe: ERROR: could not insert 'rtc_twl': Exec format error
> >> >
> >>
> >> Is this with CONFIG_MODVERSIONS enabled?
> >
> > Yes, but disabling that did not seem to make any difference
> > based on just one test.
> >
>
> Yeah, well, it appears I missed a couple of details :-)
>
> This should fix the module loading issues:
Yeah now modprobe works :) That's after manually applying
it as the tabs got munched in your patch somewhere, see below.
Regards,
Tony
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 1a0304dd388d..bbefd5f32ec2 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1830,6 +1830,8 @@ config RANDOMIZE_BASE
> depends on MMU && AUTO_ZRELADDR
> depends on !XIP_KERNEL && !ZBOOT_ROM
> select RELOCATABLE
> + select ARM_MODULE_PLTS if MODULES
> + select MODULE_REL_CRCS if MODVERSIONS
> help
> Randomizes the virtual and physical address at which the kernel
> image is loaded, as a security feature that deters exploit attempts
> diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
> index f13ae153fb24..b56fc4dd27b6 100644
> --- a/arch/arm/include/asm/elf.h
> +++ b/arch/arm/include/asm/elf.h
> @@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t;
> #define R_ARM_NONE 0
> #define R_ARM_PC24 1
> #define R_ARM_ABS32 2
> +#define R_ARM_REL32 3
> #define R_ARM_CALL 28
> #define R_ARM_JUMP24 29
> #define R_ARM_TARGET1 38
> diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
> index 3ff571c2c71c..aa4d72837cd5 100644
> --- a/arch/arm/kernel/module.c
> +++ b/arch/arm/kernel/module.c
> @@ -175,6 +175,10 @@
> *(u32 *)loc |= offset & 0x7fffffff;
> break;
>
> + case R_ARM_REL32:
> + *(u32 *)loc += sym->st_value - loc;
> + break;
> +
> case R_ARM_MOVW_ABS_NC:
> case R_ARM_MOVT_ABS:
> offset = tmp = __mem_to_opcode_arm(*(u32 *)loc);
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-05 21:27 ` [kernel-hardening] " Tony Lindgren
@ 2017-09-05 21:31 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-05 21:31 UTC (permalink / raw)
To: linux-arm-kernel
On 5 September 2017 at 22:27, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 12:43]:
>> Right. Well, I will try to reproduce with the BB white I have.
>
> Yeah that should be reproducable, I got it to happen on BBB here
> after about 5 boots.
>
>> Are you booting with an initrd?
>
> Not on this one, on beagleboard xm I do.
>
Interesting.
>> >> > Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
>> >> >
>> >> > $ sudo modprobe rtc-twl
>> >> > rtc_twl: disagrees about version of symbol module_layout
>> >> > modprobe: ERROR: could not insert 'rtc_twl': Exec format error
>> >> >
>> >>
>> >> Is this with CONFIG_MODVERSIONS enabled?
>> >
>> > Yes, but disabling that did not seem to make any difference
>> > based on just one test.
>> >
>>
>> Yeah, well, it appears I missed a couple of details :-)
>>
>> This should fix the module loading issues:
>
> Yeah now modprobe works :) That's after manually applying
> it as the tabs got munched in your patch somewhere, see below.
>
Yeah, Gmail tends to do that now and again. Apologies.
Thanks for confirming that the module loading works for you, I will
fold this into my v3.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-05 21:31 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-05 21:31 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
On 5 September 2017 at 22:27, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 12:43]:
>> Right. Well, I will try to reproduce with the BB white I have.
>
> Yeah that should be reproducable, I got it to happen on BBB here
> after about 5 boots.
>
>> Are you booting with an initrd?
>
> Not on this one, on beagleboard xm I do.
>
Interesting.
>> >> > Then loading modules with CONFIG_RANDOMIZE_BASE=y seems to fail with:
>> >> >
>> >> > $ sudo modprobe rtc-twl
>> >> > rtc_twl: disagrees about version of symbol module_layout
>> >> > modprobe: ERROR: could not insert 'rtc_twl': Exec format error
>> >> >
>> >>
>> >> Is this with CONFIG_MODVERSIONS enabled?
>> >
>> > Yes, but disabling that did not seem to make any difference
>> > based on just one test.
>> >
>>
>> Yeah, well, it appears I missed a couple of details :-)
>>
>> This should fix the module loading issues:
>
> Yeah now modprobe works :) That's after manually applying
> it as the tabs got munched in your patch somewhere, see below.
>
Yeah, Gmail tends to do that now and again. Apologies.
Thanks for confirming that the module loading works for you, I will
fold this into my v3.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-05 21:31 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-06 10:40 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 10:40 UTC (permalink / raw)
To: linux-arm-kernel
On 5 September 2017 at 22:31, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 5 September 2017 at 22:27, Tony Lindgren <tony@atomide.com> wrote:
>> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 12:43]:
>>> Right. Well, I will try to reproduce with the BB white I have.
>>
>> Yeah that should be reproducable, I got it to happen on BBB here
>> after about 5 boots.
>>
Unfortunately, my BB white boots happily every time.
I have added DEBUG_UNCOMPRESS support to mach-omap2, and added some
debug output to the kaslr init routine
For example,
Starting kernel ...
regions.image_size:00e00000
regions.pa_start:80000000
regions.pa_end:90000000
regions.zimage_start:80200000
regions.zimage_size:00430228
regions.dtb_start:82000000
regions.dtb_size:00009000
num:00000016
*kaslr_offset:04400000
Uncompressing Linux... done, booting the kernel.
[ 0.000000] Booting Linux on physical CPU 0x0
....
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0xd0000000 - 0xff800000 ( 760 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xcfe00000 ( 254 MB)
[ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
[ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
[ 0.000000] .text : 0xc4408000 - 0xc4d00000 (9184 kB)
[ 0.000000] .init : 0xc5000000 - 0xc5100000 (1024 kB)
[ 0.000000] .data : 0xc5100000 - 0xc5149df0 ( 296 kB)
[ 0.000000] .bss : 0xc51cb000 - 0xc59a9a8c (8059 kB)
I have pushed the changes to my arm-kaslr-v3 branch. If you are
willing to spend more cycles on this, could you please run it with
DEBUG_LL enabled, and capture the output of the failed boots?
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 10:40 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 10:40 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
On 5 September 2017 at 22:31, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 5 September 2017 at 22:27, Tony Lindgren <tony@atomide.com> wrote:
>> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 12:43]:
>>> Right. Well, I will try to reproduce with the BB white I have.
>>
>> Yeah that should be reproducable, I got it to happen on BBB here
>> after about 5 boots.
>>
Unfortunately, my BB white boots happily every time.
I have added DEBUG_UNCOMPRESS support to mach-omap2, and added some
debug output to the kaslr init routine
For example,
Starting kernel ...
regions.image_size:00e00000
regions.pa_start:80000000
regions.pa_end:90000000
regions.zimage_start:80200000
regions.zimage_size:00430228
regions.dtb_start:82000000
regions.dtb_size:00009000
num:00000016
*kaslr_offset:04400000
Uncompressing Linux... done, booting the kernel.
[ 0.000000] Booting Linux on physical CPU 0x0
....
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0xd0000000 - 0xff800000 ( 760 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xcfe00000 ( 254 MB)
[ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
[ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
[ 0.000000] .text : 0xc4408000 - 0xc4d00000 (9184 kB)
[ 0.000000] .init : 0xc5000000 - 0xc5100000 (1024 kB)
[ 0.000000] .data : 0xc5100000 - 0xc5149df0 ( 296 kB)
[ 0.000000] .bss : 0xc51cb000 - 0xc59a9a8c (8059 kB)
I have pushed the changes to my arm-kaslr-v3 branch. If you are
willing to spend more cycles on this, could you please run it with
DEBUG_LL enabled, and capture the output of the failed boots?
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 10:40 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-06 16:22 ` Tony Lindgren
-1 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 16:22 UTC (permalink / raw)
To: linux-arm-kernel
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 03:41]:
> On 5 September 2017 at 22:31, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > On 5 September 2017 at 22:27, Tony Lindgren <tony@atomide.com> wrote:
> >> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 12:43]:
> >>> Right. Well, I will try to reproduce with the BB white I have.
> >>
> >> Yeah that should be reproducable, I got it to happen on BBB here
> >> after about 5 boots.
> >>
>
> Unfortunately, my BB white boots happily every time.
>
> I have added DEBUG_UNCOMPRESS support to mach-omap2, and added some
> debug output to the kaslr init routine
OK. FYI, the DEBUG_UNCOMPRESS support works in Linux next as
it's now using the generic 8250 debug_ll code.
> For example,
>
> Starting kernel ...
>
> regions.image_size:00e00000
> regions.pa_start:80000000
> regions.pa_end:90000000
> regions.zimage_start:80200000
> regions.zimage_size:00430228
> regions.dtb_start:82000000
> regions.dtb_size:00009000
> num:00000016
> *kaslr_offset:04400000
> Uncompressing Linux... done, booting the kernel.
> [ 0.000000] Booting Linux on physical CPU 0x0
> ....
> [ 0.000000] Virtual kernel memory layout:
> [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
> [ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
> [ 0.000000] vmalloc : 0xd0000000 - 0xff800000 ( 760 MB)
> [ 0.000000] lowmem : 0xc0000000 - 0xcfe00000 ( 254 MB)
> [ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
> [ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
> [ 0.000000] .text : 0xc4408000 - 0xc4d00000 (9184 kB)
> [ 0.000000] .init : 0xc5000000 - 0xc5100000 (1024 kB)
> [ 0.000000] .data : 0xc5100000 - 0xc5149df0 ( 296 kB)
> [ 0.000000] .bss : 0xc51cb000 - 0xc59a9a8c (8059 kB)
>
> I have pushed the changes to my arm-kaslr-v3 branch. If you are
> willing to spend more cycles on this, could you please run it with
> DEBUG_LL enabled, and capture the output of the failed boots?
Sure was not able to reproduce it so far on BBB. But here's
failed boot output from logicpd-torpedo-37xx-devkit. Will
try some more booting on BBB too.
Regards,
Tony
8< -------------------
Kernel image @ 0x81000000 [ 0x000000 - 0x426810 ]
## Flattened Device Tree blob at 84000000
Booting using the fdt blob@0x84000000
Loading Device Tree to 86feb000, end 86fff2d5 ... OK
Starting kernel ...
regions.image_size:00e00000
regions.pa_start:80000000
regions.pa_end:88000000
regions.zimage_start:81000000
regions.zimage_size:00437830
regions.dtb_start:86feb000
regions.dtb_size:00012000
regions.initrd_start:00000000
regions.initrd_size:00000000
num:0000002f
num:00000029
*kaslr_offset:07400000
Uncompressing Linux...
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 16:22 ` Tony Lindgren
0 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 16:22 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 03:41]:
> On 5 September 2017 at 22:31, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > On 5 September 2017 at 22:27, Tony Lindgren <tony@atomide.com> wrote:
> >> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 12:43]:
> >>> Right. Well, I will try to reproduce with the BB white I have.
> >>
> >> Yeah that should be reproducable, I got it to happen on BBB here
> >> after about 5 boots.
> >>
>
> Unfortunately, my BB white boots happily every time.
>
> I have added DEBUG_UNCOMPRESS support to mach-omap2, and added some
> debug output to the kaslr init routine
OK. FYI, the DEBUG_UNCOMPRESS support works in Linux next as
it's now using the generic 8250 debug_ll code.
> For example,
>
> Starting kernel ...
>
> regions.image_size:00e00000
> regions.pa_start:80000000
> regions.pa_end:90000000
> regions.zimage_start:80200000
> regions.zimage_size:00430228
> regions.dtb_start:82000000
> regions.dtb_size:00009000
> num:00000016
> *kaslr_offset:04400000
> Uncompressing Linux... done, booting the kernel.
> [ 0.000000] Booting Linux on physical CPU 0x0
> ....
> [ 0.000000] Virtual kernel memory layout:
> [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
> [ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
> [ 0.000000] vmalloc : 0xd0000000 - 0xff800000 ( 760 MB)
> [ 0.000000] lowmem : 0xc0000000 - 0xcfe00000 ( 254 MB)
> [ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
> [ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
> [ 0.000000] .text : 0xc4408000 - 0xc4d00000 (9184 kB)
> [ 0.000000] .init : 0xc5000000 - 0xc5100000 (1024 kB)
> [ 0.000000] .data : 0xc5100000 - 0xc5149df0 ( 296 kB)
> [ 0.000000] .bss : 0xc51cb000 - 0xc59a9a8c (8059 kB)
>
> I have pushed the changes to my arm-kaslr-v3 branch. If you are
> willing to spend more cycles on this, could you please run it with
> DEBUG_LL enabled, and capture the output of the failed boots?
Sure was not able to reproduce it so far on BBB. But here's
failed boot output from logicpd-torpedo-37xx-devkit. Will
try some more booting on BBB too.
Regards,
Tony
8< -------------------
Kernel image @ 0x81000000 [ 0x000000 - 0x426810 ]
## Flattened Device Tree blob at 84000000
Booting using the fdt blob at 0x84000000
Loading Device Tree to 86feb000, end 86fff2d5 ... OK
Starting kernel ...
regions.image_size:00e00000
regions.pa_start:80000000
regions.pa_end:88000000
regions.zimage_start:81000000
regions.zimage_size:00437830
regions.dtb_start:86feb000
regions.dtb_size:00012000
regions.initrd_start:00000000
regions.initrd_size:00000000
num:0000002f
num:00000029
*kaslr_offset:07400000
Uncompressing Linux...
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 16:22 ` [kernel-hardening] " Tony Lindgren
@ 2017-09-06 16:25 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 16:25 UTC (permalink / raw)
To: linux-arm-kernel
On 6 September 2017 at 17:22, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 03:41]:
>> On 5 September 2017 at 22:31, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> > On 5 September 2017 at 22:27, Tony Lindgren <tony@atomide.com> wrote:
>> >> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 12:43]:
>> >>> Right. Well, I will try to reproduce with the BB white I have.
>> >>
>> >> Yeah that should be reproducable, I got it to happen on BBB here
>> >> after about 5 boots.
>> >>
>>
>> Unfortunately, my BB white boots happily every time.
>>
>> I have added DEBUG_UNCOMPRESS support to mach-omap2, and added some
>> debug output to the kaslr init routine
>
> OK. FYI, the DEBUG_UNCOMPRESS support works in Linux next as
> it's now using the generic 8250 debug_ll code.
>
>> For example,
>>
>> Starting kernel ...
>>
>> regions.image_size:00e00000
>> regions.pa_start:80000000
>> regions.pa_end:90000000
>> regions.zimage_start:80200000
>> regions.zimage_size:00430228
>> regions.dtb_start:82000000
>> regions.dtb_size:00009000
>> num:00000016
>> *kaslr_offset:04400000
>> Uncompressing Linux... done, booting the kernel.
>> [ 0.000000] Booting Linux on physical CPU 0x0
>> ....
>> [ 0.000000] Virtual kernel memory layout:
>> [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
>> [ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
>> [ 0.000000] vmalloc : 0xd0000000 - 0xff800000 ( 760 MB)
>> [ 0.000000] lowmem : 0xc0000000 - 0xcfe00000 ( 254 MB)
>> [ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
>> [ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
>> [ 0.000000] .text : 0xc4408000 - 0xc4d00000 (9184 kB)
>> [ 0.000000] .init : 0xc5000000 - 0xc5100000 (1024 kB)
>> [ 0.000000] .data : 0xc5100000 - 0xc5149df0 ( 296 kB)
>> [ 0.000000] .bss : 0xc51cb000 - 0xc59a9a8c (8059 kB)
>>
>> I have pushed the changes to my arm-kaslr-v3 branch. If you are
>> willing to spend more cycles on this, could you please run it with
>> DEBUG_LL enabled, and capture the output of the failed boots?
>
> Sure was not able to reproduce it so far on BBB. But here's
> failed boot output from logicpd-torpedo-37xx-devkit. Will
> try some more booting on BBB too.
>
Thanks Tony.
> 8< -------------------
> Kernel image @ 0x81000000 [ 0x000000 - 0x426810 ]
> ## Flattened Device Tree blob at 84000000
> Booting using the fdt blob at 0x84000000
> Loading Device Tree to 86feb000, end 86fff2d5 ... OK
>
> Starting kernel ...
>
> regions.image_size:00e00000
> regions.pa_start:80000000
> regions.pa_end:88000000
> regions.zimage_start:81000000
> regions.zimage_size:00437830
> regions.dtb_start:86feb000
> regions.dtb_size:00012000
> regions.initrd_start:00000000
> regions.initrd_size:00000000
> num:0000002f
> num:00000029
> *kaslr_offset:07400000
> Uncompressing Linux...
Is that all? Does it hang while decompressing the kernel?
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 16:25 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 16:25 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
On 6 September 2017 at 17:22, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 03:41]:
>> On 5 September 2017 at 22:31, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> > On 5 September 2017 at 22:27, Tony Lindgren <tony@atomide.com> wrote:
>> >> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170905 12:43]:
>> >>> Right. Well, I will try to reproduce with the BB white I have.
>> >>
>> >> Yeah that should be reproducable, I got it to happen on BBB here
>> >> after about 5 boots.
>> >>
>>
>> Unfortunately, my BB white boots happily every time.
>>
>> I have added DEBUG_UNCOMPRESS support to mach-omap2, and added some
>> debug output to the kaslr init routine
>
> OK. FYI, the DEBUG_UNCOMPRESS support works in Linux next as
> it's now using the generic 8250 debug_ll code.
>
>> For example,
>>
>> Starting kernel ...
>>
>> regions.image_size:00e00000
>> regions.pa_start:80000000
>> regions.pa_end:90000000
>> regions.zimage_start:80200000
>> regions.zimage_size:00430228
>> regions.dtb_start:82000000
>> regions.dtb_size:00009000
>> num:00000016
>> *kaslr_offset:04400000
>> Uncompressing Linux... done, booting the kernel.
>> [ 0.000000] Booting Linux on physical CPU 0x0
>> ....
>> [ 0.000000] Virtual kernel memory layout:
>> [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
>> [ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
>> [ 0.000000] vmalloc : 0xd0000000 - 0xff800000 ( 760 MB)
>> [ 0.000000] lowmem : 0xc0000000 - 0xcfe00000 ( 254 MB)
>> [ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
>> [ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
>> [ 0.000000] .text : 0xc4408000 - 0xc4d00000 (9184 kB)
>> [ 0.000000] .init : 0xc5000000 - 0xc5100000 (1024 kB)
>> [ 0.000000] .data : 0xc5100000 - 0xc5149df0 ( 296 kB)
>> [ 0.000000] .bss : 0xc51cb000 - 0xc59a9a8c (8059 kB)
>>
>> I have pushed the changes to my arm-kaslr-v3 branch. If you are
>> willing to spend more cycles on this, could you please run it with
>> DEBUG_LL enabled, and capture the output of the failed boots?
>
> Sure was not able to reproduce it so far on BBB. But here's
> failed boot output from logicpd-torpedo-37xx-devkit. Will
> try some more booting on BBB too.
>
Thanks Tony.
> 8< -------------------
> Kernel image @ 0x81000000 [ 0x000000 - 0x426810 ]
> ## Flattened Device Tree blob at 84000000
> Booting using the fdt blob at 0x84000000
> Loading Device Tree to 86feb000, end 86fff2d5 ... OK
>
> Starting kernel ...
>
> regions.image_size:00e00000
> regions.pa_start:80000000
> regions.pa_end:88000000
> regions.zimage_start:81000000
> regions.zimage_size:00437830
> regions.dtb_start:86feb000
> regions.dtb_size:00012000
> regions.initrd_start:00000000
> regions.initrd_size:00000000
> num:0000002f
> num:00000029
> *kaslr_offset:07400000
> Uncompressing Linux...
Is that all? Does it hang while decompressing the kernel?
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 16:25 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-06 16:31 ` Tony Lindgren
-1 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 16:31 UTC (permalink / raw)
To: linux-arm-kernel
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 09:26]:
> On 6 September 2017 at 17:22, Tony Lindgren <tony@atomide.com> wrote:
> > Sure was not able to reproduce it so far on BBB. But here's
> > failed boot output from logicpd-torpedo-37xx-devkit. Will
> > try some more booting on BBB too.
...
> > 8< -------------------
> > Kernel image @ 0x81000000 [ 0x000000 - 0x426810 ]
> > ## Flattened Device Tree blob at 84000000
> > Booting using the fdt blob at 0x84000000
> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
> >
> > Starting kernel ...
> >
> > regions.image_size:00e00000
> > regions.pa_start:80000000
> > regions.pa_end:88000000
> > regions.zimage_start:81000000
> > regions.zimage_size:00437830
> > regions.dtb_start:86feb000
> > regions.dtb_size:00012000
> > regions.initrd_start:00000000
> > regions.initrd_size:00000000
> > num:0000002f
> > num:00000029
> > *kaslr_offset:07400000
> > Uncompressing Linux...
>
> Is that all? Does it hang while decompressing the kernel?
Yeah so it seems. If we had uncompress overwriting something
because of the increase in size it should happen on every
boot though, not once every five boots or so.
Regards,
TOny
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 16:31 ` Tony Lindgren
0 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 16:31 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 09:26]:
> On 6 September 2017 at 17:22, Tony Lindgren <tony@atomide.com> wrote:
> > Sure was not able to reproduce it so far on BBB. But here's
> > failed boot output from logicpd-torpedo-37xx-devkit. Will
> > try some more booting on BBB too.
...
> > 8< -------------------
> > Kernel image @ 0x81000000 [ 0x000000 - 0x426810 ]
> > ## Flattened Device Tree blob at 84000000
> > Booting using the fdt blob at 0x84000000
> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
> >
> > Starting kernel ...
> >
> > regions.image_size:00e00000
> > regions.pa_start:80000000
> > regions.pa_end:88000000
> > regions.zimage_start:81000000
> > regions.zimage_size:00437830
> > regions.dtb_start:86feb000
> > regions.dtb_size:00012000
> > regions.initrd_start:00000000
> > regions.initrd_size:00000000
> > num:0000002f
> > num:00000029
> > *kaslr_offset:07400000
> > Uncompressing Linux...
>
> Is that all? Does it hang while decompressing the kernel?
Yeah so it seems. If we had uncompress overwriting something
because of the increase in size it should happen on every
boot though, not once every five boots or so.
Regards,
TOny
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 16:31 ` [kernel-hardening] " Tony Lindgren
@ 2017-09-06 16:35 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 16:35 UTC (permalink / raw)
To: linux-arm-kernel
On 6 September 2017 at 17:31, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 09:26]:
>> On 6 September 2017 at 17:22, Tony Lindgren <tony@atomide.com> wrote:
>> > Sure was not able to reproduce it so far on BBB. But here's
>> > failed boot output from logicpd-torpedo-37xx-devkit. Will
>> > try some more booting on BBB too.
> ...
>> > 8< -------------------
>> > Kernel image @ 0x81000000 [ 0x000000 - 0x426810 ]
>> > ## Flattened Device Tree blob at 84000000
>> > Booting using the fdt blob at 0x84000000
>> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
>> >
>> > Starting kernel ...
>> >
>> > regions.image_size:00e00000
>> > regions.pa_start:80000000
>> > regions.pa_end:88000000
>> > regions.zimage_start:81000000
>> > regions.zimage_size:00437830
>> > regions.dtb_start:86feb000
>> > regions.dtb_size:00012000
>> > regions.initrd_start:00000000
>> > regions.initrd_size:00000000
>> > num:0000002f
>> > num:00000029
>> > *kaslr_offset:07400000
>> > Uncompressing Linux...
>>
>> Is that all? Does it hang while decompressing the kernel?
>
> Yeah so it seems. If we had uncompress overwriting something
> because of the increase in size it should happen on every
> boot though, not once every five boots or so.
>
Turns out I am calculating the top of DRAM incorrectly for boards
where less memory is present than the size of the lowmem region.
Could you try this please? (Apologies for the whitespace)
diff --git a/arch/arm/boot/compressed/kaslr.c b/arch/arm/boot/compressed/kaslr.c
index d43c0be9b47b..e9c86809c857 100644
--- a/arch/arm/boot/compressed/kaslr.c
+++ b/arch/arm/boot/compressed/kaslr.c
@@ -339,8 +339,7 @@ u32 kaslr_early_init(u32 *kaslr_offset, u32
image_base, u32 image_size,
regions.image_size = round_up(image_size, SZ_2M);
regions.pa_start = round_down(image_base, SZ_128M);
- regions.pa_end = lowmem_top - PAGE_OFFSET + regions.pa_start -
- regions.image_size;
+ regions.pa_end = lowmem_top - PAGE_OFFSET + regions.pa_start;
regions.zimage_start = zimage_start;
regions.zimage_size = zimage_end - zimage_start;
regions.dtb_start = (u32)fdt;
@@ -391,7 +390,8 @@ u32 kaslr_early_init(u32 *kaslr_offset, u32
image_base, u32 image_size,
}
/* check the memory nodes for the size of the lowmem region */
- regions.pa_end = min(regions.pa_end, get_memory_end(fdt));
+ regions.pa_end = min(regions.pa_end, get_memory_end(fdt)) -
+ regions.image_size;
puthex32(regions.image_size);
puthex32(regions.pa_start);
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 16:35 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 16:35 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
On 6 September 2017 at 17:31, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 09:26]:
>> On 6 September 2017 at 17:22, Tony Lindgren <tony@atomide.com> wrote:
>> > Sure was not able to reproduce it so far on BBB. But here's
>> > failed boot output from logicpd-torpedo-37xx-devkit. Will
>> > try some more booting on BBB too.
> ...
>> > 8< -------------------
>> > Kernel image @ 0x81000000 [ 0x000000 - 0x426810 ]
>> > ## Flattened Device Tree blob at 84000000
>> > Booting using the fdt blob at 0x84000000
>> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
>> >
>> > Starting kernel ...
>> >
>> > regions.image_size:00e00000
>> > regions.pa_start:80000000
>> > regions.pa_end:88000000
>> > regions.zimage_start:81000000
>> > regions.zimage_size:00437830
>> > regions.dtb_start:86feb000
>> > regions.dtb_size:00012000
>> > regions.initrd_start:00000000
>> > regions.initrd_size:00000000
>> > num:0000002f
>> > num:00000029
>> > *kaslr_offset:07400000
>> > Uncompressing Linux...
>>
>> Is that all? Does it hang while decompressing the kernel?
>
> Yeah so it seems. If we had uncompress overwriting something
> because of the increase in size it should happen on every
> boot though, not once every five boots or so.
>
Turns out I am calculating the top of DRAM incorrectly for boards
where less memory is present than the size of the lowmem region.
Could you try this please? (Apologies for the whitespace)
diff --git a/arch/arm/boot/compressed/kaslr.c b/arch/arm/boot/compressed/kaslr.c
index d43c0be9b47b..e9c86809c857 100644
--- a/arch/arm/boot/compressed/kaslr.c
+++ b/arch/arm/boot/compressed/kaslr.c
@@ -339,8 +339,7 @@ u32 kaslr_early_init(u32 *kaslr_offset, u32
image_base, u32 image_size,
regions.image_size = round_up(image_size, SZ_2M);
regions.pa_start = round_down(image_base, SZ_128M);
- regions.pa_end = lowmem_top - PAGE_OFFSET + regions.pa_start -
- regions.image_size;
+ regions.pa_end = lowmem_top - PAGE_OFFSET + regions.pa_start;
regions.zimage_start = zimage_start;
regions.zimage_size = zimage_end - zimage_start;
regions.dtb_start = (u32)fdt;
@@ -391,7 +390,8 @@ u32 kaslr_early_init(u32 *kaslr_offset, u32
image_base, u32 image_size,
}
/* check the memory nodes for the size of the lowmem region */
- regions.pa_end = min(regions.pa_end, get_memory_end(fdt));
+ regions.pa_end = min(regions.pa_end, get_memory_end(fdt)) -
+ regions.image_size;
puthex32(regions.image_size);
puthex32(regions.pa_start);
^ permalink raw reply related [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 16:35 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-06 17:12 ` Tony Lindgren
-1 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 17:12 UTC (permalink / raw)
To: linux-arm-kernel
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 09:36]:
> Turns out I am calculating the top of DRAM incorrectly for boards
> where less memory is present than the size of the lowmem region.
>
> Could you try this please? (Apologies for the whitespace)
I think for 10 or so units per year you can actually buy
a non-mangling outgoing SMTP service if nothing else helps..
Anyways, you patch manually applied fixed most of the random
boot hangs for me, but I did see a new one after 11 boot
attempts, see below.
Regards,
Tony
8< --------------
Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
## Flattened Device Tree blob at 84000000
Booting using the fdt blob@0x84000000
Loading Device Tree to 86feb000, end 86fff2d5 ... OK
Starting kernel ...
regions.image_size:00e00000
regions.pa_start:80000000
regions.pa_end:87200000
regions.zimage_start:81000000
regions.zimage_size:00437320
regions.dtb_start:86feb000
regions.dtb_size:00012000
regions.initrd_start:00000000
regions.initrd_size:00000000
num:00000028
num:00000025
*kaslr_offset:05e00000
Uncompressing Linux... done, booting the kernel.
Warning: Neither atags nor dtb found
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 17:12 ` Tony Lindgren
0 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 17:12 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 09:36]:
> Turns out I am calculating the top of DRAM incorrectly for boards
> where less memory is present than the size of the lowmem region.
>
> Could you try this please? (Apologies for the whitespace)
I think for 10 or so units per year you can actually buy
a non-mangling outgoing SMTP service if nothing else helps..
Anyways, you patch manually applied fixed most of the random
boot hangs for me, but I did see a new one after 11 boot
attempts, see below.
Regards,
Tony
8< --------------
Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
## Flattened Device Tree blob at 84000000
Booting using the fdt blob at 0x84000000
Loading Device Tree to 86feb000, end 86fff2d5 ... OK
Starting kernel ...
regions.image_size:00e00000
regions.pa_start:80000000
regions.pa_end:87200000
regions.zimage_start:81000000
regions.zimage_size:00437320
regions.dtb_start:86feb000
regions.dtb_size:00012000
regions.initrd_start:00000000
regions.initrd_size:00000000
num:00000028
num:00000025
*kaslr_offset:05e00000
Uncompressing Linux... done, booting the kernel.
Warning: Neither atags nor dtb found
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 17:12 ` [kernel-hardening] " Tony Lindgren
@ 2017-09-06 17:30 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 17:30 UTC (permalink / raw)
To: linux-arm-kernel
On 6 September 2017 at 18:12, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 09:36]:
>> Turns out I am calculating the top of DRAM incorrectly for boards
>> where less memory is present than the size of the lowmem region.
>>
>> Could you try this please? (Apologies for the whitespace)
>
> I think for 10 or so units per year you can actually buy
> a non-mangling outgoing SMTP service if nothing else helps..
>
Yeah, you're right, apologies. I use git-send-email mostly, but not
for inline snippets like this. And it is not actually the SMTP service
but the web client that mangles the whitespace
> Anyways, you patch manually applied fixed most of the random
> boot hangs for me, but I did see a new one after 11 boot
> attempts, see below.
>
> Regards,
>
> Tony
>
> 8< --------------
> Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
> ## Flattened Device Tree blob at 84000000
> Booting using the fdt blob at 0x84000000
> Loading Device Tree to 86feb000, end 86fff2d5 ... OK
>
> Starting kernel ...
>
> regions.image_size:00e00000
> regions.pa_start:80000000
> regions.pa_end:87200000
> regions.zimage_start:81000000
> regions.zimage_size:00437320
> regions.dtb_start:86feb000
> regions.dtb_size:00012000
> regions.initrd_start:00000000
> regions.initrd_size:00000000
> num:00000028
> num:00000025
> *kaslr_offset:05e00000
> Uncompressing Linux... done, booting the kernel.
> Warning: Neither atags nor dtb found
OK, so in this case, 80000000 + 00e00000 + 05e00000 == 86c00000, which
is still below the DTB, but apparently, it has corrupted it anyway.
I will try to figure out what's going on here.
Thanks again for taking the time,
Ard.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 17:30 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 17:30 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
On 6 September 2017 at 18:12, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 09:36]:
>> Turns out I am calculating the top of DRAM incorrectly for boards
>> where less memory is present than the size of the lowmem region.
>>
>> Could you try this please? (Apologies for the whitespace)
>
> I think for 10 or so units per year you can actually buy
> a non-mangling outgoing SMTP service if nothing else helps..
>
Yeah, you're right, apologies. I use git-send-email mostly, but not
for inline snippets like this. And it is not actually the SMTP service
but the web client that mangles the whitespace
> Anyways, you patch manually applied fixed most of the random
> boot hangs for me, but I did see a new one after 11 boot
> attempts, see below.
>
> Regards,
>
> Tony
>
> 8< --------------
> Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
> ## Flattened Device Tree blob at 84000000
> Booting using the fdt blob at 0x84000000
> Loading Device Tree to 86feb000, end 86fff2d5 ... OK
>
> Starting kernel ...
>
> regions.image_size:00e00000
> regions.pa_start:80000000
> regions.pa_end:87200000
> regions.zimage_start:81000000
> regions.zimage_size:00437320
> regions.dtb_start:86feb000
> regions.dtb_size:00012000
> regions.initrd_start:00000000
> regions.initrd_size:00000000
> num:00000028
> num:00000025
> *kaslr_offset:05e00000
> Uncompressing Linux... done, booting the kernel.
> Warning: Neither atags nor dtb found
OK, so in this case, 80000000 + 00e00000 + 05e00000 == 86c00000, which
is still below the DTB, but apparently, it has corrupted it anyway.
I will try to figure out what's going on here.
Thanks again for taking the time,
Ard.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 17:30 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-06 17:53 ` Tony Lindgren
-1 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 17:53 UTC (permalink / raw)
To: linux-arm-kernel
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 10:31]:
> On 6 September 2017 at 18:12, Tony Lindgren <tony@atomide.com> wrote:
> > Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
> > ## Flattened Device Tree blob at 84000000
> > Booting using the fdt blob at 0x84000000
> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
> >
> > Starting kernel ...
> >
> > regions.image_size:00e00000
> > regions.pa_start:80000000
> > regions.pa_end:87200000
> > regions.zimage_start:81000000
> > regions.zimage_size:00437320
> > regions.dtb_start:86feb000
> > regions.dtb_size:00012000
> > regions.initrd_start:00000000
> > regions.initrd_size:00000000
> > num:00000028
> > num:00000025
> > *kaslr_offset:05e00000
> > Uncompressing Linux... done, booting the kernel.
> > Warning: Neither atags nor dtb found
>
> OK, so in this case, 80000000 + 00e00000 + 05e00000 == 86c00000, which
> is still below the DTB, but apparently, it has corrupted it anyway.
>
> I will try to figure out what's going on here.
Do you need to have kaslr_offset beyond the uncompressed
kernel size maybe?
> Thanks again for taking the time,
No problem, I'm happy to test these changes.
Regards,
Tony
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 17:53 ` Tony Lindgren
0 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 17:53 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 10:31]:
> On 6 September 2017 at 18:12, Tony Lindgren <tony@atomide.com> wrote:
> > Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
> > ## Flattened Device Tree blob at 84000000
> > Booting using the fdt blob at 0x84000000
> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
> >
> > Starting kernel ...
> >
> > regions.image_size:00e00000
> > regions.pa_start:80000000
> > regions.pa_end:87200000
> > regions.zimage_start:81000000
> > regions.zimage_size:00437320
> > regions.dtb_start:86feb000
> > regions.dtb_size:00012000
> > regions.initrd_start:00000000
> > regions.initrd_size:00000000
> > num:00000028
> > num:00000025
> > *kaslr_offset:05e00000
> > Uncompressing Linux... done, booting the kernel.
> > Warning: Neither atags nor dtb found
>
> OK, so in this case, 80000000 + 00e00000 + 05e00000 == 86c00000, which
> is still below the DTB, but apparently, it has corrupted it anyway.
>
> I will try to figure out what's going on here.
Do you need to have kaslr_offset beyond the uncompressed
kernel size maybe?
> Thanks again for taking the time,
No problem, I'm happy to test these changes.
Regards,
Tony
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 17:53 ` [kernel-hardening] " Tony Lindgren
@ 2017-09-06 18:04 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 18:04 UTC (permalink / raw)
To: linux-arm-kernel
On 6 September 2017 at 18:53, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 10:31]:
>> On 6 September 2017 at 18:12, Tony Lindgren <tony@atomide.com> wrote:
>> > Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
>> > ## Flattened Device Tree blob at 84000000
>> > Booting using the fdt blob at 0x84000000
>> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
>> >
>> > Starting kernel ...
>> >
>> > regions.image_size:00e00000
>> > regions.pa_start:80000000
>> > regions.pa_end:87200000
>> > regions.zimage_start:81000000
>> > regions.zimage_size:00437320
>> > regions.dtb_start:86feb000
>> > regions.dtb_size:00012000
>> > regions.initrd_start:00000000
>> > regions.initrd_size:00000000
>> > num:00000028
>> > num:00000025
>> > *kaslr_offset:05e00000
>> > Uncompressing Linux... done, booting the kernel.
>> > Warning: Neither atags nor dtb found
>>
>> OK, so in this case, 80000000 + 00e00000 + 05e00000 == 86c00000, which
>> is still below the DTB, but apparently, it has corrupted it anyway.
>>
>> I will try to figure out what's going on here.
>
> Do you need to have kaslr_offset beyond the uncompressed
> kernel size maybe?
>
I think the problem is in the rounding of region.pa_start.
I have now changed this to
regions.image_size = image_base % SZ_128M + round_up(image_size, SZ_2M);
regions.pa_start = round_down(image_base, SZ_128M);
>> Thanks again for taking the time,
>
> No problem, I'm happy to test these changes.
>
I have updated my arm-kaslr-v3 with all the fixes from this discussion
(and more)
Thanks,
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 18:04 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 18:04 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
On 6 September 2017 at 18:53, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 10:31]:
>> On 6 September 2017 at 18:12, Tony Lindgren <tony@atomide.com> wrote:
>> > Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
>> > ## Flattened Device Tree blob at 84000000
>> > Booting using the fdt blob at 0x84000000
>> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
>> >
>> > Starting kernel ...
>> >
>> > regions.image_size:00e00000
>> > regions.pa_start:80000000
>> > regions.pa_end:87200000
>> > regions.zimage_start:81000000
>> > regions.zimage_size:00437320
>> > regions.dtb_start:86feb000
>> > regions.dtb_size:00012000
>> > regions.initrd_start:00000000
>> > regions.initrd_size:00000000
>> > num:00000028
>> > num:00000025
>> > *kaslr_offset:05e00000
>> > Uncompressing Linux... done, booting the kernel.
>> > Warning: Neither atags nor dtb found
>>
>> OK, so in this case, 80000000 + 00e00000 + 05e00000 == 86c00000, which
>> is still below the DTB, but apparently, it has corrupted it anyway.
>>
>> I will try to figure out what's going on here.
>
> Do you need to have kaslr_offset beyond the uncompressed
> kernel size maybe?
>
I think the problem is in the rounding of region.pa_start.
I have now changed this to
regions.image_size = image_base % SZ_128M + round_up(image_size, SZ_2M);
regions.pa_start = round_down(image_base, SZ_128M);
>> Thanks again for taking the time,
>
> No problem, I'm happy to test these changes.
>
I have updated my arm-kaslr-v3 with all the fixes from this discussion
(and more)
Thanks,
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 18:04 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-06 18:22 ` Tony Lindgren
-1 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 18:22 UTC (permalink / raw)
To: linux-arm-kernel
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 11:05]:
> On 6 September 2017 at 18:53, Tony Lindgren <tony@atomide.com> wrote:
> > * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 10:31]:
> >> On 6 September 2017 at 18:12, Tony Lindgren <tony@atomide.com> wrote:
> >> > Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
> >> > ## Flattened Device Tree blob at 84000000
> >> > Booting using the fdt blob at 0x84000000
> >> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
> >> >
> >> > Starting kernel ...
> >> >
> >> > regions.image_size:00e00000
> >> > regions.pa_start:80000000
> >> > regions.pa_end:87200000
> >> > regions.zimage_start:81000000
> >> > regions.zimage_size:00437320
> >> > regions.dtb_start:86feb000
> >> > regions.dtb_size:00012000
> >> > regions.initrd_start:00000000
> >> > regions.initrd_size:00000000
> >> > num:00000028
> >> > num:00000025
> >> > *kaslr_offset:05e00000
> >> > Uncompressing Linux... done, booting the kernel.
> >> > Warning: Neither atags nor dtb found
> >>
> >> OK, so in this case, 80000000 + 00e00000 + 05e00000 == 86c00000, which
> >> is still below the DTB, but apparently, it has corrupted it anyway.
> >>
> >> I will try to figure out what's going on here.
> >
> > Do you need to have kaslr_offset beyond the uncompressed
> > kernel size maybe?
> >
>
> I think the problem is in the rounding of region.pa_start.
>
> I have now changed this to
>
> regions.image_size = image_base % SZ_128M + round_up(image_size, SZ_2M);
> regions.pa_start = round_down(image_base, SZ_128M);
...
> I have updated my arm-kaslr-v3 with all the fixes from this discussion
> (and more)
Looks like your branch at commit 5221c86ad2e7 still failed
after boot attempt #4, see below. Is that the right commit?
Regards,
Tony
8< -----------------
regions.zimage_size:004379e8
regions.dtb_start:86feb000
regions.dtb_size:00012000
regions.initrd_start:00000000
regions.initrd_size:00000000
count:00000028
num:00000025
*kaslr_offset:05e00000
Uncompressing Linux... done, booting the kernel.
Warning: Neither atags nor dtb found
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 18:22 ` Tony Lindgren
0 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 18:22 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 11:05]:
> On 6 September 2017 at 18:53, Tony Lindgren <tony@atomide.com> wrote:
> > * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 10:31]:
> >> On 6 September 2017 at 18:12, Tony Lindgren <tony@atomide.com> wrote:
> >> > Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
> >> > ## Flattened Device Tree blob at 84000000
> >> > Booting using the fdt blob at 0x84000000
> >> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
> >> >
> >> > Starting kernel ...
> >> >
> >> > regions.image_size:00e00000
> >> > regions.pa_start:80000000
> >> > regions.pa_end:87200000
> >> > regions.zimage_start:81000000
> >> > regions.zimage_size:00437320
> >> > regions.dtb_start:86feb000
> >> > regions.dtb_size:00012000
> >> > regions.initrd_start:00000000
> >> > regions.initrd_size:00000000
> >> > num:00000028
> >> > num:00000025
> >> > *kaslr_offset:05e00000
> >> > Uncompressing Linux... done, booting the kernel.
> >> > Warning: Neither atags nor dtb found
> >>
> >> OK, so in this case, 80000000 + 00e00000 + 05e00000 == 86c00000, which
> >> is still below the DTB, but apparently, it has corrupted it anyway.
> >>
> >> I will try to figure out what's going on here.
> >
> > Do you need to have kaslr_offset beyond the uncompressed
> > kernel size maybe?
> >
>
> I think the problem is in the rounding of region.pa_start.
>
> I have now changed this to
>
> regions.image_size = image_base % SZ_128M + round_up(image_size, SZ_2M);
> regions.pa_start = round_down(image_base, SZ_128M);
...
> I have updated my arm-kaslr-v3 with all the fixes from this discussion
> (and more)
Looks like your branch at commit 5221c86ad2e7 still failed
after boot attempt #4, see below. Is that the right commit?
Regards,
Tony
8< -----------------
regions.zimage_size:004379e8
regions.dtb_start:86feb000
regions.dtb_size:00012000
regions.initrd_start:00000000
regions.initrd_size:00000000
count:00000028
num:00000025
*kaslr_offset:05e00000
Uncompressing Linux... done, booting the kernel.
Warning: Neither atags nor dtb found
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 18:22 ` [kernel-hardening] " Tony Lindgren
@ 2017-09-06 18:25 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 18:25 UTC (permalink / raw)
To: linux-arm-kernel
On 6 September 2017 at 19:22, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 11:05]:
>> On 6 September 2017 at 18:53, Tony Lindgren <tony@atomide.com> wrote:
>> > * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 10:31]:
>> >> On 6 September 2017 at 18:12, Tony Lindgren <tony@atomide.com> wrote:
>> >> > Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
>> >> > ## Flattened Device Tree blob at 84000000
>> >> > Booting using the fdt blob at 0x84000000
>> >> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
>> >> >
>> >> > Starting kernel ...
>> >> >
>> >> > regions.image_size:00e00000
>> >> > regions.pa_start:80000000
>> >> > regions.pa_end:87200000
>> >> > regions.zimage_start:81000000
>> >> > regions.zimage_size:00437320
>> >> > regions.dtb_start:86feb000
>> >> > regions.dtb_size:00012000
>> >> > regions.initrd_start:00000000
>> >> > regions.initrd_size:00000000
>> >> > num:00000028
>> >> > num:00000025
>> >> > *kaslr_offset:05e00000
>> >> > Uncompressing Linux... done, booting the kernel.
>> >> > Warning: Neither atags nor dtb found
>> >>
>> >> OK, so in this case, 80000000 + 00e00000 + 05e00000 == 86c00000, which
>> >> is still below the DTB, but apparently, it has corrupted it anyway.
>> >>
>> >> I will try to figure out what's going on here.
>> >
>> > Do you need to have kaslr_offset beyond the uncompressed
>> > kernel size maybe?
>> >
>>
>> I think the problem is in the rounding of region.pa_start.
>>
>> I have now changed this to
>>
>> regions.image_size = image_base % SZ_128M + round_up(image_size, SZ_2M);
>> regions.pa_start = round_down(image_base, SZ_128M);
> ...
>
>> I have updated my arm-kaslr-v3 with all the fixes from this discussion
>> (and more)
>
> Looks like your branch at commit 5221c86ad2e7 still failed
> after boot attempt #4, see below. Is that the right commit?
>
It should be, yes.
> 8< -----------------
> regions.zimage_size:004379e8
> regions.dtb_start:86feb000
> regions.dtb_size:00012000
> regions.initrd_start:00000000
> regions.initrd_size:00000000
> count:00000028
> num:00000025
> *kaslr_offset:05e00000
> Uncompressing Linux... done, booting the kernel.
> Warning: Neither atags nor dtb found
Did you capture the image_size and pa_start/pa_end as well?
In any case, this is the exact same offset that failed before, so the
rounding of pa_start wasn't the problem.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 18:25 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-06 18:25 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
On 6 September 2017 at 19:22, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 11:05]:
>> On 6 September 2017 at 18:53, Tony Lindgren <tony@atomide.com> wrote:
>> > * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 10:31]:
>> >> On 6 September 2017 at 18:12, Tony Lindgren <tony@atomide.com> wrote:
>> >> > Kernel image @ 0x81000000 [ 0x000000 - 0x426300 ]
>> >> > ## Flattened Device Tree blob at 84000000
>> >> > Booting using the fdt blob at 0x84000000
>> >> > Loading Device Tree to 86feb000, end 86fff2d5 ... OK
>> >> >
>> >> > Starting kernel ...
>> >> >
>> >> > regions.image_size:00e00000
>> >> > regions.pa_start:80000000
>> >> > regions.pa_end:87200000
>> >> > regions.zimage_start:81000000
>> >> > regions.zimage_size:00437320
>> >> > regions.dtb_start:86feb000
>> >> > regions.dtb_size:00012000
>> >> > regions.initrd_start:00000000
>> >> > regions.initrd_size:00000000
>> >> > num:00000028
>> >> > num:00000025
>> >> > *kaslr_offset:05e00000
>> >> > Uncompressing Linux... done, booting the kernel.
>> >> > Warning: Neither atags nor dtb found
>> >>
>> >> OK, so in this case, 80000000 + 00e00000 + 05e00000 == 86c00000, which
>> >> is still below the DTB, but apparently, it has corrupted it anyway.
>> >>
>> >> I will try to figure out what's going on here.
>> >
>> > Do you need to have kaslr_offset beyond the uncompressed
>> > kernel size maybe?
>> >
>>
>> I think the problem is in the rounding of region.pa_start.
>>
>> I have now changed this to
>>
>> regions.image_size = image_base % SZ_128M + round_up(image_size, SZ_2M);
>> regions.pa_start = round_down(image_base, SZ_128M);
> ...
>
>> I have updated my arm-kaslr-v3 with all the fixes from this discussion
>> (and more)
>
> Looks like your branch at commit 5221c86ad2e7 still failed
> after boot attempt #4, see below. Is that the right commit?
>
It should be, yes.
> 8< -----------------
> regions.zimage_size:004379e8
> regions.dtb_start:86feb000
> regions.dtb_size:00012000
> regions.initrd_start:00000000
> regions.initrd_size:00000000
> count:00000028
> num:00000025
> *kaslr_offset:05e00000
> Uncompressing Linux... done, booting the kernel.
> Warning: Neither atags nor dtb found
Did you capture the image_size and pa_start/pa_end as well?
In any case, this is the exact same offset that failed before, so the
rounding of pa_start wasn't the problem.
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 18:25 ` [kernel-hardening] " Ard Biesheuvel
@ 2017-09-06 20:08 ` Tony Lindgren
-1 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 20:08 UTC (permalink / raw)
To: linux-arm-kernel
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 11:25]:
> Did you capture the image_size and pa_start/pa_end as well?
Sorry I guess that was an incomplete copy & paste, but here's
another one:
regions.image_size:00e08000
regions.pa_start:80000000
regions.pa_end:871f8000
regions.zimage_start:81000000
regions.zimage_size:004379e8
regions.dtb_start:86feb000
regions.dtb_size:00012000
regions.initrd_start:00000000
regions.initrd_size:00000000
count:00000028
num:00000025
*kaslr_offset:05e00000
Uncompressing Linux... done, booting the kernel.
Warning: Neither atags nor dtb found
> In any case, this is the exact same offset that failed before, so the
> rounding of pa_start wasn't the problem.
OK
Regards,
Tony
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-06 20:08 ` Tony Lindgren
0 siblings, 0 replies; 166+ messages in thread
From: Tony Lindgren @ 2017-09-06 20:08 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
* Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 11:25]:
> Did you capture the image_size and pa_start/pa_end as well?
Sorry I guess that was an incomplete copy & paste, but here's
another one:
regions.image_size:00e08000
regions.pa_start:80000000
regions.pa_end:871f8000
regions.zimage_start:81000000
regions.zimage_size:004379e8
regions.dtb_start:86feb000
regions.dtb_size:00012000
regions.initrd_start:00000000
regions.initrd_size:00000000
count:00000028
num:00000025
*kaslr_offset:05e00000
Uncompressing Linux... done, booting the kernel.
Warning: Neither atags nor dtb found
> In any case, this is the exact same offset that failed before, so the
> rounding of pa_start wasn't the problem.
OK
Regards,
Tony
^ permalink raw reply [flat|nested] 166+ messages in thread
* [PATCH v2 00/29] implement KASLR for ARM
2017-09-06 20:08 ` [kernel-hardening] " Tony Lindgren
@ 2017-09-12 6:51 ` Ard Biesheuvel
-1 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-12 6:51 UTC (permalink / raw)
To: linux-arm-kernel
On 6 September 2017 at 21:08, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 11:25]:
>> Did you capture the image_size and pa_start/pa_end as well?
>
> Sorry I guess that was an incomplete copy & paste, but here's
> another one:
>
> regions.image_size:00e08000
> regions.pa_start:80000000
> regions.pa_end:871f8000
> regions.zimage_start:81000000
> regions.zimage_size:004379e8
> regions.dtb_start:86feb000
> regions.dtb_size:00012000
> regions.initrd_start:00000000
> regions.initrd_size:00000000
> count:00000028
> num:00000025
> *kaslr_offset:05e00000
> Uncompressing Linux... done, booting the kernel.
> Warning: Neither atags nor dtb found
>
>> In any case, this is the exact same offset that failed before, so the
>> rounding of pa_start wasn't the problem.
>
> OK
>
I am pretty sure this is an issue with .bss, which is not covered by
image_size (and which is absolutely *huge* btw [8+ MB] on
omap2plus_defconfig, due to lockdep being enabled by default)
^ permalink raw reply [flat|nested] 166+ messages in thread
* [kernel-hardening] Re: [PATCH v2 00/29] implement KASLR for ARM
@ 2017-09-12 6:51 ` Ard Biesheuvel
0 siblings, 0 replies; 166+ messages in thread
From: Ard Biesheuvel @ 2017-09-12 6:51 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-arm-kernel, Kernel Hardening, Arnd Bergmann, Nicolas Pitre,
Russell King, Kees Cook, Thomas Garnier, Marc Zyngier,
Mark Rutland, Matt Fleming, Dave Martin
On 6 September 2017 at 21:08, Tony Lindgren <tony@atomide.com> wrote:
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> [170906 11:25]:
>> Did you capture the image_size and pa_start/pa_end as well?
>
> Sorry I guess that was an incomplete copy & paste, but here's
> another one:
>
> regions.image_size:00e08000
> regions.pa_start:80000000
> regions.pa_end:871f8000
> regions.zimage_start:81000000
> regions.zimage_size:004379e8
> regions.dtb_start:86feb000
> regions.dtb_size:00012000
> regions.initrd_start:00000000
> regions.initrd_size:00000000
> count:00000028
> num:00000025
> *kaslr_offset:05e00000
> Uncompressing Linux... done, booting the kernel.
> Warning: Neither atags nor dtb found
>
>> In any case, this is the exact same offset that failed before, so the
>> rounding of pa_start wasn't the problem.
>
> OK
>
I am pretty sure this is an issue with .bss, which is not covered by
image_size (and which is absolutely *huge* btw [8+ MB] on
omap2plus_defconfig, due to lockdep being enabled by default)
^ permalink raw reply [flat|nested] 166+ messages in thread
end of thread, other threads:[~2017-09-12 6:51 UTC | newest]
Thread overview: 166+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-03 12:07 [PATCH v2 00/29] implement KASLR for ARM Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 01/29] net/core: work around section mismatch warning for ptp_classifier Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 02/29] asm-generic: add .data.rel.ro sections to __ro_after_init Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 15:59 ` Nicolas Pitre
2017-09-04 15:59 ` [kernel-hardening] " Nicolas Pitre
2017-09-04 17:09 ` Kees Cook
2017-09-04 17:09 ` [kernel-hardening] " Kees Cook
2017-09-03 12:07 ` [PATCH v2 03/29] ARM: assembler: introduce adr_l, ldr_l and str_l macros Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:05 ` Nicolas Pitre
2017-09-04 16:05 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 04/29] ARM: head-common.S: use PC-relative insn sequence for __proc_info Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:06 ` Nicolas Pitre
2017-09-04 16:06 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 05/29] ARM: head-common.S: use PC-relative insn sequence for idmap creation Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:08 ` Nicolas Pitre
2017-09-04 16:08 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 06/29] ARM: head.S: use PC-relative insn sequence for secondary_data Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:09 ` Nicolas Pitre
2017-09-04 16:09 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 07/29] ARM: kernel: use relative references for UP/SMP alternatives Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:15 ` Nicolas Pitre
2017-09-04 16:15 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 08/29] ARM: head: use PC-relative insn sequence for __smp_alt Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:19 ` Nicolas Pitre
2017-09-04 16:19 ` [kernel-hardening] " Nicolas Pitre
2017-09-04 16:20 ` Ard Biesheuvel
2017-09-04 16:20 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 09/29] ARM: sleep.S: use PC-relative insn sequence for sleep_save_sp/mpidr_hash Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:20 ` Nicolas Pitre
2017-09-04 16:20 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 10/29] ARM: head.S: use PC-relative insn sequences for __fixup_pv_table Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:47 ` Nicolas Pitre
2017-09-04 16:47 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 11/29] ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:50 ` Nicolas Pitre
2017-09-04 16:50 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 12/29] ARM: kvm: replace open coded VA->PA calculations with adr_l call Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:57 ` Nicolas Pitre
2017-09-04 16:57 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 13/29] arm-soc: exynos: replace open coded VA->PA conversions Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 16:59 ` Nicolas Pitre
2017-09-04 16:59 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 14/29] arm-soc: mvebu: replace open coded VA->PA conversion Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 17:00 ` Nicolas Pitre
2017-09-04 17:00 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 15/29] arm-soc: various: replace open coded VA->PA calculation of pen_release Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 17:01 ` Nicolas Pitre
2017-09-04 17:01 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 16/29] ARM: kernel: switch to relative exception tables Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 17:17 ` Nicolas Pitre
2017-09-04 17:17 ` [kernel-hardening] " Nicolas Pitre
2017-09-04 17:30 ` Ard Biesheuvel
2017-09-04 17:30 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 17/29] ARM: kernel: use relative phys-to-virt patch tables Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 18:03 ` Nicolas Pitre
2017-09-04 18:03 ` [kernel-hardening] " Nicolas Pitre
2017-09-04 19:09 ` Ard Biesheuvel
2017-09-04 19:09 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 18/29] arm-soc: tegra: make sleep asm code runtime relocatable Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 19/29] ARM: kernel: make vmlinux buildable as a PIE executable Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 18:11 ` Nicolas Pitre
2017-09-04 18:11 ` [kernel-hardening] " Nicolas Pitre
2017-09-04 19:10 ` Ard Biesheuvel
2017-09-04 19:10 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 20/29] ARM: kernel: use PC-relative symbol references in MMU switch code Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 18:15 ` Nicolas Pitre
2017-09-04 18:15 ` [kernel-hardening] " Nicolas Pitre
2017-09-04 19:14 ` Ard Biesheuvel
2017-09-04 19:14 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 21/29] ARM: kernel: use PC relative symbol references in suspend/resume code Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 18:24 ` Nicolas Pitre
2017-09-04 18:24 ` [kernel-hardening] " Nicolas Pitre
2017-09-04 19:17 ` Ard Biesheuvel
2017-09-04 19:17 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 22/29] ARM: mm: export default vmalloc base address Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 18:25 ` Nicolas Pitre
2017-09-04 18:25 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 23/29] ARM: kernel: refer to swapper_pg_dir via its symbol Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 18:30 ` Nicolas Pitre
2017-09-04 18:30 ` [kernel-hardening] " Nicolas Pitre
2017-09-04 19:26 ` Ard Biesheuvel
2017-09-04 19:26 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 24/29] ARM: kernel: implement randomization of the kernel load address Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 18:44 ` Nicolas Pitre
2017-09-04 18:44 ` [kernel-hardening] " Nicolas Pitre
2017-09-04 19:29 ` Ard Biesheuvel
2017-09-04 19:29 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 25/29] ARM: decompressor: explicitly map decompressor binary cacheable Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 18:47 ` Nicolas Pitre
2017-09-04 18:47 ` [kernel-hardening] " Nicolas Pitre
2017-09-03 12:07 ` [PATCH v2 26/29] ARM: decompressor: add KASLR support Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-04 18:53 ` Nicolas Pitre
2017-09-04 18:53 ` [kernel-hardening] " Nicolas Pitre
2017-09-04 19:33 ` Ard Biesheuvel
2017-09-04 19:33 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 27/29] efi/libstub: add 'max' parameter to efi_random_alloc() Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 28/29] efi/libstub: check for vmalloc= command line argument Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-03 12:07 ` [PATCH v2 29/29] efi/libstub: arm: implement KASLR Ard Biesheuvel
2017-09-03 12:07 ` [kernel-hardening] " Ard Biesheuvel
2017-09-05 16:45 ` [PATCH v2 00/29] implement KASLR for ARM Tony Lindgren
2017-09-05 16:45 ` [kernel-hardening] " Tony Lindgren
2017-09-05 16:48 ` Ard Biesheuvel
2017-09-05 16:48 ` [kernel-hardening] " Ard Biesheuvel
2017-09-05 19:37 ` Tony Lindgren
2017-09-05 19:37 ` [kernel-hardening] " Tony Lindgren
2017-09-05 19:42 ` Ard Biesheuvel
2017-09-05 19:42 ` [kernel-hardening] " Ard Biesheuvel
2017-09-05 21:27 ` Tony Lindgren
2017-09-05 21:27 ` [kernel-hardening] " Tony Lindgren
2017-09-05 21:31 ` Ard Biesheuvel
2017-09-05 21:31 ` [kernel-hardening] " Ard Biesheuvel
2017-09-06 10:40 ` Ard Biesheuvel
2017-09-06 10:40 ` [kernel-hardening] " Ard Biesheuvel
2017-09-06 16:22 ` Tony Lindgren
2017-09-06 16:22 ` [kernel-hardening] " Tony Lindgren
2017-09-06 16:25 ` Ard Biesheuvel
2017-09-06 16:25 ` [kernel-hardening] " Ard Biesheuvel
2017-09-06 16:31 ` Tony Lindgren
2017-09-06 16:31 ` [kernel-hardening] " Tony Lindgren
2017-09-06 16:35 ` Ard Biesheuvel
2017-09-06 16:35 ` [kernel-hardening] " Ard Biesheuvel
2017-09-06 17:12 ` Tony Lindgren
2017-09-06 17:12 ` [kernel-hardening] " Tony Lindgren
2017-09-06 17:30 ` Ard Biesheuvel
2017-09-06 17:30 ` [kernel-hardening] " Ard Biesheuvel
2017-09-06 17:53 ` Tony Lindgren
2017-09-06 17:53 ` [kernel-hardening] " Tony Lindgren
2017-09-06 18:04 ` Ard Biesheuvel
2017-09-06 18:04 ` [kernel-hardening] " Ard Biesheuvel
2017-09-06 18:22 ` Tony Lindgren
2017-09-06 18:22 ` [kernel-hardening] " Tony Lindgren
2017-09-06 18:25 ` Ard Biesheuvel
2017-09-06 18:25 ` [kernel-hardening] " Ard Biesheuvel
2017-09-06 20:08 ` Tony Lindgren
2017-09-06 20:08 ` [kernel-hardening] " Tony Lindgren
2017-09-12 6:51 ` Ard Biesheuvel
2017-09-12 6:51 ` [kernel-hardening] " Ard Biesheuvel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.