mirror of
https://github.com/NixOS/nix
synced 2025-06-24 22:11: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:
parent
653a93ac0f
commit
625dce659a
19 changed files with 198 additions and 15 deletions
|
@ -359,7 +359,7 @@
|
|||
''^src/libutil/json-utils\.cc$''
|
||||
''^src/libutil/include/nix/util/json-utils\.hh$''
|
||||
''^src/libutil/linux/cgroup\.cc$''
|
||||
''^src/libutil/linux/namespaces\.cc$''
|
||||
''^src/libutil/linux/linux-namespaces\.cc$''
|
||||
''^src/libutil/logging\.cc$''
|
||||
''^src/libutil/include/nix/util/logging\.hh$''
|
||||
''^src/libutil/memory-source-accessor\.cc$''
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
# include "nix/util/namespaces.hh"
|
||||
# include "nix/util/linux-namespaces.hh"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -85,7 +85,7 @@ Settings::Settings()
|
|||
builders = concatStringsSep("\n", ss);
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(SANDBOX_SHELL)
|
||||
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(SANDBOX_SHELL)
|
||||
sandboxPaths = tokenizeString<StringSet>("/bin/sh=" SANDBOX_SHELL);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -682,7 +682,9 @@ public:
|
|||
description of the `size` option of `tmpfs` in mount(8). The default
|
||||
is `50%`.
|
||||
)"};
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
Setting<Path> sandboxBuildDir{this, "/build", "sandbox-build-dir",
|
||||
R"(
|
||||
*Linux only*
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# include "nix/store/personality.hh"
|
||||
# include "nix/util/cgroup.hh"
|
||||
# include "nix/util/namespaces.hh"
|
||||
# include "nix/util/linux-namespaces.hh"
|
||||
# include "linux/fchmodat2-compat.hh"
|
||||
|
||||
# include <sys/ioctl.h>
|
||||
|
|
|
@ -197,7 +197,7 @@ bool useBuildUsers()
|
|||
#ifdef __linux__
|
||||
static bool b = (settings.buildUsersGroup != "" || settings.autoAllocateUids) && isRootUser();
|
||||
return b;
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) && defined(__FreeBSD__)
|
||||
static bool b = settings.buildUsersGroup != "" && isRootUser();
|
||||
return b;
|
||||
#else
|
||||
|
|
|
@ -16,7 +16,12 @@
|
|||
#ifdef __linux__
|
||||
# include <mutex>
|
||||
# include "nix/util/cgroup.hh"
|
||||
# include "nix/util/namespaces.hh"
|
||||
# include "nix/util/linux-namespaces.hh"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
# include <sys/param.h>
|
||||
# include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
namespace nix {
|
||||
|
@ -115,6 +120,24 @@ std::optional<Path> getSelfExe()
|
|||
return buf;
|
||||
else
|
||||
return std::nullopt;
|
||||
#elif defined(__FreeBSD__)
|
||||
int sysctlName[] = {
|
||||
CTL_KERN,
|
||||
KERN_PROC,
|
||||
KERN_PROC_PATHNAME,
|
||||
-1,
|
||||
};
|
||||
size_t pathLen = 0;
|
||||
if (sysctl(sysctlName, sizeof(sysctlName) / sizeof(sysctlName[0]), nullptr, &pathLen, nullptr, 0) < 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<char> path(pathLen);
|
||||
if (sysctl(sysctlName, sizeof(sysctlName) / sizeof(sysctlName[0]), path.data(), &pathLen, nullptr, 0) < 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return Path(path.begin(), path.end());
|
||||
#else
|
||||
return std::nullopt;
|
||||
#endif
|
||||
|
|
|
@ -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() {
|
||||
|
|
52
src/libutil/freebsd/freebsd-jail.cc
Normal file
52
src/libutil/freebsd/freebsd-jail.cc
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifdef __FreeBSD__
|
||||
# include "nix/util/freebsd-jail.hh"
|
||||
|
||||
# include <sys/resource.h>
|
||||
# include <sys/param.h>
|
||||
# include <sys/jail.h>
|
||||
# include <sys/mount.h>
|
||||
|
||||
# include "nix/util/error.hh"
|
||||
# include "nix/util/util.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
AutoRemoveJail::AutoRemoveJail()
|
||||
: del{false}
|
||||
{
|
||||
}
|
||||
|
||||
AutoRemoveJail::AutoRemoveJail(int jid)
|
||||
: jid(jid)
|
||||
, del(true)
|
||||
{
|
||||
}
|
||||
|
||||
AutoRemoveJail::~AutoRemoveJail()
|
||||
{
|
||||
try {
|
||||
if (del) {
|
||||
if (jail_remove(jid) < 0) {
|
||||
throw SysError("Failed to remove jail %1%", jid);
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
ignoreExceptionInDestructor();
|
||||
}
|
||||
}
|
||||
|
||||
void AutoRemoveJail::cancel()
|
||||
{
|
||||
del = false;
|
||||
}
|
||||
|
||||
void AutoRemoveJail::reset(int j)
|
||||
{
|
||||
del = true;
|
||||
jid = j;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
#endif
|
20
src/libutil/freebsd/include/nix/util/freebsd-jail.hh
Normal file
20
src/libutil/freebsd/include/nix/util/freebsd-jail.hh
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "nix/util/types.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
class AutoRemoveJail
|
||||
{
|
||||
int jid;
|
||||
bool del;
|
||||
public:
|
||||
AutoRemoveJail(int jid);
|
||||
AutoRemoveJail();
|
||||
~AutoRemoveJail();
|
||||
void cancel();
|
||||
void reset(int j);
|
||||
};
|
||||
|
||||
}
|
7
src/libutil/freebsd/include/nix/util/meson.build
Normal file
7
src/libutil/freebsd/include/nix/util/meson.build
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Public headers directory
|
||||
|
||||
include_dirs += include_directories('../..')
|
||||
|
||||
headers += files(
|
||||
'freebsd-jail.hh',
|
||||
)
|
5
src/libutil/freebsd/meson.build
Normal file
5
src/libutil/freebsd/meson.build
Normal file
|
@ -0,0 +1,5 @@
|
|||
sources += files(
|
||||
'freebsd-jail.cc',
|
||||
)
|
||||
|
||||
subdir('include/nix/util')
|
|
@ -310,7 +310,7 @@ typedef std::unique_ptr<DIR, DIRDeleter> AutoCloseDir;
|
|||
/**
|
||||
* Create a temporary directory.
|
||||
*/
|
||||
Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
|
||||
Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
|
||||
mode_t mode = 0755);
|
||||
|
||||
/**
|
||||
|
@ -420,4 +420,17 @@ private:
|
|||
std::filesystem::directory_iterator it_;
|
||||
};
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
class AutoUnmount
|
||||
{
|
||||
Path path;
|
||||
bool del;
|
||||
public:
|
||||
AutoUnmount(Path&);
|
||||
AutoUnmount();
|
||||
~AutoUnmount();
|
||||
void cancel();
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -4,5 +4,5 @@ include_dirs += include_directories('../..')
|
|||
|
||||
headers += files(
|
||||
'cgroup.hh',
|
||||
'namespaces.hh',
|
||||
'linux-namespaces.hh',
|
||||
)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "nix/util/linux-namespaces.hh"
|
||||
#include "nix/util/current-process.hh"
|
||||
#include "nix/util/util.hh"
|
||||
#include "nix/util/finally.hh"
|
|
@ -1,6 +1,6 @@
|
|||
sources += files(
|
||||
'cgroup.cc',
|
||||
'namespaces.cc',
|
||||
'linux-namespaces.cc',
|
||||
)
|
||||
|
||||
subdir('include/nix/util')
|
||||
|
|
|
@ -169,6 +169,10 @@ if host_machine.system() == 'linux'
|
|||
subdir('linux')
|
||||
endif
|
||||
|
||||
if host_machine.system() == 'freebsd'
|
||||
subdir('freebsd')
|
||||
endif
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
subdir('windows')
|
||||
else
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
# include "nix/util/namespaces.hh"
|
||||
# include "nix/util/linux-namespaces.hh"
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue