nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1declare -a hardeningCFlagsAfter=()
2declare -a hardeningCFlagsBefore=()
3
4declare -A hardeningEnableMap=()
5
6# Intentionally word-split in case 'NIX_HARDENING_ENABLE' is defined in Nix. The
7# array expansion also prevents undefined variables from causing trouble with
8# `set -u`.
9for flag in ${NIX_HARDENING_ENABLE_@suffixSalt@-}; do
10 hardeningEnableMap["$flag"]=1
11done
12
13
14# fortify3 implies fortify enablement - make explicit before
15# we filter unsupported flags because unsupporting fortify3
16# doesn't mean we should unsupport fortify too
17if [[ -n "${hardeningEnableMap[fortify3]-}" ]]; then
18 hardeningEnableMap["fortify"]=1
19fi
20
21# strictflexarrays3 implies strictflexarrays1 enablement - make explicit before
22# we filter unsupported flags because unsupporting strictflexarrays3
23# doesn't mean we should unsupport strictflexarrays1 too
24if [[ -n "${hardeningEnableMap[strictflexarrays3]-}" ]]; then
25 hardeningEnableMap["strictflexarrays1"]=1
26fi
27
28
29# Remove unsupported flags.
30for flag in @hardening_unsupported_flags@; do
31 unset -v "hardeningEnableMap[$flag]"
32 # fortify being unsupported implies fortify3 is unsupported
33 if [[ "$flag" = 'fortify' ]] ; then
34 unset -v "hardeningEnableMap['fortify3']"
35 fi
36 # strictflexarrays1 being unsupported implies strictflexarrays3 is unsupported
37 if [[ "$flag" = 'strictflexarrays1' ]] ; then
38 unset -v "hardeningEnableMap['strictflexarrays3']"
39 fi
40done
41
42
43# now make fortify and fortify3 mutually exclusive
44if [[ -n "${hardeningEnableMap[fortify3]-}" ]]; then
45 unset -v "hardeningEnableMap['fortify']"
46fi
47
48# now make strictflexarrays1 and strictflexarrays3 mutually exclusive
49if [[ -n "${hardeningEnableMap[strictflexarrays3]-}" ]]; then
50 unset -v "hardeningEnableMap['strictflexarrays1']"
51fi
52
53
54if (( "${NIX_DEBUG:-0}" >= 1 )); then
55 declare -a allHardeningFlags=(fortify fortify3 shadowstack stackprotector stackclashprotection nostrictaliasing pacret strictflexarrays1 strictflexarrays3 pie pic strictoverflow format trivialautovarinit zerocallusedregs)
56 declare -A hardeningDisableMap=()
57
58 # Determine which flags were effectively disabled so we can report below.
59 for flag in "${allHardeningFlags[@]}"; do
60 if [[ -z "${hardeningEnableMap[$flag]-}" ]]; then
61 hardeningDisableMap["$flag"]=1
62 fi
63 done
64
65 printf 'HARDENING: disabled flags:' >&2
66 (( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2
67 echo >&2
68
69 if (( "${#hardeningEnableMap[@]}" )); then
70 echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2;
71 fi
72fi
73
74for flag in "${!hardeningEnableMap[@]}"; do
75 case $flag in
76 fortify | fortify3)
77 # Use -U_FORTIFY_SOURCE to avoid warnings on toolchains that explicitly
78 # set -D_FORTIFY_SOURCE=0 (like 'clang -fsanitize=address').
79 hardeningCFlagsBefore+=('-O2' '-U_FORTIFY_SOURCE')
80 # Unset any _FORTIFY_SOURCE values the command-line may have set before
81 # enforcing our own value, avoiding (potentially fatal) redefinition
82 # warnings
83 hardeningCFlagsAfter+=('-U_FORTIFY_SOURCE')
84 case $flag in
85 fortify)
86 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling fortify >&2; fi
87 hardeningCFlagsAfter+=('-D_FORTIFY_SOURCE=2')
88 ;;
89 fortify3)
90 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling fortify3 >&2; fi
91 hardeningCFlagsAfter+=('-D_FORTIFY_SOURCE=3')
92 ;;
93 *)
94 # Ignore unsupported.
95 ;;
96 esac
97 ;;
98 shadowstack)
99 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling shadowstack >&2; fi
100 hardeningCFlagsBefore+=('-fcf-protection=return')
101 ;;
102 strictflexarrays1)
103 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling strictflexarrays1 >&2; fi
104 hardeningCFlagsBefore+=('-fstrict-flex-arrays=1')
105 ;;
106 strictflexarrays3)
107 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling strictflexarrays3 >&2; fi
108 hardeningCFlagsBefore+=('-fstrict-flex-arrays=3')
109 ;;
110 pacret)
111 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling pacret >&2; fi
112 hardeningCFlagsBefore+=('-mbranch-protection=pac-ret')
113 ;;
114 stackprotector)
115 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling stackprotector >&2; fi
116 hardeningCFlagsBefore+=('-fstack-protector-strong' '--param' 'ssp-buffer-size=4')
117 ;;
118 stackclashprotection)
119 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling stack-clash-protection >&2; fi
120 hardeningCFlagsBefore+=('-fstack-clash-protection')
121 ;;
122 nostrictaliasing)
123 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling nostrictaliasing >&2; fi
124 hardeningCFlagsBefore+=('-fno-strict-aliasing')
125 ;;
126 pie)
127 # NB: we do not use `+=` here, because PIE flags must occur before any PIC flags
128 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling CFlags -fPIE >&2; fi
129 hardeningCFlagsBefore=('-fPIE' "${hardeningCFlagsBefore[@]}")
130 if [[ ! (" ${params[*]} " =~ " -shared " || " ${params[*]} " =~ " -static ") ]]; then
131 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling LDFlags -pie >&2; fi
132 hardeningCFlagsBefore=('-pie' "${hardeningCFlagsBefore[@]}")
133 fi
134 ;;
135 pic)
136 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling pic >&2; fi
137 hardeningCFlagsBefore+=('-fPIC')
138 ;;
139 strictoverflow)
140 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling strictoverflow >&2; fi
141 if (( @isClang@ )); then
142 # In Clang, -fno-strict-overflow only serves to set -fwrapv and is
143 # reported as an unused CLI argument if -fwrapv or -fno-wrapv is set
144 # explicitly, so we side step that by doing the conversion here.
145 #
146 # See: https://github.com/llvm/llvm-project/blob/llvmorg-16.0.6/clang/lib/Driver/ToolChains/Clang.cpp#L6315
147 #
148 hardeningCFlagsBefore+=('-fwrapv')
149 else
150 hardeningCFlagsBefore+=('-fno-strict-overflow')
151 fi
152 ;;
153 trivialautovarinit)
154 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling trivialautovarinit >&2; fi
155 hardeningCFlagsBefore+=('-ftrivial-auto-var-init=pattern')
156 ;;
157 format)
158 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling format >&2; fi
159 hardeningCFlagsBefore+=('-Wformat' '-Wformat-security' '-Werror=format-security')
160 ;;
161 zerocallusedregs)
162 if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling zerocallusedregs >&2; fi
163 hardeningCFlagsBefore+=('-fzero-call-used-regs=used-gpr')
164 ;;
165 *)
166 # Ignore unsupported. Checked in Nix that at least *some*
167 # tool supports each flag.
168 ;;
169 esac
170done