1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-28 21:21:00 +01:00

Merge pull request #14651 from NixOS/restore-sink-more-openat2

libutil: Use openFileEnsureBeneathNoSymlinks in RestoreSink::createRe…
This commit is contained in:
John Ericson 2025-11-26 01:45:50 +00:00 committed by GitHub
commit c38349583f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 10 additions and 1 deletions

View file

@ -351,6 +351,10 @@ TEST(openFileEnsureBeneathNoSymlinks, works)
sink.createDirectory( sink.createDirectory(
CanonPath("a/b/c/f"), [](FileSystemObjectSink & dirSink, const CanonPath & relPath) {}), CanonPath("a/b/c/f"), [](FileSystemObjectSink & dirSink, const CanonPath & relPath) {}),
SymlinkNotAllowed); SymlinkNotAllowed);
ASSERT_THROW(
sink.createRegularFile(
CanonPath("a/b/c/regular"), [](CreateRegularFileSink & crf) { crf("some contents"); }),
SymlinkNotAllowed);
} }
AutoCloseFD dirFd = openDirectory(tmpDir); AutoCloseFD dirFd = openDirectory(tmpDir);

View file

@ -170,7 +170,7 @@ void RestoreSink::createRegularFile(const CanonPath & path, std::function<void(C
constexpr int flags = O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC; constexpr int flags = O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC;
if (!dirFd) if (!dirFd)
return ::open(p.c_str(), flags, 0666); return ::open(p.c_str(), flags, 0666);
return ::openat(dirFd.get(), path.rel_c_str(), flags, 0666); return unix::openFileEnsureBeneathNoSymlinks(dirFd.get(), path, flags, 0666);
}(); }();
#endif #endif
; ;

View file

@ -263,6 +263,8 @@ struct SymlinkNotAllowed : public Error
* @param flags O_* flags * @param flags O_* flags
* @param mode Mode for O_{CREAT,TMPFILE} * @param mode Mode for O_{CREAT,TMPFILE}
* *
* @pre path.isRoot() is false
*
* @throws SymlinkNotAllowed if any path components * @throws SymlinkNotAllowed if any path components
*/ */
Descriptor openFileEnsureBeneathNoSymlinks(Descriptor dirFd, const CanonPath & path, int flags, mode_t mode = 0); Descriptor openFileEnsureBeneathNoSymlinks(Descriptor dirFd, const CanonPath & path, int flags, mode_t mode = 0);

View file

@ -269,6 +269,7 @@ openFileEnsureBeneathNoSymlinksIterative(Descriptor dirFd, const CanonPath & pat
{ {
AutoCloseFD parentFd; AutoCloseFD parentFd;
auto nrComponents = std::ranges::distance(path); auto nrComponents = std::ranges::distance(path);
assert(nrComponents >= 1);
auto components = std::views::take(path, nrComponents - 1); /* Everything but last component */ auto components = std::views::take(path, nrComponents - 1); /* Everything but last component */
auto getParentFd = [&]() { return parentFd ? parentFd.get() : dirFd; }; auto getParentFd = [&]() { return parentFd ? parentFd.get() : dirFd; };
@ -320,6 +321,8 @@ openFileEnsureBeneathNoSymlinksIterative(Descriptor dirFd, const CanonPath & pat
Descriptor unix::openFileEnsureBeneathNoSymlinks(Descriptor dirFd, const CanonPath & path, int flags, mode_t mode) Descriptor unix::openFileEnsureBeneathNoSymlinks(Descriptor dirFd, const CanonPath & path, int flags, mode_t mode)
{ {
assert(!path.rel().starts_with('/')); /* Just in case the invariant is somehow broken. */
assert(!path.isRoot());
#ifdef __linux__ #ifdef __linux__
auto maybeFd = linux::openat2( auto maybeFd = linux::openat2(
dirFd, path.rel_c_str(), flags, static_cast<uint64_t>(mode), RESOLVE_BENEATH | RESOLVE_NO_SYMLINKS); dirFd, path.rel_c_str(), flags, static_cast<uint64_t>(mode), RESOLVE_BENEATH | RESOLVE_NO_SYMLINKS);