Skip to content

Commit

Permalink
EvalState::realiseContext(): Allow access to the entire closure
Browse files Browse the repository at this point in the history
Fixes #11030.

(cherry picked from commit 08361f0)

# Conflicts:
#	src/libexpr/eval.cc
#	tests/functional/import-from-derivation.nix
#	tests/functional/import-from-derivation.sh
  • Loading branch information
edolstra authored and mergify[bot] committed Dec 16, 2024
1 parent 6a791e9 commit f986f7e
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 5 deletions.
14 changes: 14 additions & 0 deletions src/libexpr/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,16 @@ void EvalState::allowPath(const StorePath & storePath)
rootFS2->allowPrefix(CanonPath(store->toRealPath(storePath)));
}

void EvalState::allowClosure(const StorePath & storePath)
{
if (!rootFS.dynamic_pointer_cast<AllowListSourceAccessor>()) return;

StorePathSet closure;
store->computeFSClosure(storePath, closure);
for (auto & p : closure)
allowPath(p);
}

void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value & v)
{
allowPath(storePath);
Expand Down Expand Up @@ -3113,10 +3123,14 @@ std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Pa
allowPath(path);
if (store->isInStore(path)) {
try {
<<<<<<< HEAD
StorePathSet closure;
store->computeFSClosure(store->toStorePath(path).first, closure);
for (auto & p : closure)
allowPath(p);
=======
allowClosure(store->toStorePath(path.path.abs()).first);
>>>>>>> 08361f031 (EvalState::realiseContext(): Allow access to the entire closure)
} catch (InvalidPath &) { }
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/libexpr/eval.hh
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,11 @@ public:
*/
void allowPath(const StorePath & storePath);

/**
* Allow access to the closure of a store path.
*/
void allowClosure(const StorePath & storePath);

/**
* Allow access to a store path and return it as a string.
*/
Expand Down
8 changes: 3 additions & 5 deletions src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,9 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS
if (store != buildStore) copyClosure(*buildStore, *store, outputsToCopyAndAllow);

if (isIFD) {
for (auto & outputPath : outputsToCopyAndAllow) {
/* Add the output of this derivations to the allowed
paths. */
allowPath(outputPath);
}
/* Allow access to the output closures of this derivation. */
for (auto & outputPath : outputsToCopyAndAllow)
allowClosure(outputPath);
}

return res;
Expand Down
52 changes: 52 additions & 0 deletions tests/functional/import-from-derivation.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
with import <config>;

rec {
bar = mkDerivation {
name = "bar";
builder = builtins.toFile "builder.sh"
''
echo 'builtins.add 123 456' > $out
'';
};

value =
# Test that pathExists can check the existence of /nix/store paths
assert builtins.pathExists bar;
import bar;

result = mkDerivation {
name = "foo";
builder = builtins.toFile "builder.sh"
''
echo -n FOO${toString value} > $out
'';
};

addPath = mkDerivation {
name = "add-path";
src = builtins.filterSource (path: type: true) result;
builder = builtins.toFile "builder.sh"
''
echo -n BLA$(cat $src) > $out
'';
};

step1 = mkDerivation {
name = "step1";
buildCommand = ''
mkdir -p $out
echo 'foo' > $out/bla
'';
};

addPathExpr = mkDerivation {
name = "add-path";
inherit step1;
buildCommand = ''
mkdir -p $out
echo "builtins.path { path = \"$step1\"; sha256 = \"7ptL+pnrZXnSa5hwwB+2SXTLkcSb5264WGGokN8OXto=\"; }" > $out/default.nix
'';
};

importAddPathExpr = import addPathExpr;
}
55 changes: 55 additions & 0 deletions tests/functional/import-from-derivation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env bash

source common.sh

TODO_NixOS

clearStoreIfPossible

export NIX_PATH=config="${config_nix}"

if nix-instantiate --readonly-mode ./import-from-derivation.nix -A result; then
echo "read-only evaluation of an imported derivation unexpectedly failed"
exit 1
fi

outPath=$(nix-build ./import-from-derivation.nix -A result --no-out-link)

[ "$(cat "$outPath")" = FOO579 ]

# Check that we can have access to the entire closure of a derivation output.
nix build --no-link --restrict-eval -I src=. -f ./import-from-derivation.nix importAddPathExpr -v

# FIXME: the next tests are broken on CA.
if [[ -n "${NIX_TESTS_CA_BY_DEFAULT:-}" ]]; then
exit 0
fi

# Test filterSource on the result of a derivation.
outPath2=$(nix-build ./import-from-derivation.nix -A addPath --no-out-link)
[[ "$(cat "$outPath2")" = BLAFOO579 ]]

# Test that IFD works with a chroot store.
if canUseSandbox; then

store2="$TEST_ROOT/store2"
store2_url="$store2?store=$NIX_STORE_DIR"

# Copy the derivation outputs to the chroot store to avoid having
# to actually build anything, as that would fail due to the lack
# of a shell in the sandbox. We only care about testing the IFD
# semantics.
for i in bar result addPath; do
nix copy --to "$store2_url" --no-check-sigs "$(nix-build ./import-from-derivation.nix -A "$i" --no-out-link)"
done

clearStore

outPath_check=$(nix-build ./import-from-derivation.nix -A result --no-out-link --store "$store2_url")
[[ "$outPath" = "$outPath_check" ]]
[[ ! -e "$outPath" ]]
[[ -e "$store2/nix/store/$(basename "$outPath")" ]]

outPath2_check=$(nix-build ./import-from-derivation.nix -A addPath --no-out-link --store "$store2_url")
[[ "$outPath2" = "$outPath2_check" ]]
fi

0 comments on commit f986f7e

Please sign in to comment.