1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-08 15:13:55 +02:00

When moving paths out of sandbox, ensure we have write permission.

If we're a single-user installation of Nix, then we won't have root
superpowers to just ignore the permission bits. This means that we'll
need permission on the directory (if it's a directory) that we're moving
in order to move it with rename, because it must update the ".."
directory entry.

Fixes #4295.

This is already working in master, thanks to
e913a2989f (and followup cleanups).
This commit is contained in:
Luke Granger-Brown 2020-12-04 04:09:14 +00:00
parent 6456941993
commit 2239953894

View file

@ -3193,6 +3193,26 @@ PathSet parseReferenceSpecifiers(Store & store, const BasicDerivation & drv, con
} }
/* Move/rename path 'src' to 'dst'. Temporarily make 'src' writable if
it's a directory and we're not root (to be able to update the
directory's parent link ".."). */
static void movePath(const Path & src, const Path & dst)
{
auto st = lstat(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("renaming '%1%' to '%2%'", src, dst);
if (changePerm)
chmod_(dst, st.st_mode);
}
void DerivationGoal::registerOutputs() void DerivationGoal::registerOutputs()
{ {
/* When using a build hook, the build hook can register the output /* When using a build hook, the build hook can register the output
@ -3233,9 +3253,8 @@ void DerivationGoal::registerOutputs()
/* Move output paths from the chroot to the Nix store. */ /* Move output paths from the chroot to the Nix store. */
if (buildMode == bmRepair) if (buildMode == bmRepair)
replaceValidPath(path, actualPath); replaceValidPath(path, actualPath);
else else if (buildMode != bmCheck)
if (buildMode != bmCheck && rename(actualPath.c_str(), worker.store.toRealPath(path).c_str()) == -1) movePath(actualPath, worker.store.toRealPath(path));
throw SysError(format("moving build output '%1%' from the sandbox to the Nix store") % path);
} }
if (buildMode != bmCheck) actualPath = worker.store.toRealPath(path); if (buildMode != bmCheck) actualPath = worker.store.toRealPath(path);
} }