mirror of
https://codeberg.org/guix/guix.git
synced 2025-10-02 02:15:12 +00:00
daemon: Protect ‘copyFileRecursively’ from race conditions.
Previously, if an attacker managed to introduce a hard link or a symlink on one of the destination file names before it is opened, ‘copyFileRecursively’ would overwrite the symlink’s target or the hard link’s content. This kind of attack could be carried out while guix-daemon is copying the output or the chroot directory of a failed fixed-output derivation build, possibly allowing the attacker to escalate to the privileges of the build user. * nix/libutil/util.cc (copyFileRecursively): In the ‘S_ISREG’ case, open ‘destination’ with O_NOFOLLOW | O_EXCL. In the ‘S_ISDIR’ case, open ‘destination’ with O_NOFOLLOW. Reported-by: Reepca Russelstein <reepca@russelstein.xyz> Change-Id: I94273efe4e92c1a4270a98c5ec47bd098e9227c9 Signed-off-by: John Kehayias <john.kehayias@protonmail.com>
This commit is contained in:
parent
c659f977bb
commit
0e79d5b655
1 changed files with 5 additions and 3 deletions
|
@ -473,7 +473,8 @@ static void copyFileRecursively(int sourceroot, const Path &source,
|
||||||
if (sourceFd == -1) throw SysError(format("opening `%1%'") % source);
|
if (sourceFd == -1) throw SysError(format("opening `%1%'") % source);
|
||||||
|
|
||||||
AutoCloseFD destinationFd = openat(destinationroot, destination.c_str(),
|
AutoCloseFD destinationFd = openat(destinationroot, destination.c_str(),
|
||||||
O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC,
|
O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC
|
||||||
|
| O_NOFOLLOW | O_EXCL,
|
||||||
st.st_mode);
|
st.st_mode);
|
||||||
if (destinationFd == -1) throw SysError(format("opening `%1%'") % source);
|
if (destinationFd == -1) throw SysError(format("opening `%1%'") % source);
|
||||||
|
|
||||||
|
@ -495,7 +496,8 @@ static void copyFileRecursively(int sourceroot, const Path &source,
|
||||||
throw SysError(format("creating directory `%1%'") % destination);
|
throw SysError(format("creating directory `%1%'") % destination);
|
||||||
|
|
||||||
AutoCloseFD destinationFd = openat(destinationroot, destination.c_str(),
|
AutoCloseFD destinationFd = openat(destinationroot, destination.c_str(),
|
||||||
O_CLOEXEC | O_RDONLY | O_DIRECTORY);
|
O_CLOEXEC | O_RDONLY | O_DIRECTORY
|
||||||
|
| O_NOFOLLOW);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
throw SysError(format("opening directory `%1%'") % destination);
|
throw SysError(format("opening directory `%1%'") % destination);
|
||||||
|
|
||||||
|
@ -505,7 +507,7 @@ static void copyFileRecursively(int sourceroot, const Path &source,
|
||||||
throw SysError(format("opening `%1%'") % source);
|
throw SysError(format("opening `%1%'") % source);
|
||||||
|
|
||||||
if (deleteSource && !(st.st_mode & S_IWUSR)) {
|
if (deleteSource && !(st.st_mode & S_IWUSR)) {
|
||||||
/* Ensure the directory writable so files within it can be
|
/* Ensure the directory is writable so files within it can be
|
||||||
deleted. */
|
deleted. */
|
||||||
if (fchmod(sourceFd, st.st_mode | S_IWUSR) == -1)
|
if (fchmod(sourceFd, st.st_mode | S_IWUSR) == -1)
|
||||||
throw SysError(format("making `%1%' directory writable") % source);
|
throw SysError(format("making `%1%' directory writable") % source);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue