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>
This commit is contained in:
parent
21532b9e5b
commit
228d96c603
2 changed files with 40 additions and 35 deletions
67
Makefile
67
Makefile
|
@ -655,41 +655,26 @@ ifneq ($(CONFIG_FRAME_WARN),0)
|
||||||
KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
|
KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Handle stack protector mode.
|
# This selects the stack protector compiler flag. Testing it is delayed
|
||||||
#
|
# until after .config has been reprocessed, in the prepare-compiler-check
|
||||||
# Since kbuild can potentially perform two passes (first with the old
|
# target.
|
||||||
# .config values and then with updated .config values), we cannot error out
|
|
||||||
# if a desired compiler option is unsupported. If we were to error, kbuild
|
|
||||||
# could never get to the second pass and actually notice that we changed
|
|
||||||
# the option to something that was supported.
|
|
||||||
#
|
|
||||||
# Additionally, we don't want to fallback and/or silently change which compiler
|
|
||||||
# flags will be used, since that leads to producing kernels with different
|
|
||||||
# security feature characteristics depending on the compiler used. ("But I
|
|
||||||
# selected CC_STACKPROTECTOR_STRONG! Why did it build with _REGULAR?!")
|
|
||||||
#
|
|
||||||
# The middle ground is to warn here so that the failed option is obvious, but
|
|
||||||
# to let the build fail with bad compiler flags so that we can't produce a
|
|
||||||
# kernel when there is a CONFIG and compiler mismatch.
|
|
||||||
#
|
|
||||||
ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
|
ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
|
||||||
stackp-flag := -fstack-protector
|
stackp-flag := -fstack-protector
|
||||||
ifeq ($(call cc-option, $(stackp-flag)),)
|
stackp-name := REGULAR
|
||||||
$(warning Cannot use CONFIG_CC_STACKPROTECTOR_REGULAR: \
|
|
||||||
-fstack-protector not supported by compiler)
|
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
ifdef CONFIG_CC_STACKPROTECTOR_STRONG
|
ifdef CONFIG_CC_STACKPROTECTOR_STRONG
|
||||||
stackp-flag := -fstack-protector-strong
|
stackp-flag := -fstack-protector-strong
|
||||||
ifeq ($(call cc-option, $(stackp-flag)),)
|
stackp-name := STRONG
|
||||||
$(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \
|
|
||||||
-fstack-protector-strong not supported by compiler)
|
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
# Force off for distro compilers that enable stack protector by default.
|
# Force off for distro compilers that enable stack protector by default.
|
||||||
stackp-flag := $(call cc-option, -fno-stack-protector)
|
stackp-flag := $(call cc-option, -fno-stack-protector)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
# Find arch-specific stack protector compiler sanity-checking script.
|
||||||
|
ifdef CONFIG_CC_STACKPROTECTOR
|
||||||
|
stackp-path := $(srctree)/scripts/gcc-$(SRCARCH)_$(BITS)-has-stack-protector.sh
|
||||||
|
stackp-check := $(wildcard $(stackp-path))
|
||||||
|
endif
|
||||||
KBUILD_CFLAGS += $(stackp-flag)
|
KBUILD_CFLAGS += $(stackp-flag)
|
||||||
|
|
||||||
ifeq ($(cc-name),clang)
|
ifeq ($(cc-name),clang)
|
||||||
|
@ -1017,8 +1002,10 @@ ifneq ($(KBUILD_SRC),)
|
||||||
fi;
|
fi;
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# prepare2 creates a makefile if using a separate output directory
|
# prepare2 creates a makefile if using a separate output directory.
|
||||||
prepare2: prepare3 outputmakefile asm-generic
|
# From this point forward, .config has been reprocessed, so any rules
|
||||||
|
# that need to depend on updated CONFIG_* values can be checked here.
|
||||||
|
prepare2: prepare3 prepare-compiler-check outputmakefile asm-generic
|
||||||
|
|
||||||
prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
|
prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
|
||||||
include/config/auto.conf
|
include/config/auto.conf
|
||||||
|
@ -1049,6 +1036,32 @@ endif
|
||||||
PHONY += prepare-objtool
|
PHONY += prepare-objtool
|
||||||
prepare-objtool: $(objtool_target)
|
prepare-objtool: $(objtool_target)
|
||||||
|
|
||||||
|
# Check for CONFIG flags that require compiler support. Abort the build
|
||||||
|
# after .config has been processed, but before the kernel build starts.
|
||||||
|
#
|
||||||
|
# For security-sensitive CONFIG options, we don't want to fallback and/or
|
||||||
|
# silently change which compiler flags will be used, since that leads to
|
||||||
|
# producing kernels with different security feature characteristics
|
||||||
|
# depending on the compiler used. (For example, "But I selected
|
||||||
|
# CC_STACKPROTECTOR_STRONG! Why did it build with _REGULAR?!")
|
||||||
|
PHONY += prepare-compiler-check
|
||||||
|
prepare-compiler-check: FORCE
|
||||||
|
# Make sure compiler supports requested stack protector flag.
|
||||||
|
ifdef stackp-name
|
||||||
|
ifeq ($(call cc-option, $(stackp-flag)),)
|
||||||
|
@echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
|
||||||
|
$(stackp-flag) not supported by compiler >&2 && exit 1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
# Make sure compiler does not have buggy stack-protector support.
|
||||||
|
ifdef stackp-check
|
||||||
|
ifneq ($(shell $(CONFIG_SHELL) $(stackp-check) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y)
|
||||||
|
@echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
|
||||||
|
$(stackp-flag) available but compiler is broken >&2 && exit 1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
@:
|
||||||
|
|
||||||
# Generate some files
|
# Generate some files
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -126,14 +126,6 @@ else
|
||||||
KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args)
|
KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Make sure compiler does not have buggy stack-protector support.
|
|
||||||
ifdef CONFIG_CC_STACKPROTECTOR
|
|
||||||
cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh
|
|
||||||
ifneq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y)
|
|
||||||
$(warning stack-protector enabled but compiler support broken)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef CONFIG_X86_X32
|
ifdef CONFIG_X86_X32
|
||||||
x32_ld_ok := $(call try-run,\
|
x32_ld_ok := $(call try-run,\
|
||||||
/bin/echo -e '1: .quad 1b' | \
|
/bin/echo -e '1: .quad 1b' | \
|
||||||
|
|
Loading…
Reference in a new issue