aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasahiro Yamada <yamada.masahiro@socionext.com>2018-05-28 05:22:00 -0400
committerMasahiro Yamada <yamada.masahiro@socionext.com>2018-06-08 05:56:00 -0400
commit2a61f4747eeaa85ce26ca9fbd81421b15facd018 (patch)
tree497f971a5b6af6085c8d2349e773045f6a88dcc1
parent315bab4e972d9795529b764718d475492db40c0f (diff)
stack-protector: test compiler capability in Kconfig and drop AUTO mode
Move the test for -fstack-protector(-strong) option to Kconfig. If the compiler does not support the option, the corresponding menu is automatically hidden. If STRONG is not supported, it will fall back to REGULAR. If REGULAR is not supported, it will be disabled. This means, AUTO is implicitly handled by the dependency solver of Kconfig, hence removed. I also turned the 'choice' into only two boolean symbols. The use of 'choice' is not a good idea here, because all of all{yes,mod,no}config would choose the first visible value, while we want allnoconfig to disable as many features as possible. X86 has additional shell scripts in case the compiler supports those options, but generates broken code. I added CC_HAS_SANE_STACKPROTECTOR to test this. I had to add -m32 to gcc-x86_32-has-stack-protector.sh to make it work correctly. Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com> Acked-by: Kees Cook <keescook@chromium.org>
-rw-r--r--Makefile93
-rw-r--r--arch/Kconfig32
-rw-r--r--arch/x86/Kconfig11
-rwxr-xr-xscripts/gcc-x86_32-has-stack-protector.sh7
-rwxr-xr-xscripts/gcc-x86_64-has-stack-protector.sh5
5 files changed, 28 insertions, 120 deletions
diff --git a/Makefile b/Makefile
index 747edaf11559..ca9d98b4a71b 100644
--- a/Makefile
+++ b/Makefile
@@ -686,55 +686,11 @@ ifneq ($(CONFIG_FRAME_WARN),0)
686KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) 686KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
687endif 687endif
688 688
689# This selects the stack protector compiler flag. Testing it is delayed 689stackp-flags-$(CONFIG_CC_HAS_STACKPROTECTOR_NONE) := -fno-stack-protector
690# until after .config has been reprocessed, in the prepare-compiler-check 690stackp-flags-$(CONFIG_CC_STACKPROTECTOR) := -fstack-protector
691# target. 691stackp-flags-$(CONFIG_CC_STACKPROTECTOR_STRONG) := -fstack-protector-strong
692ifdef CONFIG_CC_STACKPROTECTOR_AUTO 692
693 stackp-flag := $(call cc-option,-fstack-protector-strong,$(call cc-option,-fstack-protector)) 693KBUILD_CFLAGS += $(stackp-flags-y)
694 stackp-name := AUTO
695else
696ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
697 stackp-flag := -fstack-protector
698 stackp-name := REGULAR
699else
700ifdef CONFIG_CC_STACKPROTECTOR_STRONG
701 stackp-flag := -fstack-protector-strong
702 stackp-name := STRONG
703else
704 # If either there is no stack protector for this architecture or
705 # CONFIG_CC_STACKPROTECTOR_NONE is selected, we're done, and $(stackp-name)
706 # is empty, skipping all remaining stack protector tests.
707 #
708 # Force off for distro compilers that enable stack protector by default.
709 KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
710endif
711endif
712endif
713# Find arch-specific stack protector compiler sanity-checking script.
714ifdef stackp-name
715ifneq ($(stackp-flag),)
716 stackp-path := $(srctree)/scripts/gcc-$(SRCARCH)_$(BITS)-has-stack-protector.sh
717 stackp-check := $(wildcard $(stackp-path))
718 # If the wildcard test matches a test script, run it to check functionality.
719 ifdef stackp-check
720 ifneq ($(shell $(CONFIG_SHELL) $(stackp-check) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y)
721 stackp-broken := y
722 endif
723 endif
724 ifndef stackp-broken
725 # If the stack protector is functional, enable code that depends on it.
726 KBUILD_CPPFLAGS += -DCONFIG_CC_STACKPROTECTOR
727 # Either we've already detected the flag (for AUTO) or we'll fail the
728 # build in the prepare-compiler-check rule (for specific flag).
729 KBUILD_CFLAGS += $(stackp-flag)
730 else
731 # We have to make sure stack protector is unconditionally disabled if
732 # the compiler is broken (in case we're going to continue the build in
733 # AUTO mode).
734 KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
735 endif
736endif
737endif
738 694
739ifeq ($(cc-name),clang) 695ifeq ($(cc-name),clang)
740KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) 696KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,)
@@ -1118,7 +1074,7 @@ endif
1118# prepare2 creates a makefile if using a separate output directory. 1074# prepare2 creates a makefile if using a separate output directory.
1119# From this point forward, .config has been reprocessed, so any rules 1075# From this point forward, .config has been reprocessed, so any rules
1120# that need to depend on updated CONFIG_* values can be checked here. 1076# that need to depend on updated CONFIG_* values can be checked here.
1121prepare2: prepare3 prepare-compiler-check outputmakefile asm-generic 1077prepare2: prepare3 outputmakefile asm-generic
1122 1078
1123prepare1: prepare2 $(version_h) $(autoksyms_h) include/generated/utsrelease.h \ 1079prepare1: prepare2 $(version_h) $(autoksyms_h) include/generated/utsrelease.h \
1124 include/config/auto.conf 1080 include/config/auto.conf
@@ -1144,43 +1100,6 @@ uapi-asm-generic:
1144PHONY += prepare-objtool 1100PHONY += prepare-objtool
1145prepare-objtool: $(objtool_target) 1101prepare-objtool: $(objtool_target)
1146 1102
1147# Check for CONFIG flags that require compiler support. Abort the build
1148# after .config has been processed, but before the kernel build starts.
1149#
1150# For security-sensitive CONFIG options, we don't want to fallback and/or
1151# silently change which compiler flags will be used, since that leads to
1152# producing kernels with different security feature characteristics
1153# depending on the compiler used. (For example, "But I selected
1154# CC_STACKPROTECTOR_STRONG! Why did it build with _REGULAR?!")
1155PHONY += prepare-compiler-check
1156prepare-compiler-check: FORCE
1157# Make sure compiler supports requested stack protector flag.
1158ifdef stackp-name
1159 # Warn about CONFIG_CC_STACKPROTECTOR_AUTO having found no option.
1160 ifeq ($(stackp-flag),)
1161 @echo CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
1162 Compiler does not support any known stack-protector >&2
1163 else
1164 # Fail if specifically requested stack protector is missing.
1165 ifeq ($(call cc-option, $(stackp-flag)),)
1166 @echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
1167 $(stackp-flag) not supported by compiler >&2 && exit 1
1168 endif
1169 endif
1170endif
1171# Make sure compiler does not have buggy stack-protector support. If a
1172# specific stack-protector was requested, fail the build, otherwise warn.
1173ifdef stackp-broken
1174 ifeq ($(stackp-name),AUTO)
1175 @echo CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
1176 $(stackp-flag) available but compiler is broken: disabling >&2
1177 else
1178 @echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
1179 $(stackp-flag) available but compiler is broken >&2 && exit 1
1180 endif
1181endif
1182 @:
1183
1184# Generate some files 1103# Generate some files
1185# --------------------------------------------------------------------------- 1104# ---------------------------------------------------------------------------
1186 1105
diff --git a/arch/Kconfig b/arch/Kconfig
index 8a7f7e1f2ca7..2c7c3cf8adfc 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -536,13 +536,16 @@ config HAVE_CC_STACKPROTECTOR
536 bool 536 bool
537 help 537 help
538 An arch should select this symbol if: 538 An arch should select this symbol if:
539 - its compiler supports the -fstack-protector option
540 - it has implemented a stack canary (e.g. __stack_chk_guard) 539 - it has implemented a stack canary (e.g. __stack_chk_guard)
541 540
542choice 541config CC_HAS_STACKPROTECTOR_NONE
543 prompt "Stack Protector buffer overflow detection" 542 def_bool $(cc-option,-fno-stack-protector)
543
544config CC_STACKPROTECTOR
545 bool "Stack Protector buffer overflow detection"
544 depends on HAVE_CC_STACKPROTECTOR 546 depends on HAVE_CC_STACKPROTECTOR
545 default CC_STACKPROTECTOR_AUTO 547 depends on $(cc-option,-fstack-protector)
548 default y
546 help 549 help
547 This option turns on the "stack-protector" GCC feature. This 550 This option turns on the "stack-protector" GCC feature. This
548 feature puts, at the beginning of functions, a canary value on 551 feature puts, at the beginning of functions, a canary value on
@@ -552,14 +555,6 @@ choice
552 overwrite the canary, which gets detected and the attack is then 555 overwrite the canary, which gets detected and the attack is then
553 neutralized via a kernel panic. 556 neutralized via a kernel panic.
554 557
555config CC_STACKPROTECTOR_NONE
556 bool "None"
557 help
558 Disable "stack-protector" GCC feature.
559
560config CC_STACKPROTECTOR_REGULAR
561 bool "Regular"
562 help
563 Functions will have the stack-protector canary logic added if they 558 Functions will have the stack-protector canary logic added if they
564 have an 8-byte or larger character array on the stack. 559 have an 8-byte or larger character array on the stack.
565 560
@@ -571,7 +566,10 @@ config CC_STACKPROTECTOR_REGULAR
571 by about 0.3%. 566 by about 0.3%.
572 567
573config CC_STACKPROTECTOR_STRONG 568config CC_STACKPROTECTOR_STRONG
574 bool "Strong" 569 bool "Strong Stack Protector"
570 depends on CC_STACKPROTECTOR
571 depends on $(cc-option,-fstack-protector-strong)
572 default y
575 help 573 help
576 Functions will have the stack-protector canary logic added in any 574 Functions will have the stack-protector canary logic added in any
577 of the following conditions: 575 of the following conditions:
@@ -589,14 +587,6 @@ config CC_STACKPROTECTOR_STRONG
589 about 20% of all kernel functions, which increases the kernel code 587 about 20% of all kernel functions, which increases the kernel code
590 size by about 2%. 588 size by about 2%.
591 589
592config CC_STACKPROTECTOR_AUTO
593 bool "Automatic"
594 help
595 If the compiler supports it, the best available stack-protector
596 option will be chosen.
597
598endchoice
599
600config HAVE_ARCH_WITHIN_STACK_FRAMES 590config HAVE_ARCH_WITHIN_STACK_FRAMES
601 bool 591 bool
602 help 592 help
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index cb6e3a219294..50a1b8ec9ad9 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -129,7 +129,7 @@ config X86
129 select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64 129 select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64
130 select HAVE_ARCH_VMAP_STACK if X86_64 130 select HAVE_ARCH_VMAP_STACK if X86_64
131 select HAVE_ARCH_WITHIN_STACK_FRAMES 131 select HAVE_ARCH_WITHIN_STACK_FRAMES
132 select HAVE_CC_STACKPROTECTOR 132 select HAVE_CC_STACKPROTECTOR if CC_HAS_SANE_STACKPROTECTOR
133 select HAVE_CMPXCHG_DOUBLE 133 select HAVE_CMPXCHG_DOUBLE
134 select HAVE_CMPXCHG_LOCAL 134 select HAVE_CMPXCHG_LOCAL
135 select HAVE_CONTEXT_TRACKING if X86_64 135 select HAVE_CONTEXT_TRACKING if X86_64
@@ -341,6 +341,15 @@ config PGTABLE_LEVELS
341 default 2 341 default 2
342 342
343source "init/Kconfig" 343source "init/Kconfig"
344
345config CC_HAS_SANE_STACKPROTECTOR
346 bool
347 default $(success,$(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC)) if 64BIT
348 default $(success,$(srctree)/scripts/gcc-x86_32-has-stack-protector.sh $(CC))
349 help
350 We have to make sure stack protector is unconditionally disabled if
351 the compiler produces broken code.
352
344source "kernel/Kconfig.freezer" 353source "kernel/Kconfig.freezer"
345 354
346menu "Processor type and features" 355menu "Processor type and features"
diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh
index 6b2aeefb9cd3..f5c119495254 100755
--- a/scripts/gcc-x86_32-has-stack-protector.sh
+++ b/scripts/gcc-x86_32-has-stack-protector.sh
@@ -1,9 +1,4 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0 2# SPDX-License-Identifier: GPL-2.0
3 3
4echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" 4echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -m32 -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
5if [ "$?" -eq "0" ] ; then
6 echo y
7else
8 echo n
9fi
diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh
index 4a48bdcd4d6b..3755af0cd9f7 100755
--- a/scripts/gcc-x86_64-has-stack-protector.sh
+++ b/scripts/gcc-x86_64-has-stack-protector.sh
@@ -2,8 +2,3 @@
2# SPDX-License-Identifier: GPL-2.0 2# SPDX-License-Identifier: GPL-2.0
3 3
4echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fno-PIE -fstack-protector - -o - 2> /dev/null | grep -q "%gs" 4echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fno-PIE -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
5if [ "$?" -eq "0" ] ; then
6 echo y
7else
8 echo n
9fi