mirror of
https://github.com/NixOS/nix
synced 2025-07-05 20:41:47 +02:00
clean up
Signed-off-by: Samuli Thomasson <samuli.thomasson@pm.me>
This commit is contained in:
parent
b01dcf8985
commit
1b2c828d57
4 changed files with 60 additions and 48 deletions
|
@ -86,7 +86,7 @@ Settings::Settings()
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(SANDBOX_SHELL)
|
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(SANDBOX_SHELL)
|
||||||
sandboxPaths = SandboxPaths { { "/bin/sh", SandboxPath(SANDBOX_SHELL) } };
|
sandboxPaths = { { "/bin/sh", SANDBOX_SHELL } };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* chroot-like behavior from Apple's sandbox */
|
/* chroot-like behavior from Apple's sandbox */
|
||||||
|
@ -297,25 +297,26 @@ template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::s
|
||||||
}
|
}
|
||||||
|
|
||||||
NLOHMANN_JSON_SERIALIZE_ENUM(SandboxPath::MountOpt, {
|
NLOHMANN_JSON_SERIALIZE_ENUM(SandboxPath::MountOpt, {
|
||||||
{SandboxPath::MountOpt::ro, "ro"},
|
{SandboxPath::MountOpt::ro, "ro"},
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
{SandboxPath::MountOpt::nodev, "nodev"},
|
{SandboxPath::MountOpt::nodev, "nodev"},
|
||||||
{SandboxPath::MountOpt::noexec, "noexec"},
|
{SandboxPath::MountOpt::noexec, "noexec"},
|
||||||
{SandboxPath::MountOpt::nosuid, "nosuid"},
|
{SandboxPath::MountOpt::nosuid, "nosuid"},
|
||||||
{SandboxPath::MountOpt::noatime, "noatime"},
|
{SandboxPath::MountOpt::noatime, "noatime"},
|
||||||
{SandboxPath::MountOpt::nodiratime, "nodiratime"},
|
{SandboxPath::MountOpt::nodiratime, "nodiratime"},
|
||||||
{SandboxPath::MountOpt::relatime, "relatime"},
|
{SandboxPath::MountOpt::relatime, "relatime"},
|
||||||
{SandboxPath::MountOpt::strictatime, "strictatime"},
|
{SandboxPath::MountOpt::strictatime, "strictatime"},
|
||||||
{SandboxPath::MountOpt::private_, "private"},
|
{SandboxPath::MountOpt::private_, "private"},
|
||||||
{SandboxPath::MountOpt::slave, "slave"},
|
{SandboxPath::MountOpt::slave, "slave"},
|
||||||
{SandboxPath::MountOpt::unbindable, "unbindable"},
|
{SandboxPath::MountOpt::unbindable, "unbindable"},
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(SandboxPath, source, optional, readOnly, options);
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(SandboxPath, source, optional, readOnly, options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses either old (strings) or new (json object) format sandbox-paths.
|
* Parses either old ("path[=source][?]" strings) or new (json object) format
|
||||||
|
* sandbox-paths. Legacy format supports only a subset of available settings.
|
||||||
*/
|
*/
|
||||||
SandboxPaths SandboxPath::parse(const std::string_view & str, const std::string & ctx)
|
SandboxPaths SandboxPath::parse(const std::string_view & str, const std::string & ctx)
|
||||||
{
|
{
|
||||||
|
@ -334,15 +335,14 @@ SandboxPaths SandboxPath::parse(const std::string_view & str, const std::string
|
||||||
for (auto & [k, v] : nlohmann::json::parse(str, nullptr, false, true).template get<SandboxPaths>())
|
for (auto & [k, v] : nlohmann::json::parse(str, nullptr, false, true).template get<SandboxPaths>())
|
||||||
add(k, std::move(v));
|
add(k, std::move(v));
|
||||||
} else {
|
} else {
|
||||||
/* Parses legacy format sandbox-path e.g. "path[=source][?]".
|
|
||||||
* This format supports only a subset of options available with JSON format. */
|
|
||||||
for (std::string_view s : tokenizeString<Strings>(str)) {
|
for (std::string_view s : tokenizeString<Strings>(str)) {
|
||||||
bool optional = s.ends_with('?');
|
bool optional = s.ends_with('?');
|
||||||
if (optional) s.remove_suffix(1);
|
if (optional) s.remove_suffix(1);
|
||||||
if (size_t eq = s.find('='); eq != s.npos) {
|
if (size_t eq = s.find('='); eq != s.npos) {
|
||||||
add(std::string(s, 0, eq), { std::string(s.data() + eq + 1, s.size() - eq - 1), optional });
|
add(std::string(s, 0, eq), { std::string(s.data() + eq + 1, s.size() - eq - 1), optional });
|
||||||
} else
|
} else {
|
||||||
add(std::string(s), { "", optional });
|
add(std::string(s), { "", optional });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
@ -350,7 +350,7 @@ SandboxPaths SandboxPath::parse(const std::string_view & str, const std::string
|
||||||
|
|
||||||
template<> SandboxPaths BaseSetting<SandboxPaths>::parse(const std::string & str) const
|
template<> SandboxPaths BaseSetting<SandboxPaths>::parse(const std::string & str) const
|
||||||
{
|
{
|
||||||
return SandboxPath().parse(str, this->name);
|
return SandboxPath::parse(str, this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> struct BaseSetting<SandboxPaths>::trait
|
template<> struct BaseSetting<SandboxPaths>::trait
|
||||||
|
|
|
@ -25,6 +25,7 @@ struct SandboxPath;
|
||||||
using SandboxPaths = std::map<Path, SandboxPath, std::less<>>;
|
using SandboxPaths = std::map<Path, SandboxPath, std::less<>>;
|
||||||
struct SandboxPath
|
struct SandboxPath
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
ro = MS_RDONLY,
|
ro = MS_RDONLY,
|
||||||
|
@ -39,14 +40,19 @@ struct SandboxPath
|
||||||
slave = MS_SLAVE,
|
slave = MS_SLAVE,
|
||||||
unbindable = MS_UNBINDABLE
|
unbindable = MS_UNBINDABLE
|
||||||
#else
|
#else
|
||||||
ro // FIXME: do any options make sense on other that linux?
|
ro // FIXME: do any options make sense on other that linux?
|
||||||
#endif
|
#endif
|
||||||
} MountOpt;
|
} MountOpt;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
/* Options to set when readOnly=true */
|
/* Options to set when readOnly=true */
|
||||||
static constexpr std::array<MountOpt, 5> readOnlyDefaults = {
|
constexpr static MountOpt readOnlyDefaults[] = { ro, nodev, noexec, nosuid, noatime };
|
||||||
ro, nodev, noexec, nosuid, noatime
|
|
||||||
|
/* Only one atime option should be enabled at a time. Same for propagation
|
||||||
|
* style.*/
|
||||||
|
constexpr static std::pair<uint64_t, const char*> exclusiveOptionMasks[] = {
|
||||||
|
{MS_NOATIME | MS_NODIRATIME | MS_RELATIME | MS_STRICTATIME, "option-atime"},
|
||||||
|
{MS_SHARED | MS_PRIVATE | MS_SLAVE, "propagation"},
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -65,10 +71,18 @@ struct SandboxPath
|
||||||
|
|
||||||
std::vector<MountOpt> options;
|
std::vector<MountOpt> options;
|
||||||
|
|
||||||
SandboxPath(const Path & source = "",
|
SandboxPath(std::string source = "", bool optional = false,
|
||||||
bool optional = false, bool readOnly = false, const std::vector<MountOpt> & options = { })
|
bool readOnly = false, std::vector<MountOpt> options = { }) :
|
||||||
: source(source), optional(optional), readOnly(readOnly), options(options) { };
|
source(std::string(std::move(source))), optional(optional),
|
||||||
SandboxPath(const char * source) : SandboxPath(Path(source)) { };
|
readOnly(readOnly), options(std::move(options)) { }
|
||||||
|
|
||||||
|
/* This is to enable the full implicit conversion from e.g. const char[],
|
||||||
|
* even when binding a reference. Code can specify paths with literals and
|
||||||
|
* nothing extra. (Have angried the C++ deities with this? Seems like
|
||||||
|
* there should be a better way?) */
|
||||||
|
template<typename S, typename = std::enable_if_t<std::is_convertible_v<S, Path>>>
|
||||||
|
SandboxPath(S&& source, bool optional = false, bool readOnly = false) :
|
||||||
|
SandboxPath(Path(std::forward<S>(source)), optional, readOnly) { }
|
||||||
|
|
||||||
static SandboxPaths parse(const std::string_view & str, const std::string& = "(unknown)");
|
static SandboxPaths parse(const std::string_view & str, const std::string& = "(unknown)");
|
||||||
};
|
};
|
||||||
|
|
|
@ -106,7 +106,7 @@ protected:
|
||||||
* Stuff we need to pass to initChild().
|
* Stuff we need to pass to initChild().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef SandboxPaths PathsInChroot; // maps target path to source path
|
typedef SandboxPaths PathsInChroot;
|
||||||
|
|
||||||
typedef StringMap Environment;
|
typedef StringMap Environment;
|
||||||
Environment env;
|
Environment env;
|
||||||
|
@ -920,7 +920,7 @@ DerivationBuilderImpl::PathsInChroot DerivationBuilderImpl::getPathsInSandbox()
|
||||||
if (line == "") {
|
if (line == "") {
|
||||||
state = stBegin;
|
state = stBegin;
|
||||||
} else {
|
} else {
|
||||||
for (const auto & [k, v] : SandboxPath().parse(line))
|
for (const auto & [k, v] : SandboxPath::parse(line, "extra-sandbox-paths (via pre-build-hook)"))
|
||||||
pathsInChroot.try_emplace(k, v);
|
pathsInChroot.try_emplace(k, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,32 +121,30 @@ static void setupSeccomp()
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto combineMountOpts(auto init, auto iter)
|
static uint64_t mergeIntoMountOpts(uint64_t oset, uint64_t o) {
|
||||||
{
|
for (const auto & [mask, _] : SandboxPath::exclusiveOptionMasks)
|
||||||
return std::transform_reduce(iter.cbegin(), iter.cend(), init,
|
if (o & mask) return (oset & ~mask) | o;
|
||||||
[](unsigned long a, unsigned long b) {
|
return oset | o;
|
||||||
if (b & (MS_NOATIME | MS_RELATIME | MS_NODIRATIME | MS_STRICTATIME)) {
|
|
||||||
return (a & ~(MS_NOATIME | MS_NODIRATIME | MS_RELATIME | MS_STRICTATIME)) | b;
|
|
||||||
}
|
|
||||||
return a | b;
|
|
||||||
},
|
|
||||||
[](const SandboxPath::MountOpt & o) { return static_cast<unsigned long>(o); });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Iterable>
|
||||||
static void doBind(const SandboxPath & pval, const Path & target)
|
static uint64_t combineMountOpts(uint64_t init, const Iterable& opts)
|
||||||
{
|
{
|
||||||
auto source = pval.source;
|
return std::transform_reduce(std::begin(opts), std::end(opts), init, mergeIntoMountOpts,
|
||||||
auto optional = pval.optional;
|
[](const SandboxPath::MountOpt & o) { return static_cast<uint64_t>(o); });
|
||||||
debug("bind mounting '%1%' to '%2%'", source, target);
|
};
|
||||||
|
|
||||||
|
static void doBind(const SandboxPath & v, const Path & target)
|
||||||
|
{
|
||||||
|
debug("bind mounting '%1%' to '%2%'", v.source, target);
|
||||||
|
|
||||||
auto bindMount = [&]() {
|
auto bindMount = [&]() {
|
||||||
if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REC, 0) == -1)
|
if (mount(v.source.c_str(), target.c_str(), "", MS_BIND | MS_REC, 0) == -1)
|
||||||
throw SysError("bind mount from '%1%' to '%2%' failed", source, target);
|
throw SysError("bind mount from '%1%' to '%2%' failed", v.source, target);
|
||||||
|
|
||||||
// set extra options when wanted
|
// set extra options when wanted
|
||||||
auto flags = pval.readOnly ? combineMountOpts(0, pval.readOnlyDefaults) : 0;
|
auto flags = v.readOnly ? combineMountOpts(0, SandboxPath::readOnlyDefaults) : 0;
|
||||||
flags = combineMountOpts(flags, pval.options);
|
flags = combineMountOpts(flags, v.options);
|
||||||
if (flags != 0) {
|
if (flags != 0) {
|
||||||
// initial mount wouldn't respect MS_RDONLY, must remount
|
// initial mount wouldn't respect MS_RDONLY, must remount
|
||||||
debug("remounting '%s' with flags: %d", target, flags);
|
debug("remounting '%s' with flags: %d", target, flags);
|
||||||
|
@ -155,12 +153,12 @@ static void doBind(const SandboxPath & pval, const Path & target)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto maybeSt = maybeLstat(source);
|
auto maybeSt = maybeLstat(v.source);
|
||||||
if (!maybeSt) {
|
if (!maybeSt) {
|
||||||
if (optional)
|
if (v.optional)
|
||||||
return;
|
return;
|
||||||
else
|
else
|
||||||
throw SysError("getting attributes of path '%1%'", source);
|
throw SysError("getting attributes of path '%1%'", v.source);
|
||||||
}
|
}
|
||||||
auto st = *maybeSt;
|
auto st = *maybeSt;
|
||||||
|
|
||||||
|
@ -170,7 +168,7 @@ static void doBind(const SandboxPath & pval, const Path & target)
|
||||||
} else if (S_ISLNK(st.st_mode)) {
|
} else if (S_ISLNK(st.st_mode)) {
|
||||||
// Symlinks can (apparently) not be bind-mounted, so just copy it
|
// Symlinks can (apparently) not be bind-mounted, so just copy it
|
||||||
createDirs(dirOf(target));
|
createDirs(dirOf(target));
|
||||||
copyFile(std::filesystem::path(source), std::filesystem::path(target), false);
|
copyFile(std::filesystem::path(v.source), std::filesystem::path(target), false);
|
||||||
} else {
|
} else {
|
||||||
createDirs(dirOf(target));
|
createDirs(dirOf(target));
|
||||||
writeFile(target, "");
|
writeFile(target, "");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue