Commit c743f380 authored by Nicolas Pitre's avatar Nicolas Pitre

ARM: initial stack protector (-fstack-protector) support

This is the very basic stuff without the changing canary upon
task switch yet.  Just the Kconfig option and a constant canary
value initialized at boot time.
Signed-off-by: default avatarNicolas Pitre <nicolas.pitre@linaro.org>
parent cc92c28b
...@@ -1374,6 +1374,18 @@ config UACCESS_WITH_MEMCPY ...@@ -1374,6 +1374,18 @@ config UACCESS_WITH_MEMCPY
However, if the CPU data cache is using a write-allocate mode, However, if the CPU data cache is using a write-allocate mode,
this option is unlikely to provide any performance gain. this option is unlikely to provide any performance gain.
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.
endmenu endmenu
menu "Boot options" menu "Boot options"
......
...@@ -34,6 +34,10 @@ ifeq ($(CONFIG_FRAME_POINTER),y) ...@@ -34,6 +34,10 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
endif endif
ifeq ($(CONFIG_CC_STACKPROTECTOR),y)
KBUILD_CFLAGS +=-fstack-protector
endif
ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
KBUILD_CPPFLAGS += -mbig-endian KBUILD_CPPFLAGS += -mbig-endian
AS += -EB AS += -EB
......
/*
* 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
#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 */
...@@ -37,6 +37,12 @@ ...@@ -37,6 +37,12 @@
#include <asm/stacktrace.h> #include <asm/stacktrace.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
#ifdef CONFIG_CC_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
#endif
static const char *processor_modes[] = { static const char *processor_modes[] = {
"USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
"UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment