diff options
author | Kees Cook <keescook@chromium.org> | 2016-07-26 17:26:20 -0400 |
---|---|---|
committer | Michal Marek <mmarek@suse.com> | 2016-07-26 17:50:59 -0400 |
commit | 228d96c603cf53e32f672c0e459d2adbc5a4609a (patch) | |
tree | e6d936927424b32c693ad20f61f1990094765008 | |
parent | 21532b9e5bd597631cfe38d9eb34df069938065b (diff) |
kbuild: Abort build on bad stack protector flag
Before, the stack protector flag was sanity checked before .config had
been reprocessed. This meant the build couldn't be aborted early, and
only a warning could be emitted followed later by the compiler blowing
up with an unknown flag. This has caused a lot of confusion over time,
so this splits the flag selection from sanity checking and performs the
sanity checking after the make has been restarted from a reprocessed
.config, so builds can be aborted as early as possible now.
Additionally moves the x86-specific sanity check to the same location,
since it suffered from the same warn-then-wait-for-compiler-failure
problem.
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Michal Marek <mmarek@suse.com>
-rw-r--r-- | Makefile | 67 | ||||
-rw-r--r-- | arch/x86/Makefile | 8 |
2 files changed, 40 insertions, 35 deletions
@@ -655,41 +655,26 @@ ifneq ($(CONFIG_FRAME_WARN),0) | |||
655 | KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) | 655 | KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) |
656 | endif | 656 | endif |
657 | 657 | ||
658 | # Handle stack protector mode. | 658 | # This selects the stack protector compiler flag. Testing it is delayed |
659 | # | 659 | # until after .config has been reprocessed, in the prepare-compiler-check |
660 | # Since kbuild can potentially perform two passes (first with the old | 660 | # target. |
661 | # .config values and then with updated .config values), we cannot error out | ||
662 | # if a desired compiler option is unsupported. If we were to error, kbuild | ||
663 | # could never get to the second pass and actually notice that we changed | ||
664 | # the option to something that was supported. | ||
665 | # | ||
666 | # Additionally, we don't want to fallback and/or silently change which compiler | ||
667 | # flags will be used, since that leads to producing kernels with different | ||
668 | # security feature characteristics depending on the compiler used. ("But I | ||
669 | # selected CC_STACKPROTECTOR_STRONG! Why did it build with _REGULAR?!") | ||
670 | # | ||
671 | # The middle ground is to warn here so that the failed option is obvious, but | ||
672 | # to let the build fail with bad compiler flags so that we can't produce a | ||
673 | # kernel when there is a CONFIG and compiler mismatch. | ||
674 | # | ||
675 | ifdef CONFIG_CC_STACKPROTECTOR_REGULAR | 661 | ifdef CONFIG_CC_STACKPROTECTOR_REGULAR |
676 | stackp-flag := -fstack-protector | 662 | stackp-flag := -fstack-protector |
677 | ifeq ($(call cc-option, $(stackp-flag)),) | 663 | stackp-name := REGULAR |
678 | $(warning Cannot use CONFIG_CC_STACKPROTECTOR_REGULAR: \ | ||
679 | -fstack-protector not supported by compiler) | ||
680 | endif | ||
681 | else | 664 | else |
682 | ifdef CONFIG_CC_STACKPROTECTOR_STRONG | 665 | ifdef CONFIG_CC_STACKPROTECTOR_STRONG |
683 | stackp-flag := -fstack-protector-strong | 666 | stackp-flag := -fstack-protector-strong |
684 | ifeq ($(call cc-option, $(stackp-flag)),) | 667 | stackp-name := STRONG |
685 | $(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \ | ||
686 | -fstack-protector-strong not supported by compiler) | ||
687 | endif | ||
688 | else | 668 | else |
689 | # Force off for distro compilers that enable stack protector by default. | 669 | # Force off for distro compilers that enable stack protector by default. |
690 | stackp-flag := $(call cc-option, -fno-stack-protector) | 670 | stackp-flag := $(call cc-option, -fno-stack-protector) |
691 | endif | 671 | endif |
692 | endif | 672 | endif |
673 | # Find arch-specific stack protector compiler sanity-checking script. | ||
674 | ifdef CONFIG_CC_STACKPROTECTOR | ||
675 | stackp-path := $(srctree)/scripts/gcc-$(SRCARCH)_$(BITS)-has-stack-protector.sh | ||
676 | stackp-check := $(wildcard $(stackp-path)) | ||
677 | endif | ||
693 | KBUILD_CFLAGS += $(stackp-flag) | 678 | KBUILD_CFLAGS += $(stackp-flag) |
694 | 679 | ||
695 | ifeq ($(cc-name),clang) | 680 | ifeq ($(cc-name),clang) |
@@ -1017,8 +1002,10 @@ ifneq ($(KBUILD_SRC),) | |||
1017 | fi; | 1002 | fi; |
1018 | endif | 1003 | endif |
1019 | 1004 | ||
1020 | # prepare2 creates a makefile if using a separate output directory | 1005 | # prepare2 creates a makefile if using a separate output directory. |
1021 | prepare2: prepare3 outputmakefile asm-generic | 1006 | # From this point forward, .config has been reprocessed, so any rules |
1007 | # that need to depend on updated CONFIG_* values can be checked here. | ||
1008 | prepare2: prepare3 prepare-compiler-check outputmakefile asm-generic | ||
1022 | 1009 | ||
1023 | prepare1: prepare2 $(version_h) include/generated/utsrelease.h \ | 1010 | prepare1: prepare2 $(version_h) include/generated/utsrelease.h \ |
1024 | include/config/auto.conf | 1011 | include/config/auto.conf |
@@ -1049,6 +1036,32 @@ endif | |||
1049 | PHONY += prepare-objtool | 1036 | PHONY += prepare-objtool |
1050 | prepare-objtool: $(objtool_target) | 1037 | prepare-objtool: $(objtool_target) |
1051 | 1038 | ||
1039 | # Check for CONFIG flags that require compiler support. Abort the build | ||
1040 | # after .config has been processed, but before the kernel build starts. | ||
1041 | # | ||
1042 | # For security-sensitive CONFIG options, we don't want to fallback and/or | ||
1043 | # silently change which compiler flags will be used, since that leads to | ||
1044 | # producing kernels with different security feature characteristics | ||
1045 | # depending on the compiler used. (For example, "But I selected | ||
1046 | # CC_STACKPROTECTOR_STRONG! Why did it build with _REGULAR?!") | ||
1047 | PHONY += prepare-compiler-check | ||
1048 | prepare-compiler-check: FORCE | ||
1049 | # Make sure compiler supports requested stack protector flag. | ||
1050 | ifdef stackp-name | ||
1051 | ifeq ($(call cc-option, $(stackp-flag)),) | ||
1052 | @echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \ | ||
1053 | $(stackp-flag) not supported by compiler >&2 && exit 1 | ||
1054 | endif | ||
1055 | endif | ||
1056 | # Make sure compiler does not have buggy stack-protector support. | ||
1057 | ifdef stackp-check | ||
1058 | ifneq ($(shell $(CONFIG_SHELL) $(stackp-check) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y) | ||
1059 | @echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \ | ||
1060 | $(stackp-flag) available but compiler is broken >&2 && exit 1 | ||
1061 | endif | ||
1062 | endif | ||
1063 | @: | ||
1064 | |||
1052 | # Generate some files | 1065 | # Generate some files |
1053 | # --------------------------------------------------------------------------- | 1066 | # --------------------------------------------------------------------------- |
1054 | 1067 | ||
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 6fce7f096b88..830ed391e7ef 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile | |||
@@ -126,14 +126,6 @@ else | |||
126 | KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args) | 126 | KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args) |
127 | endif | 127 | endif |
128 | 128 | ||
129 | # Make sure compiler does not have buggy stack-protector support. | ||
130 | ifdef CONFIG_CC_STACKPROTECTOR | ||
131 | cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh | ||
132 | ifneq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y) | ||
133 | $(warning stack-protector enabled but compiler support broken) | ||
134 | endif | ||
135 | endif | ||
136 | |||
137 | ifdef CONFIG_X86_X32 | 129 | ifdef CONFIG_X86_X32 |
138 | x32_ld_ok := $(call try-run,\ | 130 | x32_ld_ok := $(call try-run,\ |
139 | /bin/echo -e '1: .quad 1b' | \ | 131 | /bin/echo -e '1: .quad 1b' | \ |