Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a61f474 authored by Masahiro Yamada's avatar Masahiro Yamada
Browse files

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: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
Acked-by: default avatarKees Cook <keescook@chromium.org>
parent 315bab4e
Loading
Loading
Loading
Loading
+6 −87
Original line number Diff line number Diff line
@@ -686,55 +686,11 @@ ifneq ($(CONFIG_FRAME_WARN),0)
KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
endif

# This selects the stack protector compiler flag. Testing it is delayed
# until after .config has been reprocessed, in the prepare-compiler-check
# target.
ifdef CONFIG_CC_STACKPROTECTOR_AUTO
  stackp-flag := $(call cc-option,-fstack-protector-strong,$(call cc-option,-fstack-protector))
  stackp-name := AUTO
else
ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
  stackp-flag := -fstack-protector
  stackp-name := REGULAR
else
ifdef CONFIG_CC_STACKPROTECTOR_STRONG
  stackp-flag := -fstack-protector-strong
  stackp-name := STRONG
else
  # If either there is no stack protector for this architecture or
  # CONFIG_CC_STACKPROTECTOR_NONE is selected, we're done, and $(stackp-name)
  # is empty, skipping all remaining stack protector tests.
  #
  # Force off for distro compilers that enable stack protector by default.
  KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
endif
endif
endif
# Find arch-specific stack protector compiler sanity-checking script.
ifdef stackp-name
ifneq ($(stackp-flag),)
  stackp-path := $(srctree)/scripts/gcc-$(SRCARCH)_$(BITS)-has-stack-protector.sh
  stackp-check := $(wildcard $(stackp-path))
  # If the wildcard test matches a test script, run it to check functionality.
  ifdef stackp-check
    ifneq ($(shell $(CONFIG_SHELL) $(stackp-check) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y)
      stackp-broken := y
    endif
  endif
  ifndef stackp-broken
    # If the stack protector is functional, enable code that depends on it.
    KBUILD_CPPFLAGS += -DCONFIG_CC_STACKPROTECTOR
    # Either we've already detected the flag (for AUTO) or we'll fail the
    # build in the prepare-compiler-check rule (for specific flag).
    KBUILD_CFLAGS += $(stackp-flag)
  else
    # We have to make sure stack protector is unconditionally disabled if
    # the compiler is broken (in case we're going to continue the build in
    # AUTO mode).
    KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
  endif
endif
endif
stackp-flags-$(CONFIG_CC_HAS_STACKPROTECTOR_NONE) := -fno-stack-protector
stackp-flags-$(CONFIG_CC_STACKPROTECTOR)          := -fstack-protector
stackp-flags-$(CONFIG_CC_STACKPROTECTOR_STRONG)   := -fstack-protector-strong

KBUILD_CFLAGS += $(stackp-flags-y)

ifeq ($(cc-name),clang)
KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,)
@@ -1118,7 +1074,7 @@ endif
# prepare2 creates a makefile if using a separate output directory.
# 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
prepare2: prepare3 outputmakefile asm-generic

prepare1: prepare2 $(version_h) $(autoksyms_h) include/generated/utsrelease.h \
                   include/config/auto.conf
@@ -1144,43 +1100,6 @@ uapi-asm-generic:
PHONY += prepare-objtool
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
  # Warn about CONFIG_CC_STACKPROTECTOR_AUTO having found no option.
  ifeq ($(stackp-flag),)
	@echo CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
		  Compiler does not support any known stack-protector >&2
  else
  # Fail if specifically requested stack protector is missing.
  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
endif
# Make sure compiler does not have buggy stack-protector support. If a
# specific stack-protector was requested, fail the build, otherwise warn.
ifdef stackp-broken
  ifeq ($(stackp-name),AUTO)
	@echo CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
                  $(stackp-flag) available but compiler is broken: disabling >&2
  else
	@echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
                  $(stackp-flag) available but compiler is broken >&2 && exit 1
  endif
endif
	@:

# Generate some files
# ---------------------------------------------------------------------------

+11 −21
Original line number Diff line number Diff line
@@ -536,13 +536,16 @@ config HAVE_CC_STACKPROTECTOR
	bool
	help
	  An arch should select this symbol if:
	  - its compiler supports the -fstack-protector option
	  - it has implemented a stack canary (e.g. __stack_chk_guard)

choice
	prompt "Stack Protector buffer overflow detection"
config CC_HAS_STACKPROTECTOR_NONE
	def_bool $(cc-option,-fno-stack-protector)

config CC_STACKPROTECTOR
	bool "Stack Protector buffer overflow detection"
	depends on HAVE_CC_STACKPROTECTOR
	default CC_STACKPROTECTOR_AUTO
	depends on $(cc-option,-fstack-protector)
	default y
	help
	  This option turns on the "stack-protector" GCC feature. This
	  feature puts, at the beginning of functions, a canary value on
@@ -552,14 +555,6 @@ choice
	  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"
	help
	  Functions will have the stack-protector canary logic added if they
	  have an 8-byte or larger character array on the stack.

@@ -571,7 +566,10 @@ config CC_STACKPROTECTOR_REGULAR
	  by about 0.3%.

config CC_STACKPROTECTOR_STRONG
	bool "Strong"
	bool "Strong Stack Protector"
	depends on CC_STACKPROTECTOR
	depends on $(cc-option,-fstack-protector-strong)
	default y
	help
	  Functions will have the stack-protector canary logic added in any
	  of the following conditions:
@@ -589,14 +587,6 @@ config CC_STACKPROTECTOR_STRONG
	  about 20% of all kernel functions, which increases the kernel code
	  size by about 2%.

config CC_STACKPROTECTOR_AUTO
	bool "Automatic"
	help
	  If the compiler supports it, the best available stack-protector
	  option will be chosen.

endchoice

config HAVE_ARCH_WITHIN_STACK_FRAMES
	bool
	help
+10 −1
Original line number Diff line number Diff line
@@ -129,7 +129,7 @@ config X86
	select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64
	select HAVE_ARCH_VMAP_STACK		if X86_64
	select HAVE_ARCH_WITHIN_STACK_FRAMES
	select HAVE_CC_STACKPROTECTOR
	select HAVE_CC_STACKPROTECTOR		if CC_HAS_SANE_STACKPROTECTOR
	select HAVE_CMPXCHG_DOUBLE
	select HAVE_CMPXCHG_LOCAL
	select HAVE_CONTEXT_TRACKING		if X86_64
@@ -341,6 +341,15 @@ config PGTABLE_LEVELS
	default 2

source "init/Kconfig"

config CC_HAS_SANE_STACKPROTECTOR
	bool
	default $(success,$(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC)) if 64BIT
	default $(success,$(srctree)/scripts/gcc-x86_32-has-stack-protector.sh $(CC))
	help
	   We have to make sure stack protector is unconditionally disabled if
	   the compiler produces broken code.

source "kernel/Kconfig.freezer"

menu "Processor type and features"
+1 −6
Original line number Diff line number Diff line
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0

echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
if [ "$?" -eq "0" ] ; then
	echo y
else
	echo n
fi
echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -m32 -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
+0 −5
Original line number Diff line number Diff line
@@ -2,8 +2,3 @@
# SPDX-License-Identifier: GPL-2.0

echo "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"
if [ "$?" -eq "0" ] ; then
	echo y
else
	echo n
fi