Message ID | 20180720214154.2940-3-labbott@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 21.07.2018 00:41, Laura Abbott wrote: > 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. > > Reviewed-by: Mark Rutland <mark.rutland@arm.com> > Reviewed-by: Kees Cook <keescook@chromium.org> > Signed-off-by: Laura Abbott <labbott@redhat.com> > --- > v3: Actual commit text courtesy of Kees. A comment explaining why we > panic > --- > arch/arm64/Kconfig | 1 + > arch/arm64/include/asm/processor.h | 15 +++++++++++++++ > arch/arm64/kernel/entry.S | 7 +++++++ > arch/arm64/kernel/process.c | 22 ++++++++++++++++++++++ > arch/arm64/kvm/hyp/Makefile | 3 ++- > drivers/firmware/efi/libstub/Makefile | 3 ++- > 6 files changed, 49 insertions(+), 2 deletions(-) Laura, thanks for your work! I've reviewed and tested this patch on my LeMaker HiKey board (HiSilicon Kirin 620 SoC). The lkdtm tests for STACKLEAK work fine. Acked-by: Alexander Popov <alex.popov@linux.com> For testing I applied your patches above Kees' for-next/kspp: https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/log/?h=for-next/kspp I've had one trouble with building CONFIG_STACKLEAK_RUNTIME_DISABLE on arm64. Kees, could you please fold this into the 7th patch of the series? ---- >8 ---- diff --git a/kernel/stackleak.c b/kernel/stackleak.c index f731c9a..03031f7a 100644 --- a/kernel/stackleak.c +++ b/kernel/stackleak.c @@ -16,6 +16,7 @@ #ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE #include <linux/jump_label.h> +#include <linux/sysctl.h> static DEFINE_STATIC_KEY_FALSE(stack_erasing_bypass);
On Tue, Jul 24, 2018 at 5:44 AM, Alexander Popov <alex.popov@linux.com> wrote: > On 21.07.2018 00:41, Laura Abbott wrote: >> 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. >> >> Reviewed-by: Mark Rutland <mark.rutland@arm.com> >> Reviewed-by: Kees Cook <keescook@chromium.org> >> Signed-off-by: Laura Abbott <labbott@redhat.com> >> --- >> v3: Actual commit text courtesy of Kees. A comment explaining why we >> panic >> --- >> arch/arm64/Kconfig | 1 + >> arch/arm64/include/asm/processor.h | 15 +++++++++++++++ >> arch/arm64/kernel/entry.S | 7 +++++++ >> arch/arm64/kernel/process.c | 22 ++++++++++++++++++++++ >> arch/arm64/kvm/hyp/Makefile | 3 ++- >> drivers/firmware/efi/libstub/Makefile | 3 ++- >> 6 files changed, 49 insertions(+), 2 deletions(-) > > Laura, thanks for your work! > > I've reviewed and tested this patch on my LeMaker HiKey board (HiSilicon Kirin > 620 SoC). The lkdtm tests for STACKLEAK work fine. > > Acked-by: Alexander Popov <alex.popov@linux.com> > > For testing I applied your patches above Kees' for-next/kspp: > https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/log/?h=for-next/kspp > > I've had one trouble with building CONFIG_STACKLEAK_RUNTIME_DISABLE on arm64. > Kees, could you please fold this into the 7th patch of the series? Sure thing! -Kees > > ---- >8 ---- > > diff --git a/kernel/stackleak.c b/kernel/stackleak.c > index f731c9a..03031f7a 100644 > --- a/kernel/stackleak.c > +++ b/kernel/stackleak.c > @@ -16,6 +16,7 @@ > > #ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE > #include <linux/jump_label.h> > +#include <linux/sysctl.h> > > static DEFINE_STATIC_KEY_FALSE(stack_erasing_bypass); >
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 42c090cf0292..216d36a49ab5 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -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 diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index a73ae1e49200..0061450a793b 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 28ad8799406f..67d12016063d 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -431,6 +431,11 @@ tsk .req x28 // current thread_info .text + .macro stackleak_erase +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK + bl stackleak_erase +#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) diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index e10bc363f533..f0ad00fb6a71 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