diff mbox series

LoongArch: Enable HAVE_ARCH_STACKLEAK

Message ID 20250423063147.69178-1-youling.tang@linux.dev
State New
Headers show
Series LoongArch: Enable HAVE_ARCH_STACKLEAK | expand

Commit Message

Youling Tang April 23, 2025, 6:31 a.m. UTC
From: Youling Tang <tangyouling@kylinos.cn>

Add support for the stackleak feature. It initialize the stack with the
poison value before returning from system calls which improves the kernel
security.

At the same time, disables the plugin in EFI stub code because EFI stub
is out of scope for the protection.

Tested on 3A5000 (enable CONFIG_GCC_PLUGIN_STACKLEAK and CONFIG_LKDTM):
 # echo STACKLEAK_ERASING > /sys/kernel/debug/provoke-crash/DIRECT
 # dmesg
   lkdtm: Performing direct entry STACKLEAK_ERASING
   lkdtm: stackleak stack usage:
      high offset: 320 bytes
      current:     448 bytes
      lowest:      1264 bytes
      tracked:     1264 bytes
      untracked:   208 bytes
      poisoned:    14528 bytes
      low offset:  64 bytes
   lkdtm: OK: the rest of the thread stack is properly erased

Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
---
 arch/loongarch/Kconfig                    | 1 +
 arch/loongarch/include/asm/entry-common.h | 8 +-------
 arch/loongarch/include/asm/stacktrace.h   | 5 +++++
 arch/loongarch/kernel/entry.S             | 9 +++++++++
 drivers/firmware/efi/libstub/Makefile     | 2 +-
 5 files changed, 17 insertions(+), 8 deletions(-)

Comments

Huacai Chen April 23, 2025, 2:02 p.m. UTC | #1
Hi, Youling,

On Wed, Apr 23, 2025 at 2:32 PM Youling Tang <youling.tang@linux.dev> wrote:
>
> From: Youling Tang <tangyouling@kylinos.cn>
>
> Add support for the stackleak feature. It initialize the stack with the
> poison value before returning from system calls which improves the kernel
> security.
>
> At the same time, disables the plugin in EFI stub code because EFI stub
> is out of scope for the protection.
>
> Tested on 3A5000 (enable CONFIG_GCC_PLUGIN_STACKLEAK and CONFIG_LKDTM):
>  # echo STACKLEAK_ERASING > /sys/kernel/debug/provoke-crash/DIRECT
>  # dmesg
>    lkdtm: Performing direct entry STACKLEAK_ERASING
>    lkdtm: stackleak stack usage:
>       high offset: 320 bytes
>       current:     448 bytes
>       lowest:      1264 bytes
>       tracked:     1264 bytes
>       untracked:   208 bytes
>       poisoned:    14528 bytes
>       low offset:  64 bytes
>    lkdtm: OK: the rest of the thread stack is properly erased
>
> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> ---
>  arch/loongarch/Kconfig                    | 1 +
>  arch/loongarch/include/asm/entry-common.h | 8 +-------
>  arch/loongarch/include/asm/stacktrace.h   | 5 +++++
>  arch/loongarch/kernel/entry.S             | 9 +++++++++
>  drivers/firmware/efi/libstub/Makefile     | 2 +-
>  5 files changed, 17 insertions(+), 8 deletions(-)
>
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index 067c0b994648..3a6bfcab2dde 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -122,6 +122,7 @@ config LOONGARCH
>         select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
>         select HAVE_ARCH_SECCOMP
>         select HAVE_ARCH_SECCOMP_FILTER
> +       select HAVE_ARCH_STACKLEAK
>         select HAVE_ARCH_TRACEHOOK
>         select HAVE_ARCH_TRANSPARENT_HUGEPAGE
>         select HAVE_ARCH_USERFAULTFD_MINOR if USERFAULTFD
> diff --git a/arch/loongarch/include/asm/entry-common.h b/arch/loongarch/include/asm/entry-common.h
> index 0fe2a098ded9..a7a6af490f86 100644
> --- a/arch/loongarch/include/asm/entry-common.h
> +++ b/arch/loongarch/include/asm/entry-common.h
> @@ -2,12 +2,6 @@
>  #ifndef ARCH_LOONGARCH_ENTRY_COMMON_H
>  #define ARCH_LOONGARCH_ENTRY_COMMON_H
>
> -#include <linux/sched.h>
> -#include <linux/processor.h>
> -
> -static inline bool on_thread_stack(void)
> -{
> -       return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
> -}
> +#include <asm/stacktrace.h>
>
>  #endif
> diff --git a/arch/loongarch/include/asm/stacktrace.h b/arch/loongarch/include/asm/stacktrace.h
> index fc8b64773794..3861beb96002 100644
> --- a/arch/loongarch/include/asm/stacktrace.h
> +++ b/arch/loongarch/include/asm/stacktrace.h
> @@ -31,6 +31,11 @@ bool in_irq_stack(unsigned long stack, struct stack_info *info);
>  bool in_task_stack(unsigned long stack, struct task_struct *task, struct stack_info *info);
>  int get_stack_info(unsigned long stack, struct task_struct *task, struct stack_info *info);
>
> +static inline bool on_thread_stack(void)
Use __always_inline is better for objtool, like x86.

> +{
> +       return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
> +}
> +
>  #define STR_LONG_L    __stringify(LONG_L)
>  #define STR_LONG_S    __stringify(LONG_S)
>  #define STR_LONGSIZE  __stringify(LONGSIZE)
> diff --git a/arch/loongarch/kernel/entry.S b/arch/loongarch/kernel/entry.S
> index 48e7e34e355e..27dcb3a66b2b 100644
> --- a/arch/loongarch/kernel/entry.S
> +++ b/arch/loongarch/kernel/entry.S
> @@ -16,6 +16,12 @@
>  #include <asm/thread_info.h>
>  #include <asm/unwind_hints.h>
>
> +       .macro STACKLEAK_ERASE
> +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
> +       bl              stackleak_erase_on_task_stack
> +#endif
> +       .endm
Move this macro to stackframe.h? This makes it can be used by other files.

Huacai

> +
>         .text
>         .cfi_sections   .debug_frame
>         .align  5
> @@ -73,6 +79,7 @@ SYM_CODE_START(handle_syscall)
>         move            a0, sp
>         bl              do_syscall
>
> +       STACKLEAK_ERASE
>         RESTORE_ALL_AND_RET
>  SYM_CODE_END(handle_syscall)
>  _ASM_NOKPROBE(handle_syscall)
> @@ -82,6 +89,7 @@ SYM_CODE_START(ret_from_fork)
>         bl              schedule_tail           # a0 = struct task_struct *prev
>         move            a0, sp
>         bl              syscall_exit_to_user_mode
> +       STACKLEAK_ERASE
>         RESTORE_STATIC
>         RESTORE_SOME
>         RESTORE_SP_AND_RET
> @@ -94,6 +102,7 @@ SYM_CODE_START(ret_from_kernel_thread)
>         jirl            ra, s0, 0
>         move            a0, sp
>         bl              syscall_exit_to_user_mode
> +       STACKLEAK_ERASE
>         RESTORE_STATIC
>         RESTORE_SOME
>         RESTORE_SP_AND_RET
> diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
> index d23a1b9fed75..b97981d63d2f 100644
> --- a/drivers/firmware/efi/libstub/Makefile
> +++ b/drivers/firmware/efi/libstub/Makefile
> @@ -31,7 +31,7 @@ cflags-$(CONFIG_ARM)          += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
>                                    $(DISABLE_STACKLEAK_PLUGIN)
>  cflags-$(CONFIG_RISCV)         += -fpic -DNO_ALTERNATIVE -mno-relax \
>                                    $(DISABLE_STACKLEAK_PLUGIN)
> -cflags-$(CONFIG_LOONGARCH)     += -fpie
> +cflags-$(CONFIG_LOONGARCH)     += -fpie $(DISABLE_STACKLEAK_PLUGIN)
>
>  cflags-$(CONFIG_EFI_PARAMS_FROM_FDT)   += -I$(srctree)/scripts/dtc/libfdt
>
> --
> 2.38.1
>
diff mbox series

Patch

diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index 067c0b994648..3a6bfcab2dde 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -122,6 +122,7 @@  config LOONGARCH
 	select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
 	select HAVE_ARCH_SECCOMP
 	select HAVE_ARCH_SECCOMP_FILTER
+	select HAVE_ARCH_STACKLEAK
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
 	select HAVE_ARCH_USERFAULTFD_MINOR if USERFAULTFD
diff --git a/arch/loongarch/include/asm/entry-common.h b/arch/loongarch/include/asm/entry-common.h
index 0fe2a098ded9..a7a6af490f86 100644
--- a/arch/loongarch/include/asm/entry-common.h
+++ b/arch/loongarch/include/asm/entry-common.h
@@ -2,12 +2,6 @@ 
 #ifndef ARCH_LOONGARCH_ENTRY_COMMON_H
 #define ARCH_LOONGARCH_ENTRY_COMMON_H
 
-#include <linux/sched.h>
-#include <linux/processor.h>
-
-static inline bool on_thread_stack(void)
-{
-	return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
-}
+#include <asm/stacktrace.h>
 
 #endif
diff --git a/arch/loongarch/include/asm/stacktrace.h b/arch/loongarch/include/asm/stacktrace.h
index fc8b64773794..3861beb96002 100644
--- a/arch/loongarch/include/asm/stacktrace.h
+++ b/arch/loongarch/include/asm/stacktrace.h
@@ -31,6 +31,11 @@  bool in_irq_stack(unsigned long stack, struct stack_info *info);
 bool in_task_stack(unsigned long stack, struct task_struct *task, struct stack_info *info);
 int get_stack_info(unsigned long stack, struct task_struct *task, struct stack_info *info);
 
+static inline bool on_thread_stack(void)
+{
+	return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
+}
+
 #define STR_LONG_L    __stringify(LONG_L)
 #define STR_LONG_S    __stringify(LONG_S)
 #define STR_LONGSIZE  __stringify(LONGSIZE)
diff --git a/arch/loongarch/kernel/entry.S b/arch/loongarch/kernel/entry.S
index 48e7e34e355e..27dcb3a66b2b 100644
--- a/arch/loongarch/kernel/entry.S
+++ b/arch/loongarch/kernel/entry.S
@@ -16,6 +16,12 @@ 
 #include <asm/thread_info.h>
 #include <asm/unwind_hints.h>
 
+	.macro STACKLEAK_ERASE
+#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
+	bl		stackleak_erase_on_task_stack
+#endif
+	.endm
+
 	.text
 	.cfi_sections	.debug_frame
 	.align	5
@@ -73,6 +79,7 @@  SYM_CODE_START(handle_syscall)
 	move		a0, sp
 	bl		do_syscall
 
+	STACKLEAK_ERASE
 	RESTORE_ALL_AND_RET
 SYM_CODE_END(handle_syscall)
 _ASM_NOKPROBE(handle_syscall)
@@ -82,6 +89,7 @@  SYM_CODE_START(ret_from_fork)
 	bl		schedule_tail		# a0 = struct task_struct *prev
 	move		a0, sp
 	bl 		syscall_exit_to_user_mode
+	STACKLEAK_ERASE
 	RESTORE_STATIC
 	RESTORE_SOME
 	RESTORE_SP_AND_RET
@@ -94,6 +102,7 @@  SYM_CODE_START(ret_from_kernel_thread)
 	jirl		ra, s0, 0
 	move		a0, sp
 	bl		syscall_exit_to_user_mode
+	STACKLEAK_ERASE
 	RESTORE_STATIC
 	RESTORE_SOME
 	RESTORE_SP_AND_RET
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index d23a1b9fed75..b97981d63d2f 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -31,7 +31,7 @@  cflags-$(CONFIG_ARM)		+= -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
 				   $(DISABLE_STACKLEAK_PLUGIN)
 cflags-$(CONFIG_RISCV)		+= -fpic -DNO_ALTERNATIVE -mno-relax \
 				   $(DISABLE_STACKLEAK_PLUGIN)
-cflags-$(CONFIG_LOONGARCH)	+= -fpie
+cflags-$(CONFIG_LOONGARCH)	+= -fpie $(DISABLE_STACKLEAK_PLUGIN)
 
 cflags-$(CONFIG_EFI_PARAMS_FROM_FDT)	+= -I$(srctree)/scripts/dtc/libfdt