1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-27 12:41:15 +02:00

Prepare for FreeBSD sandboxing support

This is the utility changes from #9968, which were easier to rebase
first.

I (@Ericson2314) didn't write this code; I just rebased it.

Co-Authored-By: Artemis Tosini <me@artem.ist>
Co-Authored-By: Audrey Dutcher <audrey@rhelmot.io>
This commit is contained in:
John Ericson 2025-05-27 14:51:39 -04:00
parent 653a93ac0f
commit 625dce659a
19 changed files with 198 additions and 15 deletions

View file

@ -23,6 +23,11 @@
#include <boost/iostreams/device/mapped_file.hpp>
#ifdef __FreeBSD__
# include <sys/param.h>
# include <sys/mount.h>
#endif
#ifdef _WIN32
# include <io.h>
#endif
@ -364,6 +369,13 @@ void syncParent(const Path & path)
fd.fsync();
}
#ifdef __FreeBSD__
#define MOUNTEDPATHS_PARAM , std::set<Path> &mountedPaths
#define MOUNTEDPATHS_ARG , mountedPaths
#else
#define MOUNTEDPATHS_PARAM
#define MOUNTEDPATHS_ARG
#endif
void recursiveSync(const Path & path)
{
@ -410,11 +422,19 @@ void recursiveSync(const Path & path)
}
static void _deletePath(Descriptor parentfd, const std::filesystem::path & path, uint64_t & bytesFreed)
static void _deletePath(Descriptor parentfd, const std::filesystem::path & path, uint64_t & bytesFreed MOUNTEDPATHS_PARAM)
{
#ifndef _WIN32
checkInterrupt();
#ifdef __FreeBSD__
// In case of emergency (unmount fails for some reason) not recurse into mountpoints.
// This prevents us from tearing up the nullfs-mounted nix store.
if (mountedPaths.find(path) != mountedPaths.end()) {
return;
}
#endif
std::string name(baseNameOf(path.native()));
struct stat st;
@ -468,7 +488,7 @@ static void _deletePath(Descriptor parentfd, const std::filesystem::path & path,
checkInterrupt();
std::string childName = dirent->d_name;
if (childName == "." || childName == "..") continue;
_deletePath(dirfd(dir.get()), path + "/" + childName, bytesFreed);
_deletePath(dirfd(dir.get()), path + "/" + childName, bytesFreed MOUNTEDPATHS_ARG);
}
if (errno) throw SysError("reading directory %1%", path);
}
@ -484,7 +504,7 @@ static void _deletePath(Descriptor parentfd, const std::filesystem::path & path,
#endif
}
static void _deletePath(const std::filesystem::path & path, uint64_t & bytesFreed)
static void _deletePath(const std::filesystem::path & path, uint64_t & bytesFreed MOUNTEDPATHS_PARAM)
{
Path dir = dirOf(path.string());
if (dir == "")
@ -496,7 +516,7 @@ static void _deletePath(const std::filesystem::path & path, uint64_t & bytesFree
throw SysError("opening directory '%1%'", path);
}
_deletePath(dirfd.get(), path, bytesFreed);
_deletePath(dirfd.get(), path, bytesFreed MOUNTEDPATHS_ARG);
}
@ -529,8 +549,20 @@ void createDirs(const std::filesystem::path & path)
void deletePath(const std::filesystem::path & path, uint64_t & bytesFreed)
{
//Activity act(*logger, lvlDebug, "recursively deleting path '%1%'", path);
#ifdef __FreeBSD__
std::set<Path> mountedPaths;
struct statfs *mntbuf;
int count;
if ((count = getmntinfo(&mntbuf, MNT_WAIT)) < 0) {
throw SysError("getmntinfo");
}
for (int i = 0; i < count; i++) {
mountedPaths.emplace(mntbuf[i].f_mntonname);
}
#endif
bytesFreed = 0;
_deletePath(path, bytesFreed);
_deletePath(path, bytesFreed MOUNTEDPATHS_ARG);
}
@ -572,6 +604,30 @@ void AutoDelete::reset(const std::filesystem::path & p, bool recursive) {
//////////////////////////////////////////////////////////////////////
#ifdef __FreeBSD__
AutoUnmount::AutoUnmount() : del{false} {}
AutoUnmount::AutoUnmount(Path &p) : path(p), del(true) {}
AutoUnmount::~AutoUnmount()
{
try {
if (del) {
if (unmount(path.c_str(), 0) < 0) {
throw SysError("Failed to unmount path %1%", path);
}
}
} catch (...) {
ignoreExceptionInDestructor();
}
}
void AutoUnmount::cancel()
{
del = false;
}
#endif
//////////////////////////////////////////////////////////////////////
std::string defaultTempDir() {