Skip to content

Commit 1a5bd69

Browse files
committed
mkDerivation, bintools-wrapper: move defaultHardeningFlags determination to bintools-wrapper
this makes it a lot easier to create a modified stdenv with a different set of defaultHardeningFlags and as a bonus allows us to inject the correct defaultHardeningFlags into toolchain wrapper scripts, reducing repetition. while most hardening flags are arguably more of a compiler thing, it works better to put them in bintools-wrapper because cc-wrapper can easily refer to bintools but not vice-versa. mkDerivation can still easily refer to either when it is constructed. this also switches fortran-hook.sh to use the same defaults for NIX_HARDENING_ENABLE as for C. previously NIX_HARDENING_ENABLE defaults were apparently used to avoid passing problematic flags to a fortran compiler, but this falls apart as soon as mkDerivation sets its own NIX_HARDENING_ENABLE - cc.hardeningUnsupportedFlags is a more appropriate mechanism for this as it actively filters out flags from being used by the wrapper, so switch to using that instead. this is still an imperfect mechanism because it doesn't handle a compiler which has both langFortran *and* langC very well - applying the superset of the two's hardeningUnsupportedFlags to either compiler's invocation. however this is nothing new - cc-wrapper already poorly handles a langFortran+langC compiler, applying two setup hooks that have contradictory options.
1 parent 229cde6 commit 1a5bd69

File tree

8 files changed

+53
-20
lines changed

8 files changed

+53
-20
lines changed

pkgs/build-support/bintools-wrapper/default.nix

+25
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,28 @@
3333
, useMacosReexportHack ? false
3434
, wrapGas ? false
3535

36+
# Note: the hardening flags are part of the bintools-wrapper, rather than
37+
# the cc-wrapper, because a few of them are handled by the linker.
38+
, defaultHardeningFlags ? with stdenvNoCC; [
39+
"bindnow"
40+
"format"
41+
"fortify"
42+
"fortify3"
43+
"pic"
44+
"relro"
45+
"stackprotector"
46+
"strictoverflow"
47+
] ++ lib.optional (
48+
# Musl-based platforms will keep "pie", other platforms will not.
49+
# If you change this, make sure to update section `{#sec-hardening-in-nixpkgs}`
50+
# in the nixpkgs manual to inform users about the defaults.
51+
targetPlatform.libc == "musl"
52+
# Except when:
53+
# - static aarch64, where compilation works, but produces segfaulting dynamically linked binaries.
54+
# - static armv7l, where compilation fails.
55+
&& !(hostPlatform.isAarch && hostPlatform.isStatic)
56+
) "pie"
57+
3658
# Darwin code signing support utilities
3759
, postLinkSignHook ? null, signingUtils ? null
3860
}:
@@ -124,6 +146,8 @@ stdenv.mkDerivation {
124146
(setenv "NIX_LDFLAGS_${suffixSalt}" (concat (getenv "NIX_LDFLAGS_${suffixSalt}") " -L" arg "/lib64"))))
125147
'(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)}))
126148
'';
149+
150+
inherit defaultHardeningFlags;
127151
};
128152

129153
dontBuild = true;
@@ -380,6 +404,7 @@ stdenv.mkDerivation {
380404
wrapperName = "BINTOOLS_WRAPPER";
381405
inherit dynamicLinker targetPrefix suffixSalt coreutils_bin;
382406
inherit bintools_bin libc_bin libc_dev libc_lib;
407+
default_hardening_flags_str = builtins.toString defaultHardeningFlags;
383408
};
384409

385410
meta =

pkgs/build-support/bintools-wrapper/setup-hook.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ do
6565
done
6666

6767
# If unset, assume the default hardening flags.
68-
: ${NIX_HARDENING_ENABLE="fortify stackprotector pic strictoverflow format relro bindnow"}
68+
: ${NIX_HARDENING_ENABLE="@default_hardening_flags_str@"}
6969
export NIX_HARDENING_ENABLE
7070

7171
# No local scope in sourced file

pkgs/build-support/cc-wrapper/add-hardening.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ if [[ -n "${hardeningEnableMap[fortify3]-}" ]]; then
3232
fi
3333

3434
if (( "${NIX_DEBUG:-0}" >= 1 )); then
35-
declare -a allHardeningFlags=(fortify stackprotector pie pic strictoverflow format)
35+
declare -a allHardeningFlags=(fortify fortify3 stackprotector pie pic strictoverflow format)
3636
declare -A hardeningDisableMap=()
3737

3838
# Determine which flags were effectively disabled so we can report below.

pkgs/build-support/cc-wrapper/default.nix

+5
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ let
218218
then guess
219219
else null;
220220

221+
defaultHardeningFlags = bintools.defaultHardeningFlags or [];
222+
221223
darwinPlatformForCC = optionalString stdenv.targetPlatform.isDarwin (
222224
if (targetPlatform.darwinPlatform == "macos" && isGNU) then "macosx"
223225
else targetPlatform.darwinPlatform
@@ -271,6 +273,8 @@ stdenv.mkDerivation {
271273
inherit expand-response-params;
272274

273275
inherit nixSupport;
276+
277+
inherit defaultHardeningFlags;
274278
};
275279

276280
dontBuild = true;
@@ -706,6 +710,7 @@ stdenv.mkDerivation {
706710
inherit suffixSalt coreutils_bin bintools;
707711
inherit libc_bin libc_dev libc_lib;
708712
inherit darwinPlatformForCC darwinMinVersion darwinMinVersionVariable;
713+
default_hardening_flags_str = builtins.toString defaultHardeningFlags;
709714
};
710715

711716
meta =

pkgs/build-support/cc-wrapper/fortran-hook.sh

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ getTargetRoleWrapper
44
export FC${role_post}=@named_fc@
55

66
# If unset, assume the default hardening flags.
7-
# These are different for fortran.
8-
: ${NIX_HARDENING_ENABLE="stackprotector pic strictoverflow relro bindnow"}
7+
: ${NIX_HARDENING_ENABLE="@default_hardening_flags_str@"}
98
export NIX_HARDENING_ENABLE
109

1110
unset -v role_post

pkgs/build-support/cc-wrapper/setup-hook.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export CC${role_post}=@named_cc@
111111
export CXX${role_post}=@named_cxx@
112112

113113
# If unset, assume the default hardening flags.
114-
: ${NIX_HARDENING_ENABLE="fortify fortify3 stackprotector pic strictoverflow format relro bindnow"}
114+
: ${NIX_HARDENING_ENABLE="@default_hardening_flags_str@"}
115115
export NIX_HARDENING_ENABLE
116116

117117
# No local scope in sourced file

pkgs/development/compilers/gcc/default.nix

+3-2
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,9 @@ lib.pipe ((callFile ./common/builder.nix {}) ({
406406
passthru = {
407407
inherit langC langCC langObjC langObjCpp langAda langFortran langGo langD langJava version;
408408
isGNU = true;
409-
} // lib.optionalAttrs (!atLeast12) {
410-
hardeningUnsupportedFlags = lib.optionals is48 [ "stackprotector" ] ++ [ "fortify3" ];
409+
hardeningUnsupportedFlags = lib.optional is48 "stackprotector"
410+
++ lib.optional (!atLeast12) "fortify3"
411+
++ lib.optionals (langFortran) [ "fortify" "format" ];
411412
};
412413

413414
enableParallelBuilding = true;

pkgs/stdenv/generic/make-derivation.nix

+16-13
Original file line numberDiff line numberDiff line change
@@ -239,23 +239,26 @@ let
239239
# disabling fortify implies fortify3 should also be disabled
240240
then unique (hardeningDisable ++ [ "fortify3" ])
241241
else hardeningDisable;
242-
supportedHardeningFlags = [ "fortify" "fortify3" "stackprotector" "pie" "pic" "strictoverflow" "format" "relro" "bindnow" ];
243-
# Musl-based platforms will keep "pie", other platforms will not.
244-
# If you change this, make sure to update section `{#sec-hardening-in-nixpkgs}`
245-
# in the nixpkgs manual to inform users about the defaults.
246-
defaultHardeningFlags = if stdenv.hostPlatform.isMusl &&
247-
# Except when:
248-
# - static aarch64, where compilation works, but produces segfaulting dynamically linked binaries.
249-
# - static armv7l, where compilation fails.
250-
!(stdenv.hostPlatform.isAarch && stdenv.hostPlatform.isStatic)
251-
then supportedHardeningFlags
252-
else remove "pie" supportedHardeningFlags;
242+
knownHardeningFlags = [
243+
"bindnow"
244+
"format"
245+
"fortify"
246+
"fortify3"
247+
"pic"
248+
"pie"
249+
"relro"
250+
"stackprotector"
251+
"strictoverflow"
252+
];
253+
defaultHardeningFlags = stdenv.cc.defaultHardeningFlags or
254+
# fallback safe-ish set of flags
255+
(remove "pie" knownHardeningFlags);
253256
enabledHardeningOptions =
254257
if builtins.elem "all" hardeningDisable'
255258
then []
256259
else subtractLists hardeningDisable' (defaultHardeningFlags ++ hardeningEnable);
257260
# hardeningDisable additionally supports "all".
258-
erroneousHardeningFlags = subtractLists supportedHardeningFlags (hardeningEnable ++ remove "all" hardeningDisable);
261+
erroneousHardeningFlags = subtractLists knownHardeningFlags (hardeningEnable ++ remove "all" hardeningDisable);
259262

260263
checkDependencyList = checkDependencyList' [];
261264
checkDependencyList' = positions: name: deps: flip imap1 deps (index: dep:
@@ -264,7 +267,7 @@ let
264267
else throw "Dependency is not of a valid type: ${concatMapStrings (ix: "element ${toString ix} of ") ([index] ++ positions)}${name} for ${attrs.name or attrs.pname}");
265268
in if builtins.length erroneousHardeningFlags != 0
266269
then abort ("mkDerivation was called with unsupported hardening flags: " + lib.generators.toPretty {} {
267-
inherit erroneousHardeningFlags hardeningDisable hardeningEnable supportedHardeningFlags;
270+
inherit erroneousHardeningFlags hardeningDisable hardeningEnable knownHardeningFlags;
268271
})
269272
else let
270273
doCheck = doCheck';

0 commit comments

Comments
 (0)