2023-10-09 19:29:22 +00:00
declare -a hardeningCFlagsAfter = ( )
declare -a hardeningCFlagsBefore = ( )
2020-04-24 23:36:52 +00:00
declare -A hardeningEnableMap = ( )
# 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`.
2020-06-18 07:06:33 +00:00
for flag in ${ NIX_HARDENING_ENABLE_ @suffixSalt@- } ; do
2020-04-24 23:36:52 +00:00
hardeningEnableMap[ " $flag " ] = 1
done
2023-11-16 04:20:00 +00:00
# fortify3 implies fortify enablement - make explicit before
# we filter unsupported flags because unsupporting fortify3
# doesn't mean we should unsupport fortify too
if [ [ -n " ${ hardeningEnableMap [fortify3]- } " ] ] ; then
hardeningEnableMap[ "fortify" ] = 1
fi
2020-04-24 23:36:52 +00:00
# Remove unsupported flags.
for flag in @hardening_unsupported_flags@; do
unset -v " hardeningEnableMap[ $flag ] "
2023-03-15 16:39:30 +00:00
# fortify being unsupported implies fortify3 is unsupported
if [ [ " $flag " = 'fortify' ] ] ; then
unset -v "hardeningEnableMap['fortify3']"
fi
2020-04-24 23:36:52 +00:00
done
2023-11-16 04:20:00 +00:00
# now make fortify and fortify3 mutually exclusive
2023-03-15 16:39:30 +00:00
if [ [ -n " ${ hardeningEnableMap [fortify3]- } " ] ] ; then
unset -v "hardeningEnableMap['fortify']"
fi
2020-04-24 23:36:52 +00:00
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then
2024-09-19 14:19:46 +00:00
declare -a allHardeningFlags = ( fortify fortify3 shadowstack stackprotector stackclashprotection pacret pie pic strictoverflow format trivialautovarinit zerocallusedregs)
2020-04-24 23:36:52 +00:00
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
if ( ( " ${# hardeningEnableMap [@] } " ) ) ; then
echo 'HARDENING: Is active (not completely disabled with "all" flag)' >& 2;
fi
fi
for flag in " ${ !hardeningEnableMap[@] } " ; do
case $flag in
2023-03-15 16:39:30 +00:00
fortify | fortify3)
2022-10-30 15:09:59 +00:00
# Use -U_FORTIFY_SOURCE to avoid warnings on toolchains that explicitly
# set -D_FORTIFY_SOURCE=0 (like 'clang -fsanitize=address').
2023-10-09 19:29:22 +00:00
hardeningCFlagsBefore += ( '-O2' '-U_FORTIFY_SOURCE' )
# Unset any _FORTIFY_SOURCE values the command-line may have set before
# enforcing our own value, avoiding (potentially fatal) redefinition
# warnings
hardeningCFlagsAfter += ( '-U_FORTIFY_SOURCE' )
2023-03-15 16:39:30 +00:00
case $flag in
fortify)
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling fortify >& 2; fi
2023-10-09 19:29:22 +00:00
hardeningCFlagsAfter += ( '-D_FORTIFY_SOURCE=2' )
2023-03-15 16:39:30 +00:00
; ;
fortify3)
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling fortify3 >& 2; fi
2023-10-09 19:29:22 +00:00
hardeningCFlagsAfter += ( '-D_FORTIFY_SOURCE=3' )
2023-03-15 16:39:30 +00:00
; ;
*)
# Ignore unsupported.
; ;
esac
2020-04-24 23:36:52 +00:00
; ;
2024-09-19 14:19:46 +00:00
shadowstack)
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling shadowstack >& 2; fi
hardeningCFlagsBefore += ( '-fcf-protection=return' )
; ;
pacret)
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling pacret >& 2; fi
hardeningCFlagsBefore += ( '-mbranch-protection=pac-ret' )
; ;
2020-04-24 23:36:52 +00:00
stackprotector)
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling stackprotector >& 2; fi
2023-10-09 19:29:22 +00:00
hardeningCFlagsBefore += ( '-fstack-protector-strong' '--param' 'ssp-buffer-size=4' )
2020-04-24 23:36:52 +00:00
; ;
2024-07-27 06:49:29 +00:00
stackclashprotection)
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling stack-clash-protection >& 2; fi
hardeningCFlagsBefore += ( '-fstack-clash-protection' )
; ;
2020-04-24 23:36:52 +00:00
pie)
2021-10-06 13:57:05 +00:00
# NB: we do not use `+=` here, because PIE flags must occur before any PIC flags
2020-04-24 23:36:52 +00:00
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling CFlags -fPIE >& 2; fi
2023-10-09 19:29:22 +00:00
hardeningCFlagsBefore = ( '-fPIE' " ${ hardeningCFlagsBefore [@] } " )
2023-07-15 17:15:38 +00:00
if [ [ ! ( " ${ params [*] } " = ~ " -shared " || " ${ params [*] } " = ~ " -static " ) ] ] ; then
2020-04-24 23:36:52 +00:00
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling LDFlags -pie >& 2; fi
2023-10-09 19:29:22 +00:00
hardeningCFlagsBefore = ( '-pie' " ${ hardeningCFlagsBefore [@] } " )
2020-04-24 23:36:52 +00:00
fi
; ;
pic)
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling pic >& 2; fi
2023-10-09 19:29:22 +00:00
hardeningCFlagsBefore += ( '-fPIC' )
2020-04-24 23:36:52 +00:00
; ;
strictoverflow)
2023-08-10 07:59:29 +00:00
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling strictoverflow >& 2; fi
if ( ( @isClang@ ) ) ; then
# In Clang, -fno-strict-overflow only serves to set -fwrapv and is
# reported as an unused CLI argument if -fwrapv or -fno-wrapv is set
# explicitly, so we side step that by doing the conversion here.
#
# See: https://github.com/llvm/llvm-project/blob/llvmorg-16.0.6/clang/lib/Driver/ToolChains/Clang.cpp#L6315
#
2023-10-09 19:29:22 +00:00
hardeningCFlagsBefore += ( '-fwrapv' )
2023-08-10 07:59:29 +00:00
else
2023-10-09 19:29:22 +00:00
hardeningCFlagsBefore += ( '-fno-strict-overflow' )
2023-08-10 07:59:29 +00:00
fi
2020-04-24 23:36:52 +00:00
; ;
2024-04-21 15:54:59 +00:00
trivialautovarinit)
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling trivialautovarinit >& 2; fi
hardeningCFlagsBefore += ( '-ftrivial-auto-var-init=pattern' )
; ;
2020-04-24 23:36:52 +00:00
format)
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling format >& 2; fi
2023-10-09 19:29:22 +00:00
hardeningCFlagsBefore += ( '-Wformat' '-Wformat-security' '-Werror=format-security' )
2020-04-24 23:36:52 +00:00
; ;
2024-02-29 20:09:43 +00:00
zerocallusedregs)
if ( ( " ${ NIX_DEBUG :- 0 } " >= 1 ) ) ; then echo HARDENING: enabling zerocallusedregs >& 2; fi
hardeningCFlagsBefore += ( '-fzero-call-used-regs=used-gpr' )
; ;
2020-04-24 23:36:52 +00:00
*)
# Ignore unsupported. Checked in Nix that at least *some*
# tool supports each flag.
; ;
esac
done