diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2018-04-11 14:00:13 -0400 |
---|---|---|
committer | John Ericson <John.Ericson@Obsidian.Systems> | 2018-04-11 14:00:13 -0400 |
commit | 0884027ef56c0e7cac94e1c0a42c2a1610c8ef5c (patch) | |
tree | 8ca677cf85cbb6857b6a10d7bd27360a3281685a | |
parent | 27dd87222769bc602d34c5a5c2a13f492f432dbe (diff) |
Revert "Revert "Merge pull request #28029 from cstrahan/hardening-fix""
This reverts commit 6c064e6b1f34a8416f990db0cc617a7195f71588, reapplying PR #28029 which was supposed to have gone to staging all along.
-rw-r--r-- | pkgs/build-support/bintools-wrapper/add-flags.sh | 5 | ||||
-rw-r--r-- | pkgs/build-support/bintools-wrapper/add-hardening.sh | 87 | ||||
-rw-r--r-- | pkgs/build-support/bintools-wrapper/ld-wrapper.sh | 4 | ||||
-rw-r--r-- | pkgs/build-support/bintools-wrapper/setup-hook.sh | 4 | ||||
-rw-r--r-- | pkgs/build-support/cc-wrapper/add-flags.sh | 4 | ||||
-rw-r--r-- | pkgs/build-support/cc-wrapper/add-hardening.sh | 115 | ||||
-rw-r--r-- | pkgs/build-support/cc-wrapper/cc-wrapper.sh | 4 | ||||
-rw-r--r-- | pkgs/build-support/cc-wrapper/setup-hook.sh | 4 | ||||
-rw-r--r-- | pkgs/stdenv/generic/make-derivation.nix | 7 |
9 files changed, 130 insertions, 104 deletions
diff --git a/pkgs/build-support/bintools-wrapper/add-flags.sh b/pkgs/build-support/bintools-wrapper/add-flags.sh index 7d118d20fc682..a978092589543 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 @@ -23,10 +24,10 @@ if [ "${NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_TARGET:-}" ]; then fi for var in "${var_templates_list[@]}"; do - mangleVarList "$var" "${role_infixes[@]}" + mangleVarList "$var" ${role_infixes[@]+"${role_infixes[@]}"} done for var in "${var_templates_bool[@]}"; do - mangleVarBool "$var" "${role_infixes[@]}" + mangleVarBool "$var" ${role_infixes[@]+"${role_infixes[@]}"} done if [ -e @out@/nix-support/libc-ldflags ]; then diff --git a/pkgs/build-support/bintools-wrapper/add-hardening.sh b/pkgs/build-support/bintools-wrapper/add-hardening.sh index 5282d17fce27f..a15be821659f9 100644 --- a/pkgs/build-support/bintools-wrapper/add-hardening.sh +++ b/pkgs/build-support/bintools-wrapper/add-hardening.sh @@ -1,53 +1,58 @@ -hardeningFlags=(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 -hardeningLDFlags=() +declare -a hardeningLDFlags=() + +declare -A hardeningEnableMap=() -declare -A hardeningDisableMap +# 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_@infixSalt@_HARDENING_ENABLE-}; do + hardeningEnableMap["$flag"]=1 +done -# Intentionally word-split in case 'hardeningDisable' is defined in Nix. -for flag in ${hardeningDisable[@]:-IGNORED_KEY} @hardening_unsupported_flags@ -do - hardeningDisableMap[$flag]=1 +# Remove unsupported flags. +for flag in @hardening_unsupported_flags@; do + unset -v hardeningEnableMap["$flag"] done if (( "${NIX_DEBUG:-0}" >= 1 )); then + declare -a allHardeningFlags=(pie relro bindnow) + declare -A hardeningDisableMap=() + + # 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 (( "${NIX_DEBUG:-0}" >= 1 )); then + if (( "${#hardeningEnableMap[@]}" )); then echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2; fi - for flag in "${hardeningFlags[@]}" - do - if [[ -z "${hardeningDisableMap[$flag]:-}" ]]; then - case $flag in - pie) - if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; then - if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling LDFlags -pie >&2; fi - hardeningLDFlags+=('-pie') - fi - ;; - relro) - if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling relro >&2; fi - hardeningLDFlags+=('-z' 'relro') - ;; - bindnow) - if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling bindnow >&2; fi - hardeningLDFlags+=('-z' 'now') - ;; - *) - # Ignore unsupported. Checked in Nix that at least *some* - # tool supports each flag. - ;; - esac - fi - done fi + +for flag in "${!hardeningEnableMap[@]}"; do + case $flag in + pie) + if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; then + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling LDFlags -pie >&2; fi + hardeningLDFlags+=('-pie') + fi + ;; + relro) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling relro >&2; fi + hardeningLDFlags+=('-z' 'relro') + ;; + bindnow) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling bindnow >&2; fi + hardeningLDFlags+=('-z' 'now') + ;; + *) + # Ignore unsupported. Checked in Nix that at least *some* + # tool supports each flag. + ;; + esac +done diff --git a/pkgs/build-support/bintools-wrapper/ld-wrapper.sh b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh index 991ed0fe263c1..672a3dcbe385e 100644 --- a/pkgs/build-support/bintools-wrapper/ld-wrapper.sh +++ b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh @@ -57,8 +57,8 @@ fi source @out@/nix-support/add-hardening.sh -extraAfter=("${hardeningLDFlags[@]}") -extraBefore=() +extraAfter=() +extraBefore=(${hardeningLDFlags[@]+"${hardeningLDFlags[@]}"}) if [ -z "${NIX_@infixSalt@_LDFLAGS_SET:-}" ]; then extraAfter+=($NIX_@infixSalt@_LDFLAGS) diff --git a/pkgs/build-support/bintools-wrapper/setup-hook.sh b/pkgs/build-support/bintools-wrapper/setup-hook.sh index 48a00b0b9b074..831ee9b038722 100644 --- a/pkgs/build-support/bintools-wrapper/setup-hook.sh +++ b/pkgs/build-support/bintools-wrapper/setup-hook.sh @@ -83,6 +83,10 @@ do fi done +# If unset, assume the default hardening flags. +: ${NIX_HARDENING_ENABLE="fortify stackprotector pic strictoverflow format relro bindnow"} +export NIX_HARDENING_ENABLE + # No local scope in sourced file unset -v role_pre role_post cmd upper_case set +u diff --git a/pkgs/build-support/cc-wrapper/add-flags.sh b/pkgs/build-support/cc-wrapper/add-flags.sh index 604aaf6b6cf0b..e384d30ecbb6e 100644 --- a/pkgs/build-support/cc-wrapper/add-flags.sh +++ b/pkgs/build-support/cc-wrapper/add-flags.sh @@ -30,10 +30,10 @@ fi # We need to mangle names for hygiene, but also take parameters/overrides # from the environment. for var in "${var_templates_list[@]}"; do - mangleVarList "$var" "${role_infixes[@]}" + mangleVarList "$var" ${role_infixes[@]+"${role_infixes[@]}"} done for var in "${var_templates_bool[@]}"; do - mangleVarBool "$var" "${role_infixes[@]}" + mangleVarBool "$var" ${role_infixes[@]+"${role_infixes[@]}"} done # `-B@out@/bin' forces cc to use ld-wrapper.sh when calling ld. diff --git a/pkgs/build-support/cc-wrapper/add-hardening.sh b/pkgs/build-support/cc-wrapper/add-hardening.sh index a35ff3cb42609..026e486714479 100644 --- a/pkgs/build-support/cc-wrapper/add-hardening.sh +++ b/pkgs/build-support/cc-wrapper/add-hardening.sh @@ -1,67 +1,72 @@ -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 -hardeningCFlags=() +declare -a hardeningCFlags=() + +declare -A hardeningEnableMap=() -declare -A hardeningDisableMap +# 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_@infixSalt@_HARDENING_ENABLE-}; do + hardeningEnableMap["$flag"]=1 +done -# Intentionally word-split in case 'hardeningDisable' is defined in Nix. -for flag in ${hardeningDisable[@]:-IGNORED_KEY} @hardening_unsupported_flags@ -do - hardeningDisableMap[$flag]=1 +# Remove unsupported flags. +for flag in @hardening_unsupported_flags@; do + unset -v hardeningEnableMap["$flag"] done if (( "${NIX_DEBUG:-0}" >= 1 )); then + declare -a allHardeningFlags=(fortify stackprotector pie pic strictoverflow format) + declare -A hardeningDisableMap=() + + # 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 (( "${NIX_DEBUG:-0}" >= 1 )); then + if (( "${#hardeningEnableMap[@]}" )); then echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2; fi - for flag in "${hardeningFlags[@]}" - do - if [[ -z "${hardeningDisableMap[$flag]:-}" ]]; then - case $flag in - fortify) - if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling fortify >&2; fi - hardeningCFlags+=('-O2' '-D_FORTIFY_SOURCE=2') - ;; - stackprotector) - if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling stackprotector >&2; fi - hardeningCFlags+=('-fstack-protector-strong' '--param' 'ssp-buffer-size=4') - ;; - pie) - if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling CFlags -fPIE >&2; fi - hardeningCFlags+=('-fPIE') - if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; then - if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling LDFlags -pie >&2; fi - hardeningCFlags+=('-pie') - fi - ;; - pic) - if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling pic >&2; fi - hardeningCFlags+=('-fPIC') - ;; - strictoverflow) - if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling strictoverflow >&2; fi - hardeningCFlags+=('-fno-strict-overflow') - ;; - format) - if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling format >&2; fi - hardeningCFlags+=('-Wformat' '-Wformat-security' '-Werror=format-security') - ;; - *) - # Ignore unsupported. Checked in Nix that at least *some* - # tool supports each flag. - ;; - esac - fi - done fi + +for flag in "${!hardeningEnableMap[@]}"; do + case $flag in + fortify) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling fortify >&2; fi + hardeningCFlags+=('-O2' '-D_FORTIFY_SOURCE=2') + ;; + stackprotector) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling stackprotector >&2; fi + hardeningCFlags+=('-fstack-protector-strong' '--param' 'ssp-buffer-size=4') + ;; + pie) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling CFlags -fPIE >&2; fi + hardeningCFlags+=('-fPIE') + if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; then + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling LDFlags -pie >&2; fi + hardeningCFlags+=('-pie') + fi + ;; + pic) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling pic >&2; fi + hardeningCFlags+=('-fPIC') + ;; + strictoverflow) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling strictoverflow >&2; fi + hardeningCFlags+=('-fno-strict-overflow') + ;; + format) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling format >&2; fi + hardeningCFlags+=('-Wformat' '-Wformat-security' '-Werror=format-security') + ;; + *) + # Ignore unsupported. Checked in Nix that at least *some* + # tool supports each flag. + ;; + esac +done diff --git a/pkgs/build-support/cc-wrapper/cc-wrapper.sh b/pkgs/build-support/cc-wrapper/cc-wrapper.sh index c2e6c1406358f..8a3cfb694b4f2 100644 --- a/pkgs/build-support/cc-wrapper/cc-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/cc-wrapper.sh @@ -134,8 +134,8 @@ fi source @out@/nix-support/add-hardening.sh # Add the flags for the C compiler proper. -extraAfter=($NIX_@infixSalt@_CFLAGS_COMPILE "${hardeningCFlags[@]}") -extraBefore=() +extraAfter=($NIX_@infixSalt@_CFLAGS_COMPILE) +extraBefore=(${hardeningCFlags[@]+"${hardeningCFlags[@]}"}) if [ "$dontLink" != 1 ]; then diff --git a/pkgs/build-support/cc-wrapper/setup-hook.sh b/pkgs/build-support/cc-wrapper/setup-hook.sh index 29a7306b9b7e9..15b84dca27940 100644 --- a/pkgs/build-support/cc-wrapper/setup-hook.sh +++ b/pkgs/build-support/cc-wrapper/setup-hook.sh @@ -147,6 +147,10 @@ export ${role_pre}CXX=@named_cxx@ export CC${role_post}=@named_cc@ export CXX${role_post}=@named_cxx@ +# If unset, assume the default hardening flags. +: ${NIX_HARDENING_ENABLE="fortify stackprotector pic strictoverflow format relro bindnow"} +export NIX_HARDENING_ENABLE + # No local scope in sourced file unset -v role_pre role_post set +u diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index 46df958b83967..7b5f9f7d6b0b2 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -74,6 +74,11 @@ rec { # TODO(@Ericson2314): Make this more modular, and not O(n^2). let supportedHardeningFlags = [ "fortify" "stackprotector" "pie" "pic" "strictoverflow" "format" "relro" "bindnow" ]; + defaultHardeningFlags = lib.remove "pie" supportedHardeningFlags; + enabledHardeningOptions = + if builtins.elem "all" hardeningDisable + then [] + else lib.subtractLists hardeningDisable (defaultHardeningFlags ++ hardeningEnable); # hardeningDisable additionally supports "all". erroneousHardeningFlags = lib.subtractLists supportedHardeningFlags (hardeningEnable ++ lib.remove "all" hardeningDisable); in if builtins.length erroneousHardeningFlags != 0 @@ -179,6 +184,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 = |