Skip to content

Commit 2a61f47

Browse files
committed
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 <[email protected]> Acked-by: Kees Cook <[email protected]>
1 parent 315bab4 commit 2a61f47

File tree

5 files changed

+28
-120
lines changed

5 files changed

+28
-120
lines changed

Makefile

Lines changed: 6 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -686,55 +686,11 @@ ifneq ($(CONFIG_FRAME_WARN),0)
686686
KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
687687
endif
688688

689-
# This selects the stack protector compiler flag. Testing it is delayed
690-
# until after .config has been reprocessed, in the prepare-compiler-check
691-
# target.
692-
ifdef CONFIG_CC_STACKPROTECTOR_AUTO
693-
stackp-flag := $(call cc-option,-fstack-protector-strong,$(call cc-option,-fstack-protector))
694-
stackp-name := AUTO
695-
else
696-
ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
697-
stackp-flag := -fstack-protector
698-
stackp-name := REGULAR
699-
else
700-
ifdef CONFIG_CC_STACKPROTECTOR_STRONG
701-
stackp-flag := -fstack-protector-strong
702-
stackp-name := STRONG
703-
else
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)
710-
endif
711-
endif
712-
endif
713-
# Find arch-specific stack protector compiler sanity-checking script.
714-
ifdef stackp-name
715-
ifneq ($(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
736-
endif
737-
endif
689+
stackp-flags-$(CONFIG_CC_HAS_STACKPROTECTOR_NONE) := -fno-stack-protector
690+
stackp-flags-$(CONFIG_CC_STACKPROTECTOR) := -fstack-protector
691+
stackp-flags-$(CONFIG_CC_STACKPROTECTOR_STRONG) := -fstack-protector-strong
692+
693+
KBUILD_CFLAGS += $(stackp-flags-y)
738694

739695
ifeq ($(cc-name),clang)
740696
KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,)
@@ -1118,7 +1074,7 @@ endif
11181074
# prepare2 creates a makefile if using a separate output directory.
11191075
# From this point forward, .config has been reprocessed, so any rules
11201076
# that need to depend on updated CONFIG_* values can be checked here.
1121-
prepare2: prepare3 prepare-compiler-check outputmakefile asm-generic
1077+
prepare2: prepare3 outputmakefile asm-generic
11221078

11231079
prepare1: prepare2 $(version_h) $(autoksyms_h) include/generated/utsrelease.h \
11241080
include/config/auto.conf
@@ -1144,43 +1100,6 @@ uapi-asm-generic:
11441100
PHONY += prepare-objtool
11451101
prepare-objtool: $(objtool_target)
11461102

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?!")
1155-
PHONY += prepare-compiler-check
1156-
prepare-compiler-check: FORCE
1157-
# Make sure compiler supports requested stack protector flag.
1158-
ifdef 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
1170-
endif
1171-
# Make sure compiler does not have buggy stack-protector support. If a
1172-
# specific stack-protector was requested, fail the build, otherwise warn.
1173-
ifdef 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
1181-
endif
1182-
@:
1183-
11841103
# Generate some files
11851104
# ---------------------------------------------------------------------------
11861105

arch/Kconfig

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -536,13 +536,16 @@ config HAVE_CC_STACKPROTECTOR
536536
bool
537537
help
538538
An arch should select this symbol if:
539-
- its compiler supports the -fstack-protector option
540539
- it has implemented a stack canary (e.g. __stack_chk_guard)
541540

542-
choice
543-
prompt "Stack Protector buffer overflow detection"
541+
config CC_HAS_STACKPROTECTOR_NONE
542+
def_bool $(cc-option,-fno-stack-protector)
543+
544+
config CC_STACKPROTECTOR
545+
bool "Stack Protector buffer overflow detection"
544546
depends on HAVE_CC_STACKPROTECTOR
545-
default CC_STACKPROTECTOR_AUTO
547+
depends on $(cc-option,-fstack-protector)
548+
default y
546549
help
547550
This option turns on the "stack-protector" GCC feature. This
548551
feature puts, at the beginning of functions, a canary value on
@@ -552,14 +555,6 @@ choice
552555
overwrite the canary, which gets detected and the attack is then
553556
neutralized via a kernel panic.
554557

555-
config CC_STACKPROTECTOR_NONE
556-
bool "None"
557-
help
558-
Disable "stack-protector" GCC feature.
559-
560-
config CC_STACKPROTECTOR_REGULAR
561-
bool "Regular"
562-
help
563558
Functions will have the stack-protector canary logic added if they
564559
have an 8-byte or larger character array on the stack.
565560

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

573568
config 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
575573
help
576574
Functions will have the stack-protector canary logic added in any
577575
of the following conditions:
@@ -589,14 +587,6 @@ config CC_STACKPROTECTOR_STRONG
589587
about 20% of all kernel functions, which increases the kernel code
590588
size by about 2%.
591589

592-
config 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-
598-
endchoice
599-
600590
config HAVE_ARCH_WITHIN_STACK_FRAMES
601591
bool
602592
help

arch/x86/Kconfig

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ config X86
129129
select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64
130130
select HAVE_ARCH_VMAP_STACK if X86_64
131131
select HAVE_ARCH_WITHIN_STACK_FRAMES
132-
select HAVE_CC_STACKPROTECTOR
132+
select HAVE_CC_STACKPROTECTOR if CC_HAS_SANE_STACKPROTECTOR
133133
select HAVE_CMPXCHG_DOUBLE
134134
select HAVE_CMPXCHG_LOCAL
135135
select HAVE_CONTEXT_TRACKING if X86_64
@@ -341,6 +341,15 @@ config PGTABLE_LEVELS
341341
default 2
342342

343343
source "init/Kconfig"
344+
345+
config 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+
344353
source "kernel/Kconfig.freezer"
345354

346355
menu "Processor type and features"
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11
#!/bin/sh
22
# SPDX-License-Identifier: GPL-2.0
33

4-
echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
5-
if [ "$?" -eq "0" ] ; then
6-
echo y
7-
else
8-
echo n
9-
fi
4+
echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -m32 -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"

scripts/gcc-x86_64-has-stack-protector.sh

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,3 @@
22
# SPDX-License-Identifier: GPL-2.0
33

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

0 commit comments

Comments
 (0)