From patchwork Tue Jul 26 21:26:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 9248991 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 27348607D8 for ; Tue, 26 Jul 2016 21:26:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 17D1D20951 for ; Tue, 26 Jul 2016 21:26:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0CBEB26B41; Tue, 26 Jul 2016 21:26:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 395B920951 for ; Tue, 26 Jul 2016 21:26:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1161008AbcGZV0s (ORCPT ); Tue, 26 Jul 2016 17:26:48 -0400 Received: from mail-pa0-f44.google.com ([209.85.220.44]:34938 "EHLO mail-pa0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1161240AbcGZV0Z (ORCPT ); Tue, 26 Jul 2016 17:26:25 -0400 Received: by mail-pa0-f44.google.com with SMTP id iw10so3188052pac.2 for ; Tue, 26 Jul 2016 14:26:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=date:from:to:cc:subject:message-id:mime-version:content-disposition; bh=CbFGWSE6XU4dj5Ng/6Y+oJ92b7zdJzYk+21QzIhogbY=; b=c1tpggzqI/0DHbPVaMsdYW/2PP4HKgC+C0BRangThZ+DCF0+nXJ80xYGmQASn9V8C7 MoBk6OLCCs8JBhIinYQsweydRyE8xY6iYGGVTL7NS63YLwBWKDjL2aie3yFN0fEg1Huc TewHPflp22PDnyJeOCOD+hNqT7RagzciubqFE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition; bh=CbFGWSE6XU4dj5Ng/6Y+oJ92b7zdJzYk+21QzIhogbY=; b=mp70Sa8PWmPgGV/MqF+lq6zNxhhWl/UdHzl1rLUVYFV0WZWHIJy+W7H7fOBj/tNH6z pNLe/VR3wVR6qZE5+lAtgVuVsN/gvYjVSEhFnaGQqst4AvDWtnk1K1z0QgQDdEYXYCIV NXyuzmPZWTPTt45f0MDGCXd8n/kodpJvy/9fCgnkFpvgyuerRnhbpEowVLpR6ARMRmrd LqLn4bMhBla+dNalQEfKq5baT3Bn5BnYo8ijBbiwMagibZNJcM+h0oZ5pHsYkFc4/RXd 9CjhSVaEnwdMqk+NG1YM+dF8sFYMuIM36IM/9fzkeP+PNQvr3TOslD6aj1EjMxR3jnta yVVQ== X-Gm-Message-State: AEkoouvdlAa66aQ58NKb44jYi+/NbQpOJWsFH9jGtVgKy37989gaJHzMb3mr1e2fN0V8Pk1s X-Received: by 10.66.54.35 with SMTP id g3mr43227815pap.30.1469568382569; Tue, 26 Jul 2016 14:26:22 -0700 (PDT) Received: from www.outflux.net (173-164-112-133-Oregon.hfc.comcastbusiness.net. [173.164.112.133]) by smtp.gmail.com with ESMTPSA id d1sm3468318pas.48.2016.07.26.14.26.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Jul 2016 14:26:21 -0700 (PDT) Date: Tue, 26 Jul 2016 14:26:20 -0700 From: Kees Cook To: Michal Marek Cc: linux-kernel@vger.kernel.org, Ingo Molnar , x86@kernel.org, linux-kbuild@vger.kernel.org Subject: [PATCH v2] kbuild: Abort build on bad stack protector flag Message-ID: <20160726212620.GA8511@www.outflux.net> MIME-Version: 1.0 Content-Disposition: inline Sender: linux-kbuild-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kbuild@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- v2: - fix use of SRCARCH, mmarek - simplify stackp-check usage, mmarek --- Makefile | 67 +++++++++++++++++++++++++++++++++---------------------- arch/x86/Makefile | 8 ------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index b409076c7c18..65dea56136b6 100644 --- a/Makefile +++ b/Makefile @@ -645,41 +645,26 @@ ifneq ($(CONFIG_FRAME_WARN),0) KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) endif -# Handle stack protector mode. -# -# Since kbuild can potentially perform two passes (first with the old -# .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. -# +# 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_REGULAR stackp-flag := -fstack-protector - ifeq ($(call cc-option, $(stackp-flag)),) - $(warning Cannot use CONFIG_CC_STACKPROTECTOR_REGULAR: \ - -fstack-protector not supported by compiler) - endif + stackp-name := REGULAR else ifdef CONFIG_CC_STACKPROTECTOR_STRONG stackp-flag := -fstack-protector-strong - ifeq ($(call cc-option, $(stackp-flag)),) - $(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \ - -fstack-protector-strong not supported by compiler) - endif + stackp-name := STRONG else # Force off for distro compilers that enable stack protector by default. stackp-flag := $(call cc-option, -fno-stack-protector) 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) ifdef CONFIG_KCOV @@ -1015,8 +1000,10 @@ ifneq ($(KBUILD_SRC),) fi; endif -# prepare2 creates a makefile if using a separate output directory -prepare2: prepare3 outputmakefile asm-generic +# 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 prepare1: prepare2 $(version_h) include/generated/utsrelease.h \ include/config/auto.conf @@ -1047,6 +1034,32 @@ endif 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 + 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 # --------------------------------------------------------------------------- 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 KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args) 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 x32_ld_ok := $(call try-run,\ /bin/echo -e '1: .quad 1b' | \