diff options
author | Gregory Fong <gregory.0xf0@gmail.com> | 2013-06-12 17:08:54 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-07-01 15:10:48 +0200 |
commit | 36ecafc5ad17861e2bc1fb12af4cc97680e25942 (patch) | |
tree | 8b1094782049660b366b417119d34a5a519e0c95 | |
parent | 23df34155b29674465813b327647cd79722aa659 (diff) |
MIPS: initial stack protector support
Implements basic stack protector support based on ARM version in
c743f38013aeff58ef6252601e397b5ba281c633 , with Kconfig option,
constant canary value set at boot time, and script to check if
compiler actually supports stack protector.
Tested by creating a kernel module that writes past end of char[].
Signed-off-by: Gregory Fong <gregory.0xf0@gmail.com>
Cc: linux-mips@linux-mips.org
Cc: Filippo Arcidiacono <filippo.arcidiacono@st.com>
Cc: Carmelo Amoroso <carmelo.amoroso@st.com>
Patchwork: https://patchwork.linux-mips.org/patch/5448/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/Kconfig | 13 | ||||
-rw-r--r-- | arch/mips/Makefile | 4 | ||||
-rw-r--r-- | arch/mips/include/asm/stackprotector.h | 40 | ||||
-rw-r--r-- | arch/mips/kernel/process.c | 6 |
4 files changed, 63 insertions, 0 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 69bf31062ca..6dbeb273afc 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2367,6 +2367,19 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. +config CC_STACKPROTECTOR + bool "Enable -fstack-protector buffer overflow detection (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. + config USE_OF bool select OF diff --git a/arch/mips/Makefile b/arch/mips/Makefile index dd58a04ef4b..37f9ef324f2 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -227,6 +227,10 @@ KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0) LDFLAGS += -m $(ld-emul) +ifdef CONFIG_CC_STACKPROTECTOR + KBUILD_CFLAGS += -fstack-protector +endif + ifdef CONFIG_MIPS CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ diff --git a/arch/mips/include/asm/stackprotector.h b/arch/mips/include/asm/stackprotector.h new file mode 100644 index 00000000000..eb9b1035e92 --- /dev/null +++ b/arch/mips/include/asm/stackprotector.h @@ -0,0 +1,40 @@ +/* + * GCC stack protector support. + * + * (This is directly adopted from the ARM implementation) + * + * 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 MIPS. This unfortunately means that on SMP + * we cannot have a different canary value per task. + */ + +#ifndef _ASM_STACKPROTECTOR_H +#define _ASM_STACKPROTECTOR_H 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/mips/kernel/process.c b/arch/mips/kernel/process.c index c6a041d9d05..7d62894f7e2 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -201,6 +201,12 @@ int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr) return 1; } +#ifdef CONFIG_CC_STACKPROTECTOR +#include <linux/stackprotector.h> +unsigned long __stack_chk_guard __read_mostly; +EXPORT_SYMBOL(__stack_chk_guard); +#endif + /* * */ |