Skip to content

Commit

Permalink
Merge pull request #10471 from NixOS/backport-10456-to-2.20-maintenance
Browse files Browse the repository at this point in the history
[Backport 2.20-maintenance] Fix adding symlink to the sandbox paths
  • Loading branch information
thufschmitt authored Apr 11, 2024
2 parents 202842e + ccb9779 commit 1cf8c57
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
21 changes: 16 additions & 5 deletions src/libstore/build/local-derivation-goal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <regex>
#include <queue>

#include <sys/stat.h>
#include <sys/un.h>
#include <fcntl.h>
#include <termios.h>
Expand Down Expand Up @@ -395,20 +396,30 @@ void LocalDerivationGoal::cleanupPostOutputsRegisteredModeNonCheck()
static void doBind(const Path & source, const Path & target, bool optional = false) {
debug("bind mounting '%1%' to '%2%'", source, target);
struct stat st;
if (stat(source.c_str(), &st) == -1) {

auto bindMount = [&]() {
if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REC, 0) == -1)
throw SysError("bind mount from '%1%' to '%2%' failed", source, target);
};

if (lstat(source.c_str(), &st) == -1) {
if (optional && errno == ENOENT)
return;
else
throw SysError("getting attributes of path '%1%'", source);
}
if (S_ISDIR(st.st_mode))
if (S_ISDIR(st.st_mode)) {
createDirs(target);
else {
bindMount();
} else if (S_ISLNK(st.st_mode)) {
// Symlinks can (apparently) not be bind-mounted, so just copy it
createDirs(dirOf(target));
copyFile(source, target, /* andDelete */ false);
} else {
createDirs(dirOf(target));
writeFile(target, "");
bindMount();
}
if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REC, 0) == -1)
throw SysError("bind mount from '%1%' to '%2%' failed", source, target);
};
#endif

Expand Down
3 changes: 3 additions & 0 deletions tests/functional/linux-sandbox.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,6 @@ testCert missing fixed-output "$nocert"

# Cert in sandbox when ssl-cert-file is set to an existing file
testCert present fixed-output "$cert"

# Symlinks should be added in the sandbox directly and not followed
nix-sandbox-build symlink-derivation.nix
36 changes: 36 additions & 0 deletions tests/functional/symlink-derivation.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
with import ./config.nix;

let
foo_in_store = builtins.toFile "foo" "foo";
foo_symlink = mkDerivation {
name = "foo-symlink";
buildCommand = ''
ln -s ${foo_in_store} $out
'';
};
symlink_to_not_in_store = mkDerivation {
name = "symlink-to-not-in-store";
buildCommand = ''
ln -s ${builtins.toString ./.} $out
'';
};
in
mkDerivation {
name = "depends-on-symlink";
buildCommand = ''
(
set -x
# `foo_symlink` should be a symlink pointing to `foo_in_store`
[[ -L ${foo_symlink} ]]
[[ $(readlink ${foo_symlink}) == ${foo_in_store} ]]
# `symlink_to_not_in_store` should be a symlink pointing to `./.`, which
# is not available in the sandbox
[[ -L ${symlink_to_not_in_store} ]]
[[ $(readlink ${symlink_to_not_in_store}) == ${builtins.toString ./.} ]]
(! ls ${symlink_to_not_in_store}/)
)
echo "Success!" > $out
'';
}

0 comments on commit 1cf8c57

Please sign in to comment.