mirror of
https://github.com/NixOS/nix
synced 2025-06-25 02:21:16 +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/json-utils\.cc$''
|
||||||
''^src/libutil/include/nix/util/json-utils\.hh$''
|
''^src/libutil/include/nix/util/json-utils\.hh$''
|
||||||
''^src/libutil/linux/cgroup\.cc$''
|
''^src/libutil/linux/cgroup\.cc$''
|
||||||
''^src/libutil/linux/namespaces\.cc$''
|
''^src/libutil/linux/linux-namespaces\.cc$''
|
||||||
''^src/libutil/logging\.cc$''
|
''^src/libutil/logging\.cc$''
|
||||||
''^src/libutil/include/nix/util/logging\.hh$''
|
''^src/libutil/include/nix/util/logging\.hh$''
|
||||||
''^src/libutil/memory-source-accessor\.cc$''
|
''^src/libutil/memory-source-accessor\.cc$''
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
# include "nix/util/namespaces.hh"
|
# include "nix/util/linux-namespaces.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
|
@ -85,7 +85,7 @@ Settings::Settings()
|
||||||
builders = concatStringsSep("\n", ss);
|
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);
|
sandboxPaths = tokenizeString<StringSet>("/bin/sh=" SANDBOX_SHELL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -682,7 +682,9 @@ public:
|
||||||
description of the `size` option of `tmpfs` in mount(8). The default
|
description of the `size` option of `tmpfs` in mount(8). The default
|
||||||
is `50%`.
|
is `50%`.
|
||||||
)"};
|
)"};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__FreeBSD__)
|
||||||
Setting<Path> sandboxBuildDir{this, "/build", "sandbox-build-dir",
|
Setting<Path> sandboxBuildDir{this, "/build", "sandbox-build-dir",
|
||||||
R"(
|
R"(
|
||||||
*Linux only*
|
*Linux only*
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# include "nix/store/personality.hh"
|
# include "nix/store/personality.hh"
|
||||||
# include "nix/util/cgroup.hh"
|
# include "nix/util/cgroup.hh"
|
||||||
# include "nix/util/namespaces.hh"
|
# include "nix/util/linux-namespaces.hh"
|
||||||
# include "linux/fchmodat2-compat.hh"
|
# include "linux/fchmodat2-compat.hh"
|
||||||
|
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
|
|
|
@ -197,7 +197,7 @@ bool useBuildUsers()
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
static bool b = (settings.buildUsersGroup != "" || settings.autoAllocateUids) && isRootUser();
|
static bool b = (settings.buildUsersGroup != "" || settings.autoAllocateUids) && isRootUser();
|
||||||
return b;
|
return b;
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__) && defined(__FreeBSD__)
|
||||||
static bool b = settings.buildUsersGroup != "" && isRootUser();
|
static bool b = settings.buildUsersGroup != "" && isRootUser();
|
||||||
return b;
|
return b;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -16,7 +16,12 @@
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
# include <mutex>
|
# include <mutex>
|
||||||
# include "nix/util/cgroup.hh"
|
# 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
|
#endif
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
@ -115,6 +120,24 @@ std::optional<Path> getSelfExe()
|
||||||
return buf;
|
return buf;
|
||||||
else
|
else
|
||||||
return std::nullopt;
|
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
|
#else
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,6 +23,11 @@
|
||||||
|
|
||||||
#include <boost/iostreams/device/mapped_file.hpp>
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
# include <sys/param.h>
|
||||||
|
# include <sys/mount.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -364,6 +369,13 @@ void syncParent(const Path & path)
|
||||||
fd.fsync();
|
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)
|
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
|
#ifndef _WIN32
|
||||||
checkInterrupt();
|
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()));
|
std::string name(baseNameOf(path.native()));
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -468,7 +488,7 @@ static void _deletePath(Descriptor parentfd, const std::filesystem::path & path,
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
std::string childName = dirent->d_name;
|
std::string childName = dirent->d_name;
|
||||||
if (childName == "." || childName == "..") continue;
|
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);
|
if (errno) throw SysError("reading directory %1%", path);
|
||||||
}
|
}
|
||||||
|
@ -484,7 +504,7 @@ static void _deletePath(Descriptor parentfd, const std::filesystem::path & path,
|
||||||
#endif
|
#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());
|
Path dir = dirOf(path.string());
|
||||||
if (dir == "")
|
if (dir == "")
|
||||||
|
@ -496,7 +516,7 @@ static void _deletePath(const std::filesystem::path & path, uint64_t & bytesFree
|
||||||
throw SysError("opening directory '%1%'", path);
|
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)
|
void deletePath(const std::filesystem::path & path, uint64_t & bytesFreed)
|
||||||
{
|
{
|
||||||
//Activity act(*logger, lvlDebug, "recursively deleting path '%1%'", path);
|
//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;
|
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() {
|
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.
|
* 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);
|
mode_t mode = 0755);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -420,4 +420,17 @@ private:
|
||||||
std::filesystem::directory_iterator it_;
|
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(
|
headers += files(
|
||||||
'cgroup.hh',
|
'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/current-process.hh"
|
||||||
#include "nix/util/util.hh"
|
#include "nix/util/util.hh"
|
||||||
#include "nix/util/finally.hh"
|
#include "nix/util/finally.hh"
|
|
@ -1,6 +1,6 @@
|
||||||
sources += files(
|
sources += files(
|
||||||
'cgroup.cc',
|
'cgroup.cc',
|
||||||
'namespaces.cc',
|
'linux-namespaces.cc',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('include/nix/util')
|
subdir('include/nix/util')
|
||||||
|
|
|
@ -169,6 +169,10 @@ if host_machine.system() == 'linux'
|
||||||
subdir('linux')
|
subdir('linux')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if host_machine.system() == 'freebsd'
|
||||||
|
subdir('freebsd')
|
||||||
|
endif
|
||||||
|
|
||||||
if host_machine.system() == 'windows'
|
if host_machine.system() == 'windows'
|
||||||
subdir('windows')
|
subdir('windows')
|
||||||
else
|
else
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
# include "nix/util/namespaces.hh"
|
# include "nix/util/linux-namespaces.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue