Message ID | 20250423063147.69178-1-youling.tang@linux.dev |
---|---|
State | New |
Headers | show |
Series | LoongArch: Enable HAVE_ARCH_STACKLEAK | expand |
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 --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