Skip to content

Commit 3a9be9f

Browse files
committed
libutil: Use openFileEnsureBeneathNoSymlinks in RestoreSink::createDirectory
Starts using the new function.
1 parent 77990e7 commit 3a9be9f

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

src/libutil-tests/file-system.cc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ TEST(openFileEnsureBeneathNoSymlinks, works)
329329
{
330330
std::filesystem::path tmpDir = nix::createTempDir();
331331
nix::AutoDelete delTmpDir(tmpDir, /*recursive=*/true);
332+
using namespace nix::unix;
332333

333334
{
334335
RestoreSink sink(/*startFsync=*/false);
@@ -341,12 +342,19 @@ TEST(openFileEnsureBeneathNoSymlinks, works)
341342
sink.createSymlink(CanonPath("a/absolute_symlink"), tmpDir.string());
342343
sink.createSymlink(CanonPath("a/relative_symlink"), "../.");
343344
sink.createSymlink(CanonPath("a/broken_symlink"), "./nonexistent");
345+
sink.createDirectory(CanonPath("a/b"), [](FileSystemObjectSink & dirSink, const CanonPath & relPath) {
346+
dirSink.createDirectory(CanonPath("d"));
347+
dirSink.createSymlink(CanonPath("c"), "./d");
348+
});
349+
sink.createDirectory(CanonPath("a/b/c/e")); // FIXME: This still follows symlinks
350+
ASSERT_THROW(
351+
sink.createDirectory(
352+
CanonPath("a/b/c/f"), [](FileSystemObjectSink & dirSink, const CanonPath & relPath) {}),
353+
SymlinkNotAllowed);
344354
}
345355

346356
AutoCloseFD dirFd = openDirectory(tmpDir);
347357

348-
using namespace nix::unix;
349-
350358
auto open = [&](std::string_view path, int flags, mode_t mode = 0) {
351359
return openFileEnsureBeneathNoSymlinks(dirFd.get(), CanonPath(path), flags, mode);
352360
};
@@ -356,6 +364,7 @@ TEST(openFileEnsureBeneathNoSymlinks, works)
356364
EXPECT_THROW(open("a/absolute_symlink/a", O_RDONLY), SymlinkNotAllowed);
357365
EXPECT_THROW(open("a/absolute_symlink/c/d", O_RDONLY), SymlinkNotAllowed);
358366
EXPECT_THROW(open("a/relative_symlink/c", O_RDONLY), SymlinkNotAllowed);
367+
EXPECT_THROW(open("a/b/c/d", O_RDONLY), SymlinkNotAllowed);
359368
EXPECT_EQ(open("a/broken_symlink", O_CREAT | O_WRONLY | O_EXCL, 0666), INVALID_DESCRIPTOR);
360369
/* Sanity check, no symlink shenanigans and behaves the same as regular openat with O_EXCL | O_CREAT. */
361370
EXPECT_EQ(errno, EEXIST);

src/libutil/fs-sink.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ void RestoreSink::createDirectory(const CanonPath & path, DirectoryCreatedCallba
8484

8585
RestoreSink dirSink{startFsync};
8686
dirSink.dstPath = append(dstPath, path);
87-
dirSink.dirFd = ::openat(dirFd.get(), path.rel_c_str(), O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
87+
dirSink.dirFd =
88+
unix::openFileEnsureBeneathNoSymlinks(dirFd.get(), path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
8889

8990
if (!dirSink.dirFd)
9091
throw SysError("opening directory '%s'", dirSink.dstPath.string());

0 commit comments

Comments
 (0)