arm64: Add support for STACKLEAK gcc plugin
PATCH 1/1 arm64: Add support for STACKLEAK gcc plugin
From: Laura Abbott <[email protected]>
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.
---
This is tweaked to be stand-alone from Alexander's series so it can land via the arm64 tree. (Alexander's v14 pulled one change out already, and I've lifted the last remaining: the newly needed include in stackleak.h)
--- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/processor.h | 10 ++++++++++ arch/arm64/kernel/entry.S | 7 +++++++ arch/arm64/kernel/process.c | 16 ++++++++++++++++ arch/arm64/kvm/hyp/Makefile | 3 ++- drivers/firmware/efi/libstub/Makefile | 3 ++- 6 files changed, 38 insertions(+), 2 deletions(-)
arch/arm64/Kconfig +1 -0
@@ -96,6 +96,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
arch/arm64/include/asm/processor.h +10 -0
@@ -266,5 +266,15 @@ 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 the STACKLEAK gcc plugin. +* +* 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 () ((unsigned long)task_stack_page(current) + \ + THREAD_SIZE) +#define on_thread_stack () (on_task_stack(current, current_stack_pointer)) +#endif /* __ASSEMBLY__ */ #endif /* __ASM_PROCESSOR_H */
arch/arm64/kernel/entry.S +7 -0
@@ -431,6 +431,11 @@ tsk .req x28 // current thread_info .text + .macro stackleak_erase +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK + bl stackleak_erase_kstack +#endif + .endm /* * Exception vectors. */
@@ -910,6 +915,7 @@ ret_fast_syscall: and x2, x1, #_TIF_WORK_MASK cbnz x2, work_pending enable_step_tsk x1, x2 + stackleak_erase kernel_exit 0 ret_fast_syscall_trace: enable_daif
@@ -936,6 +942,7 @@ ret_to_user: cbnz x2, work_pending finish_ret_to_user: enable_step_tsk x1, x2 + stackleak_erase kernel_exit 0 ENDPROC(ret_to_user)
arch/arm64/kernel/process.c +16 -0
@@ -493,3 +493,19 @@ void arch_setup_new_exec(void) { current->mm->context.flags =is_compat_task () ?MMCF_AARCH32 :0 ; } + +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK +#define MIN_STACK_LEFT 256 + +void __used stackleak_check_alloca (unsigned long size) +{ +unsigned long sp, stack_left; + + sp = current_stack_pointer; + + stack_left = sp & (THREAD_SIZE -1 ); +BUG_ON (stack_left <MIN_STACK_LEFT || + size >= stack_left -MIN_STACK_LEFT ); +} +EXPORT_SYMBOL (stackleak_check_alloca); +#endif
arch/arm64/kvm/hyp/Makefile +2 -1
@@ -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
drivers/firmware/efi/libstub/Makefile +2 -1
@@ -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
Signature · 6 lines
2.17.1 -- Kees Cook Pixel Security
Quoted 103 lines · Kees Cook
From: Laura Abbott <[email protected]>
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()andon_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.Signed-off-by Laura Abbott <[email protected]>[kees: add cast to current_top_of_stack(), tweak commit log & comments]Signed-off-by Kees Cook <[email protected]>---
This is tweaked to be stand-alone from Alexander's series so it can land via the arm64 tree. (Alexander's v14 pulled one change out already, and I've lifted the last remaining: the newly needed include instackleak.h)--- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/processor.h | 10 ++++++++++ arch/arm64/kernel/entry.S | 7 +++++++ arch/arm64/kernel/process.c | 16 ++++++++++++++++ arch/arm64/kvm/hyp/Makefile | 3 ++- drivers/firmware/efi/libstub/Makefile | 3 ++- 6 files changed, 38 insertions(+), 2 deletions(-)arch/arm64/Kconfig +1
-0@@ -96,6 +96,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_HUGEPAGEarch/arm64/include/asm/processor.h +10
-0@@ -266,5 +266,15 @@ 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 the STACKLEAK gcc plugin. +* +* 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 () ((unsigned long)task_stack_page(current) + \ + THREAD_SIZE) +#define on_thread_stack () (on_task_stack(current, current_stack_pointer)) +#endif /* __ASSEMBLY__ */ #endif /* __ASM_PROCESSOR_H */ arch/arm64/kernel/entry.S +7
-0@@ -431,6 +431,11 @@ tsk .req x28 // current thread_info .text + .macro stackleak_erase +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK + bl stackleak_erase_kstack +#endif + .endm /* * Exception vectors. */@@ -910,6 +915,7 @@ ret_fast_syscall: and x2, x1, #_TIF_WORK_MASK cbnz x2, work_pending enable_step_tsk x1, x2 + stackleak_erase kernel_exit 0 ret_fast_syscall_trace: enable_daif@@ -936,6 +942,7 @@ ret_to_user: cbnz x2, work_pending finish_ret_to_user: enable_step_tsk x1, x2 + stackleak_erase kernel_exit 0 ENDPROC(ret_to_user)arch/arm64/kernel/process.c +6
-0@@ -493,3 +493,19 @@ void arch_setup_new_exec(void) { current->mm->context.flags =is_compat_task () ?MMCF_AARCH32 :0 ; } + +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK +#define MIN_STACK_LEFT 256 + +void __used stackleak_check_alloca (unsigned long size) +{
arch/arm64/kernel/process.c void arch_setup_new_exec(void) · line 511
Quoted 10 lines
arch/arm64/kernel/process.c +10
-0+unsigned long sp, stack_left; + + sp = current_stack_pointer; + + stack_left = sp & (THREAD_SIZE -1 ); +BUG_ON (stack_left <MIN_STACK_LEFT || + size >= stack_left - MIN_STACK_LEFT); +} +EXPORT_SYMBOL (stackleak_check_alloca); +#endif
I think the conclusion was this needs to be re-written to account for the different stack sizes in the same way as x86.
Quoted 29 lines
arch/arm64/kvm/hyp/Makefile +2
-1@@ -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/kvmdrivers/firmware/efi/libstub/Makefile +2
-1@@ -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
Quoted 11 lines · Laura Abbott
Quoted 11 lines
arch/arm64/kernel/process.c +11
-0+#ifdef CONFIG_GCC_PLUGIN_STACKLEAK +#define MIN_STACK_LEFT 256 + +void __used stackleak_check_alloca (unsigned long size) +{ +unsigned long sp, stack_left; + + sp = current_stack_pointer; + + stack_left = sp & (THREAD_SIZE -1 ); + BUG_ON(stack_left < MIN_STACK_LEFT ||
Quoted 8 lines
arch/arm64/kernel/process.c void arch_setup_new_exec(void) · line 511
Quoted 4 lines
arch/arm64/kernel/process.c +4
-0+ size >= stack_left - MIN_STACK_LEFT); +} +EXPORT_SYMBOL (stackleak_check_alloca); +#endif I think the conclusion was this needs to be re-written to account for the different stack sizes in the same way as x86.
Oh, whoops! Sorry, I missed that fork of the thread. :)
-Kees
Signature · 2 lines
Kees Cook Pixel Security