From 9fe17b2153ed7cc206aaeeb1c1316094b774db4d Mon Sep 17 00:00:00 2001 From: Charles Strahan Date: Mon, 7 Aug 2017 23:20:21 -0400 Subject: [PATCH] hardening: fix #18995 --- .../bintools-wrapper/add-flags.sh | 1 + .../build-support/cc-wrapper/add-hardening.sh | 37 +++++++++++-------- pkgs/stdenv/generic/make-derivation.nix | 19 ++++++++++ pkgs/stdenv/generic/setup.sh | 3 ++ 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/pkgs/build-support/bintools-wrapper/add-flags.sh b/pkgs/build-support/bintools-wrapper/add-flags.sh index 7d118d20fc6..ce213897ee3 100644 --- a/pkgs/build-support/bintools-wrapper/add-flags.sh +++ b/pkgs/build-support/bintools-wrapper/add-flags.sh @@ -5,6 +5,7 @@ var_templates_list=( NIX+LDFLAGS_BEFORE NIX+LDFLAGS_AFTER NIX+LDFLAGS_HARDEN + NIX+HARDENING_ENABLE ) var_templates_bool=( NIX+SET_BUILD_ID diff --git a/pkgs/build-support/cc-wrapper/add-hardening.sh b/pkgs/build-support/cc-wrapper/add-hardening.sh index a35ff3cb426..f0da0a85516 100644 --- a/pkgs/build-support/cc-wrapper/add-hardening.sh +++ b/pkgs/build-support/cc-wrapper/add-hardening.sh @@ -1,33 +1,41 @@ -hardeningFlags=(fortify stackprotector pic strictoverflow format relro bindnow) -# Intentionally word-split in case 'hardeningEnable' is defined in -# Nix. Also, our bootstrap tools version of bash is old enough that -# undefined arrays trip `set -u`. -if [[ -v hardeningEnable[@] ]]; then - hardeningFlags+=(${hardeningEnable[@]}) -fi +allHardeningFlags=(fortify stackprotector pie pic strictoverflow format relro bindnow) hardeningCFlags=() declare -A hardeningDisableMap +declare -A hardeningEnableMap -# Intentionally word-split in case 'hardeningDisable' is defined in Nix. -for flag in ${hardeningDisable[@]:-IGNORED_KEY} @hardening_unsupported_flags@ -do +# Create table of unsupported flags for this toolchain. +for flag in @hardening_unsupported_flags@; do hardeningDisableMap[$flag]=1 done +# Intentionally word-split in case 'NIX_HARDENING_ENABLE' is defined in Nix. The +# array expansion also prevents undefined variables from causing trouble with +# `set -u`. +for flag in ${NIX_HARDENING_ENABLE+}; do + if [[ -n "${hardeningDisableMap[$flag]}" ]]; then + hardeningEnableMap[$flag]=1 + fi +done + if (( "${NIX_DEBUG:-0}" >= 1 )); then + # Determine which flags were effectively disabled so we can report below. + for flag in ${allHardeningFlags[@]}; do + if [[ -z "${hardeningEnableMap[$flag]}" ]]; then + hardeningDisableMap[$flag]=1 + fi + done + printf 'HARDENING: disabled flags:' >&2 (( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2 echo >&2 fi -if [[ -z "${hardeningDisableMap[all]:-}" ]]; then +if (( "${#hardeningEnableMap[@]}" )); then if (( "${NIX_DEBUG:-0}" >= 1 )); then echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2; fi - for flag in "${hardeningFlags[@]}" - do - if [[ -z "${hardeningDisableMap[$flag]:-}" ]]; then + for flag in "${!hardeningEnableMap[@]}"; do case $flag in fortify) if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling fortify >&2; fi @@ -62,6 +70,5 @@ if [[ -z "${hardeningDisableMap[all]:-}" ]]; then # tool supports each flag. ;; esac - fi done fi diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index e8f78d7401f..56977747246 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -115,6 +115,23 @@ rec { ] ]; + defaultHardeningFlags = [ + "fortify" "stackprotector" "pic" "strictoverflow" "format" "relro" "bindnow" + ]; + + hardeningDisable = + let val = attrs.hardeningDisable or [ ]; + in if builtins.isList val then val else [ val ]; + + hardeningEnable = + let val = attrs.hardeningEnable or [ ]; + in if builtins.isList val then val else [ val ]; + + enabledHardeningOptions = + if builtins.elem "all" hardeningDisable + then [] + else lib.subtractLists hardeningDisable (defaultHardeningFlags ++ hardeningEnable); + outputs' = outputs ++ (if separateDebugInfo then assert stdenv.hostPlatform.isLinux; [ "debug" ] else []); @@ -179,6 +196,8 @@ rec { ++ optional (elem "host" configurePlatforms) "--host=${stdenv.hostPlatform.config}" ++ optional (elem "target" configurePlatforms) "--target=${stdenv.targetPlatform.config}"; + } // lib.optionalAttrs (hardeningDisable != [] || hardeningEnable != []) { + NIX_HARDENING_ENABLE = enabledHardeningOptions; } // lib.optionalAttrs (stdenv.buildPlatform.isDarwin) { # TODO: remove lib.unique once nix has a list canonicalization primitive __sandboxProfile = diff --git a/pkgs/stdenv/generic/setup.sh b/pkgs/stdenv/generic/setup.sh index d7a4781448a..62bc2c2af6f 100644 --- a/pkgs/stdenv/generic/setup.sh +++ b/pkgs/stdenv/generic/setup.sh @@ -7,6 +7,9 @@ fi : ${outputs:=out} +# If unset, assume the default hardening flags. +: ${NIX_HARDENING_ENABLE="fortify stackprotector pic strictoverflow format relro bindnow"} +export NIX_HARDENING_ENABLE ###################################################################### # Hook handling.