Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: 9407/1: Add support for STACKLEAK gcc plugin

Add the STACKLEAK gcc plugin to arm32 by adding the helper used by
stackleak common code: on_thread_stack(). It initialize the stack with the
poison value before returning from system calls which improves the kernel
security. Additionally, this disables the plugin in EFI stub code and
decompress code, which are out of scope for the protection.

Before the test on Qemu versatilepb board:
# echo STACKLEAK_ERASING > /sys/kernel/debug/provoke-crash/DIRECT
lkdtm: Performing direct entry STACKLEAK_ERASING
lkdtm: XFAIL: stackleak is not supported on this arch (HAVE_ARCH_STACKLEAK=n)

After:
# echo STACKLEAK_ERASING > /sys/kernel/debug/provoke-crash/DIRECT
lkdtm: Performing direct entry STACKLEAK_ERASING
lkdtm: stackleak stack usage:
high offset: 80 bytes
current: 280 bytes
lowest: 696 bytes
tracked: 696 bytes
untracked: 192 bytes
poisoned: 7220 bytes
low offset: 4 bytes
lkdtm: OK: the rest of the thread stack is properly erased

Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>

authored by

Jinjie Ruan and committed by
Russell King (Oracle)
2335c9cb ed0f9410

+14 -1
+1
arch/arm/Kconfig
··· 86 86 select HAVE_ARCH_PFN_VALID 87 87 select HAVE_ARCH_SECCOMP 88 88 select HAVE_ARCH_SECCOMP_FILTER if AEABI && !OABI_COMPAT 89 + select HAVE_ARCH_STACKLEAK 89 90 select HAVE_ARCH_THREAD_STRUCT_WHITELIST 90 91 select HAVE_ARCH_TRACEHOOK 91 92 select HAVE_ARCH_TRANSPARENT_HUGEPAGE if ARM_LPAE
+1
arch/arm/boot/compressed/Makefile
··· 9 9 10 10 HEAD = head.o 11 11 OBJS += misc.o decompress.o 12 + CFLAGS_decompress.o += $(DISABLE_STACKLEAK_PLUGIN) 12 13 ifeq ($(CONFIG_DEBUG_UNCOMPRESS),y) 13 14 OBJS += debug.o 14 15 AFLAGS_head.o += -DDEBUG
+7
arch/arm/include/asm/stacktrace.h
··· 26 26 #endif 27 27 }; 28 28 29 + static inline bool on_thread_stack(void) 30 + { 31 + unsigned long delta = current_stack_pointer ^ (unsigned long)current->stack; 32 + 33 + return delta < THREAD_SIZE; 34 + } 35 + 29 36 static __always_inline 30 37 void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame) 31 38 {
+3
arch/arm/kernel/entry-common.S
··· 119 119 120 120 ct_user_enter save = 0 121 121 122 + #ifdef CONFIG_GCC_PLUGIN_STACKLEAK 123 + bl stackleak_erase_on_task_stack 124 + #endif 122 125 restore_user_regs fast = 0, offset = 0 123 126 ENDPROC(ret_to_user_from_irq) 124 127 ENDPROC(ret_to_user)
+2 -1
drivers/firmware/efi/libstub/Makefile
··· 27 27 cflags-$(CONFIG_ARM) += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \ 28 28 -DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \ 29 29 -DEFI_HAVE_STRCMP -fno-builtin -fpic \ 30 - $(call cc-option,-mno-single-pic-base) 30 + $(call cc-option,-mno-single-pic-base) \ 31 + $(DISABLE_STACKLEAK_PLUGIN) 31 32 cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE -mno-relax 32 33 cflags-$(CONFIG_LOONGARCH) += -fpie 33 34