diff --git a/Makefile b/Makefile index 84fb5cd092d2..5271b9623aa3 100644 --- a/Makefile +++ b/Makefile @@ -596,12 +596,18 @@ KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) endif # Handle stack protector mode. -ifdef CONFIG_CC_STACKPROTECTOR +ifdef CONFIG_CC_STACKPROTECTOR_REGULAR stackp-flag := -fstack-protector ifeq ($(call cc-option, $(stackp-flag)),) $(warning Cannot use CONFIG_CC_STACKPROTECTOR: \ -fstack-protector not supported by compiler)) endif +else ifdef CONFIG_CC_STACKPROTECTOR_STRONG + stackp-flag := -fstack-protector-strong + ifeq ($(call cc-option, $(stackp-flag)),) + $(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \ + -fstack-protector-strong not supported by compiler) + endif else # Force off for distro compilers that enable stack protector by default. stackp-flag := $(call cc-option, -fno-stack-protector) diff --git a/arch/Kconfig b/arch/Kconfig index 24e026d83072..80bbb8ccd0d1 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -344,10 +344,17 @@ config HAVE_CC_STACKPROTECTOR - it has implemented a stack canary (e.g. __stack_chk_guard) config CC_STACKPROTECTOR - bool "Enable -fstack-protector buffer overflow detection" - depends on HAVE_CC_STACKPROTECTOR + def_bool n help - This option turns on the -fstack-protector GCC feature. This + Set when a stack-protector mode is enabled, so that the build + can enable kernel-side support for the GCC feature. + +choice + prompt "Stack Protector buffer overflow detection" + depends on HAVE_CC_STACKPROTECTOR + default CC_STACKPROTECTOR_NONE + help + This option turns on the "stack-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 @@ -355,8 +362,46 @@ config CC_STACKPROTECTOR overwrite the canary, which gets detected and the attack is then neutralized via a kernel panic. +config CC_STACKPROTECTOR_NONE + bool "None" + help + Disable "stack-protector" GCC feature. + +config CC_STACKPROTECTOR_REGULAR + bool "Regular" + select CC_STACKPROTECTOR + help + Functions will have the stack-protector canary logic added if they + have an 8-byte or larger character array on the stack. + This feature requires gcc version 4.2 or above, or a distribution - gcc with the feature backported. + gcc with the feature backported ("-fstack-protector"). + + On an x86 "defconfig" build, this feature adds canary checks to + about 3% of all kernel functions, which increases kernel code size + by about 0.3%. + +config CC_STACKPROTECTOR_STRONG + bool "Strong" + select CC_STACKPROTECTOR + help + Functions will have the stack-protector canary logic added in any + of the following conditions: + + - local variable's address used as part of the right hand side of an + assignment or function argument + - local variable is an array (or union containing an array), + regardless of array type or length + - uses register local variables + + This feature requires gcc version 4.9 or above, or a distribution + gcc with the feature backported ("-fstack-protector-strong"). + + On an x86 "defconfig" build, this feature adds canary checks to + about 20% of all kernel functions, which increases the kernel code + size by about 2%. + +endchoice config HAVE_CONTEXT_TRACKING bool diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 31bd43b82095..d4f891f56996 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -127,6 +127,18 @@ asmlinkage void __div0(void) error("Attempting division by 0!"); } +unsigned long __stack_chk_guard; + +void __stack_chk_guard_setup(void) +{ + __stack_chk_guard = 0x000a0dff; +} + +void __stack_chk_fail(void) +{ + error("stack-protector: Kernel stack is corrupted\n"); +} + extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); @@ -137,6 +149,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, { int ret; + __stack_chk_guard_setup(); + output_data = (unsigned char *)output_start; free_mem_ptr = free_mem_ptr_p; free_mem_end_ptr = free_mem_ptr_end_p;