Skip to content

Commit

Permalink
Merge pull request NixOS#2688 from tollb/fix/build_check_keep_failed_…
Browse files Browse the repository at this point in the history
…sandbox_perms

Fix nix-build --check -K in sandbox w/o root
  • Loading branch information
domenkozar authored Apr 11, 2020
2 parents fc14424 + e8bd1bc commit ea2148f
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
30 changes: 26 additions & 4 deletions src/libstore/build.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3537,6 +3537,29 @@ StorePathSet parseReferenceSpecifiers(Store & store, const BasicDerivation & drv
}


static void moveCheckToStore(const Path & src, const Path & dst)
{
/* For the rename of directory to succeed, we must be running as root or
the directory must be made temporarily writable (to update the
directory's parent link ".."). */
struct stat st;
if (lstat(src.c_str(), &st) == -1) {
throw SysError(format("getting attributes of path '%1%'") % src);
}

bool changePerm = (geteuid() && S_ISDIR(st.st_mode) && !(st.st_mode & S_IWUSR));

if (changePerm)
chmod_(src, st.st_mode | S_IWUSR);

if (rename(src.c_str(), dst.c_str()))
throw SysError(format("renaming '%1%' to '%2%'") % src % dst);

if (changePerm)
chmod_(dst, st.st_mode);
}


void DerivationGoal::registerOutputs()
{
/* When using a build hook, the build hook can register the output
Expand Down Expand Up @@ -3715,19 +3738,18 @@ void DerivationGoal::registerOutputs()
if (settings.runDiffHook || settings.keepFailed) {
Path dst = worker.store.toRealPath(path + checkSuffix);
deletePath(dst);
if (rename(actualPath.c_str(), dst.c_str()))
throw SysError(format("renaming '%1%' to '%2%'") % actualPath % dst);
moveCheckToStore(actualPath, dst);

handleDiffHook(
buildUser ? buildUser->getUID() : getuid(),
buildUser ? buildUser->getGID() : getgid(),
path, dst, worker.store.printStorePath(drvPath), tmpDir);

throw NotDeterministic("derivation '%s' may not be deterministic: output '%s' differs from '%s'",
worker.store.printStorePath(drvPath), path, dst);
worker.store.printStorePath(drvPath), worker.store.toRealPath(path), dst);
} else
throw NotDeterministic("derivation '%s' may not be deterministic: output '%s' differs",
worker.store.printStorePath(drvPath), path);
worker.store.printStorePath(drvPath), worker.store.toRealPath(path));
}

/* Since we verified the build, it's now ultimately trusted. */
Expand Down
5 changes: 0 additions & 5 deletions tests/check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,8 @@ checkBuildTempDirRemoved $TEST_ROOT/log

nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \
--no-out-link --check --keep-failed 2> $TEST_ROOT/log || status=$?

# The above nix-build fails with status=1 on darwin (not sure why)
# ...but the primary purpose of the test case is to verify the temp directory is retained
if [ "$(uname -s)" != "Darwin" ]; then
grep 'may not be deterministic' $TEST_ROOT/log
[ "$status" = "104" ]
fi
if checkBuildTempDirRemoved $TEST_ROOT/log; then false; fi

clearStore
Expand Down
7 changes: 7 additions & 0 deletions tests/linux-sandbox.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,10 @@ nix cat-store $outPath/foobar | grep FOOBAR

# Test --check without hash rewriting.
nix-build dependencies.nix --no-out-link --check --sandbox-paths /nix/store

# Test that sandboxed builds with --check and -K can move .check directory to store
nix-build check.nix -A nondeterministic --sandbox-paths /nix/store --no-out-link

(! nix-build check.nix -A nondeterministic --sandbox-paths /nix/store --no-out-link --check -K 2> $TEST_ROOT/log)
if grep -q 'error: renaming' $TEST_ROOT/log; then false; fi
grep -q 'may not be deterministic' $TEST_ROOT/log

0 comments on commit ea2148f

Please sign in to comment.