[PATCH] arm64: Add CONFIG_CC_STACKPROTECTOR
Will Deacon
will.deacon at arm.com
Wed Jan 22 06:28:47 EST 2014
Hi Laura,
On Tue, Jan 21, 2014 at 05:26:06PM +0000, Laura Abbott wrote:
> arm64 currently lacks support for -fstack-protector. Add
> similar functionality to arm to detect stack corruption.
>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Signed-off-by: Laura Abbott <lauraa at codeaurora.org>
> ---
> arch/arm64/Kconfig | 12 +++++++++
> arch/arm64/Makefile | 4 +++
> arch/arm64/include/asm/stackprotector.h | 38 +++++++++++++++++++++++++++++++
> arch/arm64/kernel/process.c | 9 +++++++
> 4 files changed, 63 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm64/include/asm/stackprotector.h
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 6d4dd22..4f86874 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -168,6 +168,18 @@ config HOTPLUG_CPU
> Say Y here to experiment with turning CPUs off and on. CPUs
> can be controlled through /sys/devices/system/cpu.
>
> +config CC_STACKPROTECTOR
> + bool "Enable -fstack-protector buffer overflow detection"
> + help
> + This option turns on the -fstack-protector GCC feature. This
> + feature puts, at the beginning of functions, a canary value on
> + the stack just before the return address, and validates
> + the value just before actually returning. Stack based buffer
> + overflows (that need to overwrite this return address) now also
> + overwrite the canary, which gets detected and the attack is then
> + neutralized via a kernel panic.
> + This feature requires gcc version 4.2 or above.
You can remove that bit about GCC -- GCC 4.2 doesn't support AArch64.
> +
> source kernel/Kconfig.preempt
>
> config HZ
> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> index 2fceb71..1ce221e 100644
> --- a/arch/arm64/Makefile
> +++ b/arch/arm64/Makefile
> @@ -48,6 +48,10 @@ core-$(CONFIG_XEN) += arch/arm64/xen/
> libs-y := arch/arm64/lib/ $(libs-y)
> libs-y += $(LIBGCC)
>
> +ifeq ($(CONFIG_CC_STACKPROTECTOR),y)
> +KBUILD_CFLAGS +=-fstack-protector
> +endif
> +
> # Default target when executing plain make
> KBUILD_IMAGE := Image.gz
> KBUILD_DTBS := dtbs
> diff --git a/arch/arm64/include/asm/stackprotector.h b/arch/arm64/include/asm/stackprotector.h
> new file mode 100644
> index 0000000..de00332
> --- /dev/null
> +++ b/arch/arm64/include/asm/stackprotector.h
> @@ -0,0 +1,38 @@
> +/*
> + * GCC stack protector support.
> + *
> + * Stack protector works by putting predefined pattern at the start of
> + * the stack frame and verifying that it hasn't been overwritten when
> + * returning from the function. The pattern is called stack canary
> + * and gcc expects it to be defined by a global variable called
> + * "__stack_chk_guard" on ARM. This unfortunately means that on SMP
> + * we cannot have a different canary value per task.
> + */
> +
> +#ifndef _ASM_STACKPROTECTOR_H
__ASM_ for consistency.
> +#define _ASM_STACKPROTECTOR_H 1
Why #define explicitly to 1?
> +
> +#include <linux/random.h>
> +#include <linux/version.h>
> +
> +extern unsigned long __stack_chk_guard;
> +
> +/*
> + * Initialize the stackprotector canary value.
> + *
> + * NOTE: this must only be called from functions that never return,
> + * and it must always be inlined.
> + */
> +static __always_inline void boot_init_stack_canary(void)
> +{
> + unsigned long canary;
> +
> + /* Try to get a semi random initial value. */
> + get_random_bytes(&canary, sizeof(canary));
> + canary ^= LINUX_VERSION_CODE;
> +
> + current->stack_canary = canary;
> + __stack_chk_guard = current->stack_canary;
> +}
> +
> +#endif /* _ASM_STACKPROTECTOR_H */
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index de17c89..592d630 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -50,6 +50,12 @@
> #include <asm/processor.h>
> #include <asm/stacktrace.h>
>
> +#ifdef CONFIG_CC_STACKPROTECTOR
> +#include <linux/stackprotector.h>
> +unsigned long __stack_chk_guard __read_mostly;
> +EXPORT_SYMBOL(__stack_chk_guard);
> +#endif
> +
> static void setup_restart(void)
> {
> /*
> @@ -288,6 +294,9 @@ struct task_struct *__switch_to(struct task_struct *prev,
> {
> struct task_struct *last;
>
> +#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
> + __stack_chk_guard = next->stack_canary;
> +#endif
I don't get the dependency on !SMP. Assumedly, the update of
__stack_chk_guard would be racy otherwise, but that sounds solvable with
atomics. Is the stack_canary updated periodically somewhere else?
Will
More information about the linux-arm-kernel
mailing list