Merge pull request #28029 from cstrahan/hardening-fix
hardening: fix #18995
This commit is contained in:
commit
0dbc006760
|
@ -5,6 +5,7 @@ var_templates_list=(
|
||||||
NIX+LDFLAGS_BEFORE
|
NIX+LDFLAGS_BEFORE
|
||||||
NIX+LDFLAGS_AFTER
|
NIX+LDFLAGS_AFTER
|
||||||
NIX+LDFLAGS_HARDEN
|
NIX+LDFLAGS_HARDEN
|
||||||
|
NIX+HARDENING_ENABLE
|
||||||
)
|
)
|
||||||
var_templates_bool=(
|
var_templates_bool=(
|
||||||
NIX+SET_BUILD_ID
|
NIX+SET_BUILD_ID
|
||||||
|
@ -23,10 +24,10 @@ if [ "${NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_TARGET:-}" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for var in "${var_templates_list[@]}"; do
|
for var in "${var_templates_list[@]}"; do
|
||||||
mangleVarList "$var" "${role_infixes[@]}"
|
mangleVarList "$var" ${role_infixes[@]+"${role_infixes[@]}"}
|
||||||
done
|
done
|
||||||
for var in "${var_templates_bool[@]}"; do
|
for var in "${var_templates_bool[@]}"; do
|
||||||
mangleVarBool "$var" "${role_infixes[@]}"
|
mangleVarBool "$var" ${role_infixes[@]+"${role_infixes[@]}"}
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -e @out@/nix-support/libc-ldflags ]; then
|
if [ -e @out@/nix-support/libc-ldflags ]; then
|
||||||
|
|
|
@ -1,53 +1,58 @@
|
||||||
hardeningFlags=(relro bindnow)
|
declare -a hardeningLDFlags=()
|
||||||
# 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 hardeningDisableMap
|
declare -A hardeningEnableMap=()
|
||||||
|
|
||||||
# Intentionally word-split in case 'hardeningDisable' is defined in Nix.
|
# Intentionally word-split in case 'NIX_HARDENING_ENABLE' is defined in Nix. The
|
||||||
for flag in ${hardeningDisable[@]:-IGNORED_KEY} @hardening_unsupported_flags@
|
# array expansion also prevents undefined variables from causing trouble with
|
||||||
do
|
# `set -u`.
|
||||||
hardeningDisableMap[$flag]=1
|
for flag in ${NIX_@infixSalt@_HARDENING_ENABLE-}; do
|
||||||
|
hardeningEnableMap["$flag"]=1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Remove unsupported flags.
|
||||||
|
for flag in @hardening_unsupported_flags@; do
|
||||||
|
unset -v hardeningEnableMap["$flag"]
|
||||||
done
|
done
|
||||||
|
|
||||||
if (( "${NIX_DEBUG:-0}" >= 1 )); then
|
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
|
printf 'HARDENING: disabled flags:' >&2
|
||||||
(( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2
|
(( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2
|
||||||
echo >&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;
|
echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2;
|
||||||
fi
|
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
|
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
|
||||||
|
|
|
@ -57,8 +57,8 @@ fi
|
||||||
|
|
||||||
source @out@/nix-support/add-hardening.sh
|
source @out@/nix-support/add-hardening.sh
|
||||||
|
|
||||||
extraAfter=("${hardeningLDFlags[@]}")
|
extraAfter=()
|
||||||
extraBefore=()
|
extraBefore=(${hardeningLDFlags[@]+"${hardeningLDFlags[@]}"})
|
||||||
|
|
||||||
if [ -z "${NIX_@infixSalt@_LDFLAGS_SET:-}" ]; then
|
if [ -z "${NIX_@infixSalt@_LDFLAGS_SET:-}" ]; then
|
||||||
extraAfter+=($NIX_@infixSalt@_LDFLAGS)
|
extraAfter+=($NIX_@infixSalt@_LDFLAGS)
|
||||||
|
|
|
@ -83,6 +83,10 @@ do
|
||||||
fi
|
fi
|
||||||
done
|
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
|
# No local scope in sourced file
|
||||||
unset -v role_pre role_post cmd upper_case
|
unset -v role_pre role_post cmd upper_case
|
||||||
set +u
|
set +u
|
||||||
|
|
|
@ -30,10 +30,10 @@ fi
|
||||||
# We need to mangle names for hygiene, but also take parameters/overrides
|
# We need to mangle names for hygiene, but also take parameters/overrides
|
||||||
# from the environment.
|
# from the environment.
|
||||||
for var in "${var_templates_list[@]}"; do
|
for var in "${var_templates_list[@]}"; do
|
||||||
mangleVarList "$var" "${role_infixes[@]}"
|
mangleVarList "$var" ${role_infixes[@]+"${role_infixes[@]}"}
|
||||||
done
|
done
|
||||||
for var in "${var_templates_bool[@]}"; do
|
for var in "${var_templates_bool[@]}"; do
|
||||||
mangleVarBool "$var" "${role_infixes[@]}"
|
mangleVarBool "$var" ${role_infixes[@]+"${role_infixes[@]}"}
|
||||||
done
|
done
|
||||||
|
|
||||||
# `-B@out@/bin' forces cc to use ld-wrapper.sh when calling ld.
|
# `-B@out@/bin' forces cc to use ld-wrapper.sh when calling ld.
|
||||||
|
|
|
@ -1,67 +1,72 @@
|
||||||
hardeningFlags=(fortify stackprotector pic strictoverflow format relro bindnow)
|
declare -a hardeningCFlags=()
|
||||||
# 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 hardeningDisableMap
|
declare -A hardeningEnableMap=()
|
||||||
|
|
||||||
# Intentionally word-split in case 'hardeningDisable' is defined in Nix.
|
# Intentionally word-split in case 'NIX_HARDENING_ENABLE' is defined in Nix. The
|
||||||
for flag in ${hardeningDisable[@]:-IGNORED_KEY} @hardening_unsupported_flags@
|
# array expansion also prevents undefined variables from causing trouble with
|
||||||
do
|
# `set -u`.
|
||||||
hardeningDisableMap[$flag]=1
|
for flag in ${NIX_@infixSalt@_HARDENING_ENABLE-}; do
|
||||||
|
hardeningEnableMap["$flag"]=1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Remove unsupported flags.
|
||||||
|
for flag in @hardening_unsupported_flags@; do
|
||||||
|
unset -v hardeningEnableMap["$flag"]
|
||||||
done
|
done
|
||||||
|
|
||||||
if (( "${NIX_DEBUG:-0}" >= 1 )); then
|
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
|
printf 'HARDENING: disabled flags:' >&2
|
||||||
(( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2
|
(( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2
|
||||||
echo >&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;
|
echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2;
|
||||||
fi
|
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
|
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
|
||||||
|
|
|
@ -134,8 +134,8 @@ fi
|
||||||
source @out@/nix-support/add-hardening.sh
|
source @out@/nix-support/add-hardening.sh
|
||||||
|
|
||||||
# Add the flags for the C compiler proper.
|
# Add the flags for the C compiler proper.
|
||||||
extraAfter=($NIX_@infixSalt@_CFLAGS_COMPILE "${hardeningCFlags[@]}")
|
extraAfter=($NIX_@infixSalt@_CFLAGS_COMPILE)
|
||||||
extraBefore=()
|
extraBefore=(${hardeningCFlags[@]+"${hardeningCFlags[@]}"})
|
||||||
|
|
||||||
if [ "$dontLink" != 1 ]; then
|
if [ "$dontLink" != 1 ]; then
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,10 @@ export ${role_pre}CXX=@named_cxx@
|
||||||
export CC${role_post}=@named_cc@
|
export CC${role_post}=@named_cc@
|
||||||
export CXX${role_post}=@named_cxx@
|
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
|
# No local scope in sourced file
|
||||||
unset -v role_pre role_post
|
unset -v role_pre role_post
|
||||||
set +u
|
set +u
|
||||||
|
|
|
@ -74,6 +74,11 @@ rec {
|
||||||
# TODO(@Ericson2314): Make this more modular, and not O(n^2).
|
# TODO(@Ericson2314): Make this more modular, and not O(n^2).
|
||||||
let
|
let
|
||||||
supportedHardeningFlags = [ "fortify" "stackprotector" "pie" "pic" "strictoverflow" "format" "relro" "bindnow" ];
|
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".
|
# hardeningDisable additionally supports "all".
|
||||||
erroneousHardeningFlags = lib.subtractLists supportedHardeningFlags (hardeningEnable ++ lib.remove "all" hardeningDisable);
|
erroneousHardeningFlags = lib.subtractLists supportedHardeningFlags (hardeningEnable ++ lib.remove "all" hardeningDisable);
|
||||||
in if builtins.length erroneousHardeningFlags != 0
|
in if builtins.length erroneousHardeningFlags != 0
|
||||||
|
@ -179,6 +184,8 @@ rec {
|
||||||
++ optional (elem "host" configurePlatforms) "--host=${stdenv.hostPlatform.config}"
|
++ optional (elem "host" configurePlatforms) "--host=${stdenv.hostPlatform.config}"
|
||||||
++ optional (elem "target" configurePlatforms) "--target=${stdenv.targetPlatform.config}";
|
++ optional (elem "target" configurePlatforms) "--target=${stdenv.targetPlatform.config}";
|
||||||
|
|
||||||
|
} // lib.optionalAttrs (hardeningDisable != [] || hardeningEnable != []) {
|
||||||
|
NIX_HARDENING_ENABLE = enabledHardeningOptions;
|
||||||
} // lib.optionalAttrs (stdenv.buildPlatform.isDarwin) {
|
} // lib.optionalAttrs (stdenv.buildPlatform.isDarwin) {
|
||||||
# TODO: remove lib.unique once nix has a list canonicalization primitive
|
# TODO: remove lib.unique once nix has a list canonicalization primitive
|
||||||
__sandboxProfile =
|
__sandboxProfile =
|
||||||
|
|
Loading…
Reference in New Issue