Skip to content

Commit c383495

Browse files
authored
Merge pull request #14651 from NixOS/restore-sink-more-openat2
libutil: Use openFileEnsureBeneathNoSymlinks in RestoreSink::createRe…
2 parents 31ce0c8 + 0778b86 commit c383495

File tree

4 files changed

+10
-1
lines changed

4 files changed

+10
-1
lines changed

src/libutil-tests/file-system.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ TEST(openFileEnsureBeneathNoSymlinks, works)
351351
sink.createDirectory(
352352
CanonPath("a/b/c/f"), [](FileSystemObjectSink & dirSink, const CanonPath & relPath) {}),
353353
SymlinkNotAllowed);
354+
ASSERT_THROW(
355+
sink.createRegularFile(
356+
CanonPath("a/b/c/regular"), [](CreateRegularFileSink & crf) { crf("some contents"); }),
357+
SymlinkNotAllowed);
354358
}
355359

356360
AutoCloseFD dirFd = openDirectory(tmpDir);

src/libutil/fs-sink.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ void RestoreSink::createRegularFile(const CanonPath & path, std::function<void(C
170170
constexpr int flags = O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC;
171171
if (!dirFd)
172172
return ::open(p.c_str(), flags, 0666);
173-
return ::openat(dirFd.get(), path.rel_c_str(), flags, 0666);
173+
return unix::openFileEnsureBeneathNoSymlinks(dirFd.get(), path, flags, 0666);
174174
}();
175175
#endif
176176
;

src/libutil/include/nix/util/file-descriptor.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ struct SymlinkNotAllowed : public Error
263263
* @param flags O_* flags
264264
* @param mode Mode for O_{CREAT,TMPFILE}
265265
*
266+
* @pre path.isRoot() is false
267+
*
266268
* @throws SymlinkNotAllowed if any path components
267269
*/
268270
Descriptor openFileEnsureBeneathNoSymlinks(Descriptor dirFd, const CanonPath & path, int flags, mode_t mode = 0);

src/libutil/unix/file-descriptor.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ openFileEnsureBeneathNoSymlinksIterative(Descriptor dirFd, const CanonPath & pat
269269
{
270270
AutoCloseFD parentFd;
271271
auto nrComponents = std::ranges::distance(path);
272+
assert(nrComponents >= 1);
272273
auto components = std::views::take(path, nrComponents - 1); /* Everything but last component */
273274
auto getParentFd = [&]() { return parentFd ? parentFd.get() : dirFd; };
274275

@@ -320,6 +321,8 @@ openFileEnsureBeneathNoSymlinksIterative(Descriptor dirFd, const CanonPath & pat
320321

321322
Descriptor unix::openFileEnsureBeneathNoSymlinks(Descriptor dirFd, const CanonPath & path, int flags, mode_t mode)
322323
{
324+
assert(!path.rel().starts_with('/')); /* Just in case the invariant is somehow broken. */
325+
assert(!path.isRoot());
323326
#ifdef __linux__
324327
auto maybeFd = linux::openat2(
325328
dirFd, path.rel_c_str(), flags, static_cast<uint64_t>(mode), RESOLVE_BENEATH | RESOLVE_NO_SYMLINKS);

0 commit comments

Comments
 (0)