From 3ea86495aef2f6de26b7cb1599ba350dd6a0c521 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 23 Jul 2018 10:57:30 +0900 Subject: efi/arm: preserve early mapping of UEFI memory map longer for BGRT The BGRT code validates the contents of the table against the UEFI memory map, and so it expects it to be mapped when the code runs. On ARM, this is currently not the case, since we tear down the early mapping after efi_init() completes, and only create the permanent mapping in arm_enable_runtime_services(), which executes as an early initcall, but still leaves a window where the UEFI memory map is not mapped. So move the call to efi_memmap_unmap() from efi_init() to arm_enable_runtime_services(). Signed-off-by: Ard Biesheuvel [will: fold in EFI_MEMMAP attribute check from Ard] Signed-off-by: Will Deacon --- drivers/firmware/efi/arm-init.c | 1 - drivers/firmware/efi/arm-runtime.c | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index b5214c143fee..388a929baf95 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -259,7 +259,6 @@ void __init efi_init(void) reserve_regions(); efi_esrt_init(); - efi_memmap_unmap(); memblock_reserve(params.mmap & PAGE_MASK, PAGE_ALIGN(params.mmap_size + diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 5889cbea60b8..4712445c3213 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -110,11 +110,13 @@ static int __init arm_enable_runtime_services(void) { u64 mapsize; - if (!efi_enabled(EFI_BOOT)) { + if (!efi_enabled(EFI_BOOT) || !efi_enabled(EFI_MEMMAP)) { pr_info("EFI services will not be available.\n"); return 0; } + efi_memmap_unmap(); + if (efi_runtime_disabled()) { pr_info("EFI runtime services will be disabled.\n"); return 0; -- cgit v1.2.3 From 20d12cf990618845e76d3f24daaebd15d65a5e46 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Mon, 23 Jul 2018 10:57:31 +0900 Subject: efi/arm: map UEFI memory map even w/o runtime services enabled Under the current implementation, UEFI memory map will be mapped and made available in virtual mappings only if runtime services are enabled. But in a later patch, we want to use UEFI memory map in acpi_os_ioremap() to create mappings of ACPI tables using memory attributes described in UEFI memory map. See the following commit: arm64: acpi: fix alignment fault in accessing ACPI tables So, as a first step, arm_enter_runtime_services() is modified, alongside Ard's patch[1], so that UEFI memory map will not be freed even if efi=noruntime. [1] https://marc.info/?l=linux-efi&m=152930773507524&w=2 Signed-off-by: AKASHI Takahiro Reviewed-by: Ard Biesheuvel Signed-off-by: Will Deacon --- drivers/firmware/efi/arm-runtime.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 4712445c3213..922cfb813109 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -117,6 +117,13 @@ static int __init arm_enable_runtime_services(void) efi_memmap_unmap(); + mapsize = efi.memmap.desc_size * efi.memmap.nr_map; + + if (efi_memmap_init_late(efi.memmap.phys_map, mapsize)) { + pr_err("Failed to remap EFI memory map\n"); + return 0; + } + if (efi_runtime_disabled()) { pr_info("EFI runtime services will be disabled.\n"); return 0; @@ -129,13 +136,6 @@ static int __init arm_enable_runtime_services(void) pr_info("Remapping and enabling EFI services.\n"); - mapsize = efi.memmap.desc_size * efi.memmap.nr_map; - - if (efi_memmap_init_late(efi.memmap.phys_map, mapsize)) { - pr_err("Failed to remap EFI memory map\n"); - return -ENOMEM; - } - if (!efi_virtmap_init()) { pr_err("UEFI virtual mapping missing or invalid -- runtime services will not be available\n"); return -ENOMEM; -- cgit v1.2.3 From 0b3e336601b82c6afa0e9cf21db9cb8793e25399 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Fri, 20 Jul 2018 14:41:54 -0700 Subject: arm64: Add support for STACKLEAK gcc plugin This adds support for the STACKLEAK gcc plugin to arm64 by implementing stackleak_check_alloca(), based heavily on the x86 version, and adding the two helpers used by the stackleak common code: current_top_of_stack() and on_thread_stack(). The stack erasure calls are made at syscall returns. Additionally, this disables the plugin in hypervisor and EFI stub code, which are out of scope for the protection. Acked-by: Alexander Popov Reviewed-by: Mark Rutland Reviewed-by: Kees Cook Signed-off-by: Laura Abbott Signed-off-by: Will Deacon --- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/processor.h | 15 +++++++++++++++ arch/arm64/kernel/entry.S | 3 +++ arch/arm64/kernel/process.c | 22 ++++++++++++++++++++++ arch/arm64/kvm/hyp/Makefile | 3 ++- drivers/firmware/efi/libstub/Makefile | 3 ++- 6 files changed, 45 insertions(+), 2 deletions(-) (limited to 'drivers/firmware') diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 27fd50e86dfe..1494d5cfd681 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -108,6 +108,7 @@ config ARM64 select HAVE_ARCH_MMAP_RND_BITS select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT select HAVE_ARCH_SECCOMP_FILTER + select HAVE_ARCH_STACKLEAK select HAVE_ARCH_THREAD_STRUCT_WHITELIST select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRANSPARENT_HUGEPAGE diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index e02612105d78..79657ad91397 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -266,5 +266,20 @@ extern void __init minsigstksz_setup(void); #define SVE_SET_VL(arg) sve_set_current_vl(arg) #define SVE_GET_VL() sve_get_current_vl() +/* + * For CONFIG_GCC_PLUGIN_STACKLEAK + * + * These need to be macros because otherwise we get stuck in a nightmare + * of header definitions for the use of task_stack_page. + */ + +#define current_top_of_stack() \ +({ \ + struct stack_info _info; \ + BUG_ON(!on_accessible_stack(current, current_stack_pointer, &_info)); \ + _info.high; \ +}) +#define on_thread_stack() (on_task_stack(current, current_stack_pointer, NULL)) + #endif /* __ASSEMBLY__ */ #endif /* __ASM_PROCESSOR_H */ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index d1440f84668b..09dbea221a27 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -902,6 +902,9 @@ ret_to_user: cbnz x2, work_pending finish_ret_to_user: enable_step_tsk x1, x2 +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK + bl stackleak_erase +#endif kernel_exit 0 ENDPROC(ret_to_user) diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 740b31f77ade..7f1628effe6d 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -493,3 +493,25 @@ void arch_setup_new_exec(void) { current->mm->context.flags = is_compat_task() ? MMCF_AARCH32 : 0; } + +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK +void __used stackleak_check_alloca(unsigned long size) +{ + unsigned long stack_left; + unsigned long current_sp = current_stack_pointer; + struct stack_info info; + + BUG_ON(!on_accessible_stack(current, current_sp, &info)); + + stack_left = current_sp - info.low; + + /* + * There's a good chance we're almost out of stack space if this + * is true. Using panic() over BUG() is more likely to give + * reliable debugging output. + */ + if (size >= stack_left) + panic("alloca() over the kernel stack boundary\n"); +} +EXPORT_SYMBOL(stackleak_check_alloca); +#endif diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 4313f7475333..2fabc2dc1966 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -3,7 +3,8 @@ # Makefile for Kernel-based Virtual Machine module, HYP part # -ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING +ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING \ + $(DISABLE_STACKLEAK_PLUGIN) KVM=../../../../virt/kvm diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index a34e9290a699..25dd2a14560d 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -20,7 +20,8 @@ cflags-$(CONFIG_EFI_ARMSTUB) += -I$(srctree)/scripts/dtc/libfdt KBUILD_CFLAGS := $(cflags-y) -DDISABLE_BRANCH_PROFILING \ -D__NO_FORTIFY \ $(call cc-option,-ffreestanding) \ - $(call cc-option,-fno-stack-protector) + $(call cc-option,-fno-stack-protector) \ + $(DISABLE_STACKLEAK_PLUGIN) GCOV_PROFILE := n KASAN_SANITIZE := n -- cgit v1.2.3 From ce279d374ff315264efcbcef75cc21b9fef8b36f Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 30 Jul 2018 11:31:18 -0700 Subject: efi/libstub: Only disable stackleak plugin for arm64 arm64 uses the full KBUILD_CFLAGS for building libstub as opposed to x86 which doesn't. This means that x86 doesn't pick up the gcc-plugins. We need to disable the stackleak plugin but doing this unconditionally breaks x86 build since it doesn't have any plugins. Switch to disabling the stackleak plugin for arm64 only. Reviewed-by: Kees Cook Signed-off-by: Laura Abbott Signed-off-by: Will Deacon --- drivers/firmware/efi/libstub/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 25dd2a14560d..88c322d7c71e 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -11,7 +11,10 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -O2 \ -fPIC -fno-strict-aliasing -mno-red-zone \ -mno-mmx -mno-sse -fshort-wchar -cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) -fpie +# arm64 uses the full KBUILD_CFLAGS so it's necessary to explicitly +# disable the stackleak plugin +cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) -fpie \ + $(DISABLE_STACKLEAK_PLUGIN) cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \ -fno-builtin -fpic -mno-single-pic-base @@ -21,7 +24,6 @@ KBUILD_CFLAGS := $(cflags-y) -DDISABLE_BRANCH_PROFILING \ -D__NO_FORTIFY \ $(call cc-option,-ffreestanding) \ $(call cc-option,-fno-stack-protector) \ - $(DISABLE_STACKLEAK_PLUGIN) GCOV_PROFILE := n KASAN_SANITIZE := n -- cgit v1.2.3