[PATCH (sh-2.6) 1/2] sh: add stack smashing protection support
Nicolas Pitre
nicolas.pitre at linaro.org
Tue Dec 7 13:28:44 EST 2010
On Tue, 7 Dec 2010, Filippo ARCIDIACONO wrote:
> Add stack smashing suppurt for SH architecture. This is based on work
> from Nicolas Pitre for ARM (c743f38013aeff58ef6252601e397b5ba281c633).
> Use the ARM boot_init_stack_canary function to initialize the guard
> canary. It has been placed under asm-generic to allow archtectures
> based on __stack_chk_guard to use a common implementation.
> Update the __stack_chk_guard global variable with the value stored in
> the task struct whenever a task switch occurs to allow for different
> canary values per task. This cannot work on SMP where the initial
> canary value is always used.
Uwe already pointed out some typos in the above.
> Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono at st.com>
> Reviewed-by: Carmelo Amoroso <carmelo.amoroso at st.com>
Acked-by: Nicolas Pitre <nicolas.pitre at linaro.org>
> ---
> arch/sh/Kconfig | 13 +++++++++++
> arch/sh/Makefile | 4 +++
> arch/sh/include/asm/stackprotector.h | 10 ++++++++
> arch/sh/kernel/process_32.c | 9 +++++++
> include/asm-generic/stackprotector.h | 39 ++++++++++++++++++++++++++++++++++
> 5 files changed, 75 insertions(+), 0 deletions(-)
> create mode 100644 arch/sh/include/asm/stackprotector.h
> create mode 100644 include/asm-generic/stackprotector.h
>
> diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
> index 1e905a6..2c82c98 100644
> --- a/arch/sh/Kconfig
> +++ b/arch/sh/Kconfig
> @@ -742,6 +742,19 @@ config HW_PERF_EVENTS
> Enable hardware performance counter support for perf events. If
> disabled, perf events will use software events only.
>
> +config CC_STACKPROTECTOR
> + bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
> + depends on EXPERIMENTAL
> + 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.
> +
> source "drivers/sh/Kconfig"
>
> endmenu
> diff --git a/arch/sh/Makefile b/arch/sh/Makefile
> index 9c8c6e1..3cef435 100644
> --- a/arch/sh/Makefile
> +++ b/arch/sh/Makefile
> @@ -197,6 +197,10 @@ ifeq ($(CONFIG_DWARF_UNWINDER),y)
> KBUILD_CFLAGS += -fasynchronous-unwind-tables
> endif
>
> +ifeq ($(CONFIG_CC_STACKPROTECTOR),y)
> + KBUILD_CFLAGS += -fstack-protector
> +endif
> +
> libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y)
> libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y)
>
> diff --git a/arch/sh/include/asm/stackprotector.h b/arch/sh/include/asm/stackprotector.h
> new file mode 100644
> index 0000000..f777dbd
> --- /dev/null
> +++ b/arch/sh/include/asm/stackprotector.h
> @@ -0,0 +1,10 @@
> +/*
> + * SH specific GCC stack protector support.
> + */
> +
> +#ifndef _ASM_STACKPROTECTOR_H
> +#define _ASM_STACKPROTECTOR_H 1
> +
> +#include <asm-generic/stackprotector.h>
> +
> +#endif /* _ASM_STACKPROTECTOR_H */
> diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
> index 762a139..97535d8 100644
> --- a/arch/sh/kernel/process_32.c
> +++ b/arch/sh/kernel/process_32.c
> @@ -27,6 +27,11 @@
> #include <asm/fpu.h>
> #include <asm/syscalls.h>
>
> +#ifdef CONFIG_CC_STACKPROTECTOR
> +unsigned long __stack_chk_guard __read_mostly;
> +EXPORT_SYMBOL(__stack_chk_guard);
> +#endif
> +
> void show_regs(struct pt_regs * regs)
> {
> printk("\n");
> @@ -221,6 +226,10 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
> {
> struct thread_struct *next_t = &next->thread;
>
> +#if defined CONFIG_CC_STACKPROTECTOR && !defined CONFIG_SMP
> + __stack_chk_guard = next->stack_canary;
> +#endif
> +
> unlazy_fpu(prev, task_pt_regs(prev));
>
> /* we're going to use this soon, after a few expensive things */
> diff --git a/include/asm-generic/stackprotector.h b/include/asm-generic/stackprotector.h
> new file mode 100644
> index 0000000..2d33c83
> --- /dev/null
> +++ b/include/asm-generic/stackprotector.h
> @@ -0,0 +1,39 @@
> +/*
> + * GCC stack protector support.
> + * (Generic implementation based on __stack_chk_guard)
> + *
> + * 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". This unfortunately means that on SMP
> + * we cannot have a different canary value per task.
> + */
> +
> +#ifndef _ASM_STACKPROTECTOR_H
> +#error "Never use <asm-generic/stackprotector.h> directly; \
> +include <asm/stackprotector.h> instead."
> +#endif
> +
> +#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;
> +}
> --
> 1.5.5.6
>
More information about the linux-arm-kernel
mailing list