-
-
Notifications
You must be signed in to change notification settings - Fork 13.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stdenv: don't include drvs in disallowedRefs as build-time deps. #211783
Conversation
# knowing the out path is sufficient, and the out path can be calculated from | ||
# the derivation without needing to build it, saving time and resources. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how does this interact with CA derivations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should probably work (although a bit fragile) because drv.outPath
will evaluate to a placeholder that will be rewritten just before the build if drv
is part of the derivation closure. Which means that
- If
drv
is part of the closure (because it's refered to somewhere else), then it will do the right thing (theunsafeDiscardStringContext
will morally be a no-op) - Otherwise, the placeholder won't be rewritten, but it's fine since because the derivation isn't part of the build-time closure we know that it can't be in the runtime closure either
should target staging https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#rebasing-between-branches-ie-from-master-to-staging and commit msg should follow the guide |
8db65db
to
ece8640
Compare
ece8640
to
1e5c2bf
Compare
@Artturin: right, I didn't know about staging, that should be fixed now. |
1e5c2bf
to
be21494
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I wonder if nix
's derivation()
builtin should already do the right thing. WDYT of filing a bug there? Sounds reasonable?
CA case is interesting. I think (hope) CA behaviour will not be changed by this context discard: our scanning operation does not need to pull in contents of checked derivations, but will still require building one to get the actual path for CA case. Thus I would guess this change will only help to non-CA builds. Which might be good enough. For CA-enabled builds such scans are probably already incorrect as there is no guarantee that build-CA has different store path from host-CA.
@trofi, agreed. Apparently there was an issue for nix already, but it got dismissed as not a bug, even though I think that the current behaviour is definitely surprising and unproductive and I don't think we should expect people to understand this intricacy and know about Regarding CA derivations, I must admit that I did not look into them enough to know how this would work in that case. |
Good find! Worth adding a link to to the comment around
I think it's OK to ignore it for now. We can always conditionally restore it back. |
@trofi sure! I updated the description to include the reference, I didn't know about the issue when I made the PR. |
be21494
to
bb2bc44
Compare
i added a link to the nix issue |
work for the future
https://nixos.org/manual/nix/stable/release-notes/rl-2.2.html outputChecks."out" = {
# The closure of 'out' must not be larger than 256 MiB.
maxClosureSize = 256 * 1024 * 1024;
# It must not refer to C compiler or to the 'dev' output.
disallowedRequisites = [ stdenv.cc "dev" ];
};
outputChecks."dev" = {
# The 'dev' output must not be larger than 128 KiB.
maxSize = 128 * 1024;
}; perhaps this could even be fixed in nix because there's not many users of structuredAttrs outputChecks yet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
built sway
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
Adding this to stdenv
makes a lot of sense since we can't really fix it in nixpkgs itself
# knowing the out path is sufficient, and the out path can be calculated from | ||
# the derivation without needing to build it, saving time and resources. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should probably work (although a bit fragile) because drv.outPath
will evaluate to a placeholder that will be rewritten just before the build if drv
is part of the derivation closure. Which means that
- If
drv
is part of the closure (because it's refered to somewhere else), then it will do the right thing (theunsafeDiscardStringContext
will morally be a no-op) - Otherwise, the placeholder won't be rewritten, but it's fine since because the derivation isn't part of the build-time closure we know that it can't be in the runtime closure either
disallowedReferences = | ||
map unsafeDerivationToUntrackedOutpath (attrs.disallowedReferences or [ ]); | ||
disallowedRequisites = | ||
map unsafeDerivationToUntrackedOutpath (attrs.disallowedRequisites or [ ]); | ||
allowedReferences = | ||
lib.mapNullable unsafeDerivationToUntrackedOutpath (attrs.allowedReferences or null); | ||
allowedRequisites = | ||
lib.mapNullable unsafeDerivationToUntrackedOutpath (attrs.allowedRequisites or null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe (?) we could reduce the number of rebuilds by only adding these attributes if they were present if attrs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm yes this introduces the attrs to all derivations
nix-repl> bash.allowedRe
bash.allowedReferences
bash.allowedRequisites
nix-repl> bash.disallowedRe
bash.disallowedReferences
bash.disallowedRequisites
Also why do the allowed ref use or null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They use or null
since that is the no-op value for those attrs, an empty list would mean that nothing is allowed in the output.
Agreed for the other point though, we should not add the attributes if they were not present to begin with. I'll push a fix for that tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed an update to fix this and to include the insights on the outPath in the comment.
Nope. It is undoubtedly a bug, but a bug that we can't get rid of in the forseeable future because fixing it would change the hash of some derivations, which is a hard stop for Nix |
Introduces unnecessary attrs to all derivations
Would an opt-in flag into derivation() to enable new behaviour be an option? (like |
It would. It would be less useful though since the main issue here is that it's fairly unintuitive, so people will likely overlook it until it actually bites. |
bb2bc44
to
15655db
Compare
Derivations listed as disallowedReferences or disallowedRequisites, currently end up as build-time dependencies. This is problematic since the disallowed derivations will be built by nix as build-time dependencies, while those derivations might take a very long time to build, or might not even build successfully on the platform used. However, in order to scan for disallowed references in the final output, knowing the out path is sufficient, and the out path can be calculated from the derivation without needing to build it, saving time and resources. While the problem is less severe for allowedReferences and allowedRequisites, since we want the derivation to be built eventually, we would still like to get the error early and without having to wait while nix builds a derivation that might not be used (e.g. if we listed the wrong one).
15655db
to
51acc62
Compare
I think this should really be fixed in Nix. With a proper deprecation strategy this should not be a problem. E.g. introduce a
If you want this to be more expressive you can also do something like We should be brave enough to deprecate problematic behavior, otherwise these problems will never be fixed. |
Noticed content-addressed failures on today's system build. Small reproducer against
Did not look in detail yet. Will spend some time this evening to understand it unless someone gets earlier to it. |
No, that's an unnecessary breaking change.
Deprecate yes, remove no. A subtle difference until it punches you in the face while you're trying to get some old software to work.
I think it'd be ok for supposedly easy changes like this to be linearized into a single |
Fair enough. Instead then (and I think that's what you're implying), the default should be changed for just I think we should rethink this policy though, because not ever being able to deprecate old features really locks us in, requiring maintenance on code that may be only very rarely needed. What if instead we were to not only specify a minimum support Nix version for nixpkgs (backwards compat), but also a maximum (forwards compat, perhaps with a date). Nixpkgs CI should make sure that it works with the minimum supported Nix version, and Nix CI should make sure it works with the earliest nixpkgs that supports its own version. This could be something like supporting Nix versions released around a NixOS release ± 5 years. This does mean that we can't import arbitrary old nixpkgs versions anymore (there should be a check warning/erroring for that in nixpkgs), essentially limiting the time range of nixpkgs versions in a single Nix evaluation. But with a good error message we can present some workarounds:
This also very much relates to NixOS/rfcs#137, I'm abusing this issue as a scratch pad at this point 😅 |
Without the change build for packages that use `disallowedReferences` fails in `contentAddressedByDefault = true` mode: $ nix build -f. ruby_3_1 --arg config '{ contentAddressedByDefault = true; }' ... error: derivation contains an illegal reference specifier '/0j3hif3ni7zl5zhlzzr5q2q23z66136mnzp75pyiqp5c72q14im2' error: 1 dependencies of derivation '/nix/store/39ji7qp225pxvrm8cgvzmyjqsyis2n0h-ruby-3.1.2.drv' failed to build Original intent of NixOS#211783 was to avoid pulling in actual derivation for reference scanning purposes. Unfortunately CA derivations's outputPath are placeholders until they are instantiated. Let's restore string context for CA derivations for now.
Proposed restore of context just for CA derivations as #214044. |
@infinisil I appreciate your care towards the Nix team, but "too much backcompat behavior" is not a problem I perceive in the Nix code. I can build a 2013 zlib (using $ nix-build -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/release-13.10.tar.gz --expr 'with import <nixpkgs> {}; zlib.override(o: { static = true; })' This capability can be a lifesaver if you have to deal with a really bad legacy binary in some academic, corporate or government environment or whatever. It's even useful for running old binary linux games. Being able to do this (with care of course) is uniquely valuable.
This prevents installing anything old alongside anything new in a single expression.
That's a lot of effort for very little gain (removing a couple of lines of code from Nix). Furthermore, creating and implementing a policy for breaking stuff is also work. A bad kind of work that will make nobody happy. Let's not make new problems if we don't have to. We can revisit this when compatibility becomes a proper burden, but until then, enjoy a working Nix and Nixpkgs. |
Derivations listed as
disallowedReferences
ordisallowedRequisites
, currently end up as build-time dependencies.This is problematic since the disallowed derivations will be built by nix as build-time dependencies, while those derivations might take a very long time to build, or might not even build successfully on the platform used. However, in order to scan for disallowed references in the final output, knowing the out path is sufficient, and the out path can be calculated from the derivation without needing to build it, saving time and resources.
While the problem is less severe for
allowedReferences
andallowedRequisites
, since we want the derivation to be built eventually, we would still like to get the error early and without having to wait while nix builds a derivation that might not be used (e.g. if we listed the wrong one).Before this PR:
After this PR:
Note how in the first case
busybox
ends up as a build-time dependency, and will be built or substituted if it's not yet in the nix store. In the second case, with the changes in this PR, it no longer ends up as a build-time dependency and won't be built or substituted.There is also an issue for nix itself to fix this on a lower level, where the approach implemented in this PR was suggested.
I don't agree with the conclusion on that issue and I think that it is a perfectly sensible use case to disallow references so that they cannot be accidentally included in the future and that we should not expect from our users to have to use
unsafeDiscardStringContext
to get the correct behaviour in that case.Description of changes
Things done
sandbox = true
set innix.conf
? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)nixos/doc/manual/md-to-db.sh
to update generated release notes