forked from lix-project/lix
Compare commits
18 commits
7685a0f5e0
...
537319e3b3
Author | SHA1 | Date | |
---|---|---|---|
alois31 | 537319e3b3 | ||
alois31 | 49623818c7 | ||
alois31 | 811cd63d5b | ||
alois31 | d1ebc7febc | ||
Delan Azabani | 4c3d93611f | ||
Delan Azabani | 37f276ba9d | ||
Delan Azabani | 5d33e4cd59 | ||
Delan Azabani | 3baffbdcc5 | ||
eldritch horrors | d477b34d1d | ||
eldritch horrors | 2bbdaf0b19 | ||
eldritch horrors | 2fe9157808 | ||
Qyriad | 521e08cbde | ||
Maximilian Bosch | 7c3b8229cc | ||
Qyriad | 701eb332bd | ||
Qyriad | ce4dee0fa5 | ||
Maximilian Bosch | 5f0062285c | ||
Maximilian Bosch | fc6a1451af | ||
Maximilian Bosch | 35eec921af |
|
@ -39,17 +39,19 @@ $ nix-shell -A native-clangStdenvPackages
|
|||
|
||||
### Building from the development shell
|
||||
|
||||
As always you may run [stdenv's phases by name](https://nixos.org/manual/nixpkgs/unstable/#sec-building-stdenv-package-in-nix-shell), e.g.:
|
||||
You can build and test Lix with just:
|
||||
|
||||
```bash
|
||||
$ configurePhase
|
||||
$ buildPhase
|
||||
$ checkPhase
|
||||
$ installPhase
|
||||
$ installCheckPhase
|
||||
$ just setup
|
||||
$ just build
|
||||
$ just test --suite=check
|
||||
$ just install
|
||||
$ just test --suite=installcheck
|
||||
```
|
||||
|
||||
To build manually, however, use the following:
|
||||
(Check and installcheck may both be done after install, allowing you to omit the --suite argument entirely, but this is the order package.nix runs them in.)
|
||||
|
||||
You can also build Lix manually:
|
||||
|
||||
```bash
|
||||
$ meson setup ./build "--prefix=$out" $mesonFlags
|
||||
|
@ -64,9 +66,7 @@ $ meson install -C build
|
|||
$ meson test -C build --suite=installcheck
|
||||
```
|
||||
|
||||
(Check and installcheck may both be done after install, allowing you to omit the --suite argument entirely, but this is the order package.nix runs them in.)
|
||||
|
||||
This will install Lix to `$PWD/outputs`, the `/bin` of which is prepended to PATH in the development shells.
|
||||
In both cases, Lix will be installed to `$PWD/outputs`, the `/bin` of which is prepended to PATH in the development shells.
|
||||
|
||||
If the tests fail and Meson helpfully has no output for why, use the `--print-error-logs` option to `meson test`.
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@
|
|||
nixUnstable = prev.nixUnstable;
|
||||
|
||||
check-headers = final.buildPackages.callPackage ./maintainers/check-headers.nix { };
|
||||
check-syscalls = final.buildPackages.callPackage ./maintainers/check-syscalls.nix { };
|
||||
|
||||
default-busybox-sandbox-shell = final.busybox.override {
|
||||
useMusl = true;
|
||||
|
|
2
justfile
2
justfile
|
@ -10,7 +10,7 @@ clean:
|
|||
|
||||
# Prepare meson for building
|
||||
setup:
|
||||
meson setup build --prefix="$PWD/outputs/out"
|
||||
meson setup build --prefix="$PWD/outputs/out" $mesonFlags
|
||||
|
||||
# Build lix
|
||||
build *OPTIONS:
|
||||
|
|
16
maintainers/check-syscalls.nix
Normal file
16
maintainers/check-syscalls.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
runCommandNoCC,
|
||||
lib,
|
||||
libseccomp,
|
||||
writeShellScriptBin,
|
||||
}:
|
||||
let
|
||||
syscalls-csv = runCommandNoCC "syscalls.csv" { } ''
|
||||
echo ${lib.escapeShellArg libseccomp.src}
|
||||
tar -xf ${lib.escapeShellArg libseccomp.src} --strip-components=2 ${libseccomp.name}/src/syscalls.csv
|
||||
mv syscalls.csv "$out"
|
||||
'';
|
||||
in
|
||||
writeShellScriptBin "check-syscalls" ''
|
||||
${./check-syscalls.sh} ${syscalls-csv}
|
||||
''
|
7
maintainers/check-syscalls.sh
Executable file
7
maintainers/check-syscalls.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
diff -u <(awk < src/libstore/build/local-derivation-goal.cc '/BEGIN extract-syscalls/ { extracting = 1; next }
|
||||
match($0, /allowSyscall\(ctx, SCMP_SYS\(([^)]*)\)\);|\/\/ skip ([^ ]*)/, result) { print result[1] result[2] }
|
||||
/END extract-syscalls/ { extracting = 0; next }') <(tail -n+2 "$1" | cut -d, -f 1)
|
|
@ -402,6 +402,7 @@ stdenv.mkDerivation (finalAttrs: {
|
|||
# Lix specific packages
|
||||
pre-commit-checks,
|
||||
contribNotice,
|
||||
check-syscalls,
|
||||
}:
|
||||
let
|
||||
glibcFix = lib.optionalAttrs (buildPlatform.isLinux && glibcLocales != null) {
|
||||
|
@ -455,6 +456,7 @@ stdenv.mkDerivation (finalAttrs: {
|
|||
pythonEnv
|
||||
# docker image tool
|
||||
skopeo
|
||||
check-syscalls
|
||||
just
|
||||
nixfmt
|
||||
# Load-bearing order. Must come before clang-unwrapped below, but after clang_tools above.
|
||||
|
|
|
@ -60,7 +60,7 @@ static bool allSupportedLocally(Store & store, const std::set<std::string>& requ
|
|||
static int main_build_remote(int argc, char * * argv)
|
||||
{
|
||||
{
|
||||
logger = makeJSONLogger(*logger);
|
||||
logger = makeJSONLogger(std::move(logger));
|
||||
|
||||
/* Ensure we don't get any SSH passphrase or host key popups. */
|
||||
unsetenv("DISPLAY");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <cstdio>
|
||||
#include <editline.h>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
@ -242,8 +243,7 @@ NixRepl::NixRepl(const SearchPath & searchPath, nix::ref<Store> store, ref<EvalS
|
|||
{
|
||||
}
|
||||
|
||||
void runNix(Path program, const Strings & args,
|
||||
const std::optional<std::string> & input = {})
|
||||
void runNix(Path program, const Strings & args)
|
||||
{
|
||||
auto subprocessEnv = getEnv();
|
||||
subprocessEnv["NIX_CONFIG"] = globalConfig.toKeyValue();
|
||||
|
@ -252,7 +252,6 @@ void runNix(Path program, const Strings & args,
|
|||
.program = settings.nixBinDir+ "/" + program,
|
||||
.args = args,
|
||||
.environment = subprocessEnv,
|
||||
.input = input,
|
||||
});
|
||||
|
||||
return;
|
||||
|
|
|
@ -204,7 +204,13 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
|||
std::string fragment;
|
||||
std::swap(fragment, parsedURL.fragment);
|
||||
|
||||
auto input = Input::fromURL(parsedURL, isFlake);
|
||||
// This has a special meaning for flakes and must not be passed to libfetchers.
|
||||
// Of course this means that libfetchers cannot have fetchers
|
||||
// expecting an argument `dir` 🫠
|
||||
ParsedURL urlForFetchers(parsedURL);
|
||||
urlForFetchers.query.erase("dir");
|
||||
|
||||
auto input = Input::fromURL(urlForFetchers, isFlake);
|
||||
input.parent = baseDir;
|
||||
|
||||
return std::make_pair(
|
||||
|
|
|
@ -159,6 +159,37 @@ struct InputScheme
|
|||
std::optional<std::string> commitMsg) const;
|
||||
|
||||
virtual std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) = 0;
|
||||
|
||||
protected:
|
||||
void emplaceURLQueryIntoAttrs(
|
||||
const ParsedURL & parsedURL,
|
||||
Attrs & attrs,
|
||||
const StringSet & numericParams,
|
||||
const StringSet & booleanParams) const
|
||||
{
|
||||
for (auto &[name, value] : parsedURL.query) {
|
||||
if (name == "url") {
|
||||
throw BadURL(
|
||||
"URL '%s' must not override url via query param!",
|
||||
parsedURL.to_string()
|
||||
);
|
||||
} else if (numericParams.count(name) != 0) {
|
||||
if (auto n = string2Int<uint64_t>(value)) {
|
||||
attrs.insert_or_assign(name, *n);
|
||||
} else {
|
||||
throw BadURL(
|
||||
"URL '%s' has non-numeric parameter '%s'",
|
||||
parsedURL.to_string(),
|
||||
name
|
||||
);
|
||||
}
|
||||
} else if (booleanParams.count(name) != 0) {
|
||||
attrs.emplace(name, Explicit<bool> { value == "1" });
|
||||
} else {
|
||||
attrs.emplace(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);
|
||||
|
|
|
@ -273,18 +273,15 @@ struct GitInputScheme : InputScheme
|
|||
|
||||
Attrs attrs;
|
||||
attrs.emplace("type", "git");
|
||||
|
||||
for (auto & [name, value] : url.query) {
|
||||
if (name == "rev" || name == "ref")
|
||||
attrs.emplace(name, value);
|
||||
else if (name == "shallow" || name == "submodules" || name == "allRefs")
|
||||
attrs.emplace(name, Explicit<bool> { value == "1" });
|
||||
else
|
||||
url2.query.emplace(name, value);
|
||||
}
|
||||
|
||||
attrs.emplace("url", url2.to_string());
|
||||
|
||||
emplaceURLQueryIntoAttrs(
|
||||
url,
|
||||
attrs,
|
||||
{"lastModified", "revCount"},
|
||||
{"shallow", "submodules", "allRefs"}
|
||||
);
|
||||
|
||||
return inputFromAttrs(attrs);
|
||||
}
|
||||
|
||||
|
@ -361,7 +358,7 @@ struct GitInputScheme : InputScheme
|
|||
|
||||
args.push_back(destDir);
|
||||
|
||||
runProgram("git", true, args, {}, true);
|
||||
runProgram("git", true, args, true);
|
||||
}
|
||||
|
||||
std::optional<Path> getSourcePath(const Input & input) const override
|
||||
|
@ -399,12 +396,15 @@ struct GitInputScheme : InputScheme
|
|||
|
||||
|
||||
if (commitMsg) {
|
||||
auto [_fd, msgPath] = createTempFile("nix-msg");
|
||||
AutoDelete const _delete{msgPath};
|
||||
writeFile(msgPath, *commitMsg);
|
||||
|
||||
// Pause the logger to allow for user input (such as a gpg passphrase) in `git commit`
|
||||
logger->pause();
|
||||
Finally restoreLogger([]() { logger->resume(); });
|
||||
runProgram("git", true,
|
||||
{ "-C", *root, "--git-dir", gitDir, "commit", std::string(path.rel()), "-F", "-" },
|
||||
*commitMsg);
|
||||
{ "-C", *root, "--git-dir", gitDir, "commit", std::string(path.rel()), "-F", msgPath });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -589,7 +589,7 @@ struct GitInputScheme : InputScheme
|
|||
: ref == "HEAD"
|
||||
? *ref
|
||||
: "refs/heads/" + *ref;
|
||||
runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "fetch", "--quiet", "--force", "--", actualUrl, fmt("%s:%s", fetchRef, fetchRef) }, {}, true);
|
||||
runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "fetch", "--quiet", "--force", "--", actualUrl, fmt("%s:%s", fetchRef, fetchRef) }, true);
|
||||
} catch (Error & e) {
|
||||
if (!pathExists(localRefFile)) throw;
|
||||
warn("could not update local clone of Git repository '%s'; continuing with the most recent version", actualUrl);
|
||||
|
@ -656,7 +656,7 @@ struct GitInputScheme : InputScheme
|
|||
// everything to ensure we get the rev.
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("making temporary clone of '%s'", repoDir));
|
||||
runProgram("git", true, { "-C", tmpDir, "fetch", "--quiet", "--force",
|
||||
"--update-head-ok", "--", repoDir, "refs/*:refs/*" }, {}, true);
|
||||
"--update-head-ok", "--", repoDir, "refs/*:refs/*" }, true);
|
||||
}
|
||||
|
||||
runProgram("git", true, { "-C", tmpDir, "checkout", "--quiet", input.getRev()->gitRev() });
|
||||
|
@ -683,7 +683,7 @@ struct GitInputScheme : InputScheme
|
|||
|
||||
{
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching submodules of '%s'", actualUrl));
|
||||
runProgram("git", true, { "-C", tmpDir, "submodule", "--quiet", "update", "--init", "--recursive" }, {}, true);
|
||||
runProgram("git", true, { "-C", tmpDir, "submodule", "--quiet", "update", "--init", "--recursive" }, true);
|
||||
}
|
||||
|
||||
filter = isNotDotGitDirectory;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "attrs.hh"
|
||||
#include "filetransfer.hh"
|
||||
#include "cache.hh"
|
||||
#include "globals.hh"
|
||||
|
@ -36,18 +37,11 @@ struct GitArchiveInputScheme : InputScheme
|
|||
|
||||
auto path = tokenizeString<std::vector<std::string>>(url.path, "/");
|
||||
|
||||
std::optional<Hash> rev;
|
||||
std::optional<std::string> ref;
|
||||
std::optional<std::string> host_url;
|
||||
std::optional<std::string> refOrRev;
|
||||
|
||||
auto size = path.size();
|
||||
if (size == 3) {
|
||||
if (std::regex_match(path[2], revRegex))
|
||||
rev = Hash::parseAny(path[2], htSHA1);
|
||||
else if (std::regex_match(path[2], refRegex))
|
||||
ref = path[2];
|
||||
else
|
||||
throw BadURL("in URL '%s', '%s' is not a commit hash or branch/tag name", url.url, path[2]);
|
||||
refOrRev = path[2];
|
||||
} else if (size > 3) {
|
||||
std::string rs;
|
||||
for (auto i = std::next(path.begin(), 2); i != path.end(); i++) {
|
||||
|
@ -58,61 +52,91 @@ struct GitArchiveInputScheme : InputScheme
|
|||
}
|
||||
|
||||
if (std::regex_match(rs, refRegex)) {
|
||||
ref = rs;
|
||||
refOrRev = rs;
|
||||
} else {
|
||||
throw BadURL("in URL '%s', '%s' is not a branch/tag name", url.url, rs);
|
||||
}
|
||||
} else if (size < 2)
|
||||
throw BadURL("URL '%s' is invalid", url.url);
|
||||
|
||||
Attrs attrs;
|
||||
attrs.emplace("type", type());
|
||||
attrs.emplace("owner", path[0]);
|
||||
attrs.emplace("repo", path[1]);
|
||||
|
||||
for (auto &[name, value] : url.query) {
|
||||
if (name == "rev") {
|
||||
if (rev)
|
||||
throw BadURL("URL '%s' contains multiple commit hashes", url.url);
|
||||
rev = Hash::parseAny(value, htSHA1);
|
||||
if (name == "rev" || name == "ref") {
|
||||
if (refOrRev) {
|
||||
throw BadURL("URL '%s' already contains a ref or rev", url.url);
|
||||
} else {
|
||||
refOrRev = value;
|
||||
}
|
||||
else if (name == "ref") {
|
||||
if (!std::regex_match(value, refRegex))
|
||||
throw BadURL("URL '%s' contains an invalid branch/tag name", url.url);
|
||||
if (ref)
|
||||
throw BadURL("URL '%s' contains multiple branch/tag names", url.url);
|
||||
ref = value;
|
||||
} else if (name == "lastModified") {
|
||||
if (auto n = string2Int<uint64_t>(value)) {
|
||||
attrs.emplace(name, *n);
|
||||
} else {
|
||||
throw Error(
|
||||
"Attribute 'lastModified' in URL '%s' must be an integer",
|
||||
url.to_string()
|
||||
);
|
||||
}
|
||||
else if (name == "host") {
|
||||
if (!std::regex_match(value, hostRegex))
|
||||
throw BadURL("URL '%s' contains an invalid instance host", url.url);
|
||||
host_url = value;
|
||||
} else {
|
||||
attrs.emplace(name, value);
|
||||
}
|
||||
// FIXME: barf on unsupported attributes
|
||||
}
|
||||
|
||||
if (ref && rev)
|
||||
throw BadURL("URL '%s' contains both a commit hash and a branch/tag name %s %s", url.url, *ref, rev->gitRev());
|
||||
if (refOrRev) attrs.emplace("refOrRev", *refOrRev);
|
||||
|
||||
Input input;
|
||||
input.attrs.insert_or_assign("type", type());
|
||||
input.attrs.insert_or_assign("owner", path[0]);
|
||||
input.attrs.insert_or_assign("repo", path[1]);
|
||||
if (rev) input.attrs.insert_or_assign("rev", rev->gitRev());
|
||||
if (ref) input.attrs.insert_or_assign("ref", *ref);
|
||||
if (host_url) input.attrs.insert_or_assign("host", *host_url);
|
||||
|
||||
return input;
|
||||
return inputFromAttrs(attrs);
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
{
|
||||
if (maybeGetStrAttr(attrs, "type") != type()) return {};
|
||||
// Attributes can contain refOrRev and it needs to be figured out
|
||||
// which one it is (see inputFromURL for when that may happen).
|
||||
// The correct one (ref or rev) will be written into finalAttrs and
|
||||
// it needs to be mutable for that.
|
||||
Attrs finalAttrs(attrs);
|
||||
auto type_ = maybeGetStrAttr(finalAttrs, "type");
|
||||
if (type_ != type()) return {};
|
||||
|
||||
for (auto & [name, value] : attrs)
|
||||
if (name != "type" && name != "owner" && name != "repo" && name != "ref" && name != "rev" && name != "narHash" && name != "lastModified" && name != "host")
|
||||
auto owner = getStrAttr(finalAttrs, "owner");
|
||||
auto repo = getStrAttr(finalAttrs, "repo");
|
||||
|
||||
auto url = fmt("%s:%s/%s", *type_, owner, repo);
|
||||
if (auto host = maybeGetStrAttr(finalAttrs, "host")) {
|
||||
if (!std::regex_match(*host, hostRegex)) {
|
||||
throw BadURL("URL '%s' contains an invalid instance host", url);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto refOrRev = maybeGetStrAttr(finalAttrs, "refOrRev")) {
|
||||
finalAttrs.erase("refOrRev");
|
||||
if (std::regex_match(*refOrRev, revRegex)) {
|
||||
finalAttrs.emplace("rev", *refOrRev);
|
||||
} else if (std::regex_match(*refOrRev, refRegex)) {
|
||||
finalAttrs.emplace("ref", *refOrRev);
|
||||
} else {
|
||||
throw Error(
|
||||
"in URL '%s', '%s' is not a commit hash or a branch/tag name",
|
||||
url,
|
||||
*refOrRev
|
||||
);
|
||||
}
|
||||
} else if (auto ref = maybeGetStrAttr(finalAttrs, "ref")) {
|
||||
if (!std::regex_match(*ref, refRegex)) {
|
||||
throw BadURL("URL '%s' contains an invalid branch/tag name", url);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto & [name, value] : finalAttrs) {
|
||||
if (name != "type" && name != "owner" && name != "repo" && name != "ref" && name != "rev" && name != "narHash" && name != "lastModified" && name != "host") {
|
||||
throw Error("unsupported input attribute '%s'", name);
|
||||
|
||||
getStrAttr(attrs, "owner");
|
||||
getStrAttr(attrs, "repo");
|
||||
}
|
||||
}
|
||||
|
||||
Input input;
|
||||
input.attrs = attrs;
|
||||
input.attrs = finalAttrs;
|
||||
return input;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ struct IndirectInputScheme : InputScheme
|
|||
std::optional<Hash> rev;
|
||||
std::optional<std::string> ref;
|
||||
|
||||
Attrs attrs;
|
||||
|
||||
if (path.size() == 1) {
|
||||
} else if (path.size() == 2) {
|
||||
if (std::regex_match(path[1], revRegex))
|
||||
|
@ -26,29 +28,21 @@ struct IndirectInputScheme : InputScheme
|
|||
else
|
||||
throw BadURL("in flake URL '%s', '%s' is not a commit hash or branch/tag name", url.url, path[1]);
|
||||
} else if (path.size() == 3) {
|
||||
if (!std::regex_match(path[1], refRegex))
|
||||
throw BadURL("in flake URL '%s', '%s' is not a branch/tag name", url.url, path[1]);
|
||||
ref = path[1];
|
||||
if (!std::regex_match(path[2], revRegex))
|
||||
throw BadURL("in flake URL '%s', '%s' is not a commit hash", url.url, path[2]);
|
||||
rev = Hash::parseAny(path[2], htSHA1);
|
||||
} else
|
||||
throw BadURL("GitHub URL '%s' is invalid", url.url);
|
||||
|
||||
std::string id = path[0];
|
||||
if (!std::regex_match(id, flakeRegex))
|
||||
throw BadURL("'%s' is not a valid flake ID", id);
|
||||
|
||||
// FIXME: forbid query params?
|
||||
attrs.emplace("type", "indirect");
|
||||
attrs.emplace("id", id);
|
||||
if (rev) attrs.emplace("rev", rev->gitRev());
|
||||
if (ref) attrs.emplace("ref", *ref);
|
||||
|
||||
Input input;
|
||||
input.direct = false;
|
||||
input.attrs.insert_or_assign("type", "indirect");
|
||||
input.attrs.insert_or_assign("id", id);
|
||||
if (rev) input.attrs.insert_or_assign("rev", rev->gitRev());
|
||||
if (ref) input.attrs.insert_or_assign("ref", *ref);
|
||||
emplaceURLQueryIntoAttrs(url, attrs, {}, {});
|
||||
|
||||
return input;
|
||||
return inputFromAttrs(attrs);
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
|
@ -63,6 +57,18 @@ struct IndirectInputScheme : InputScheme
|
|||
if (!std::regex_match(id, flakeRegex))
|
||||
throw BadURL("'%s' is not a valid flake ID", id);
|
||||
|
||||
// TODO come up with a nicer error message for those two.
|
||||
if (auto rev = maybeGetStrAttr(attrs, "rev")) {
|
||||
if (!std::regex_match(*rev, revRegex)) {
|
||||
throw BadURL("in flake '%s', '%s' is not a commit hash", id, *rev);
|
||||
}
|
||||
}
|
||||
if (auto ref = maybeGetStrAttr(attrs, "ref")) {
|
||||
if (!std::regex_match(*ref, refRegex)) {
|
||||
throw BadURL("in flake '%s', '%s' is not a valid branch/tag name", id, *ref);
|
||||
}
|
||||
}
|
||||
|
||||
Input input;
|
||||
input.direct = false;
|
||||
input.attrs = attrs;
|
||||
|
|
|
@ -28,10 +28,9 @@ static RunOptions hgOptions(const Strings & args)
|
|||
}
|
||||
|
||||
// runProgram wrapper that uses hgOptions instead of stock RunOptions.
|
||||
static std::string runHg(const Strings & args, const std::optional<std::string> & input = {})
|
||||
static std::string runHg(const Strings & args)
|
||||
{
|
||||
RunOptions opts = hgOptions(args);
|
||||
opts.input = input;
|
||||
|
||||
auto res = runProgram(std::move(opts));
|
||||
|
||||
|
@ -57,12 +56,7 @@ struct MercurialInputScheme : InputScheme
|
|||
Attrs attrs;
|
||||
attrs.emplace("type", "hg");
|
||||
|
||||
for (auto &[name, value] : url.query) {
|
||||
if (name == "rev" || name == "ref")
|
||||
attrs.emplace(name, value);
|
||||
else
|
||||
url2.query.emplace(name, value);
|
||||
}
|
||||
emplaceURLQueryIntoAttrs(url, attrs, {"revCount"}, {});
|
||||
|
||||
attrs.emplace("url", url2.to_string());
|
||||
|
||||
|
|
|
@ -201,29 +201,17 @@ struct CurlInputScheme : InputScheme
|
|||
if (!isValidURL(_url, requireTree))
|
||||
return std::nullopt;
|
||||
|
||||
Input input;
|
||||
|
||||
auto url = _url;
|
||||
|
||||
Attrs attrs;
|
||||
attrs.emplace("type", inputType());
|
||||
|
||||
url.scheme = parseUrlScheme(url.scheme).transport;
|
||||
|
||||
auto narHash = url.query.find("narHash");
|
||||
if (narHash != url.query.end())
|
||||
input.attrs.insert_or_assign("narHash", narHash->second);
|
||||
emplaceURLQueryIntoAttrs(url, attrs, {"revCount"}, {});
|
||||
|
||||
if (auto i = get(url.query, "rev"))
|
||||
input.attrs.insert_or_assign("rev", *i);
|
||||
|
||||
if (auto i = get(url.query, "revCount"))
|
||||
if (auto n = string2Int<uint64_t>(*i))
|
||||
input.attrs.insert_or_assign("revCount", *n);
|
||||
|
||||
url.query.erase("rev");
|
||||
url.query.erase("revCount");
|
||||
|
||||
input.attrs.insert_or_assign("type", inputType());
|
||||
input.attrs.insert_or_assign("url", url.to_string());
|
||||
return input;
|
||||
attrs.emplace("url", url.to_string());
|
||||
return inputFromAttrs(attrs);
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
|
@ -235,7 +223,7 @@ struct CurlInputScheme : InputScheme
|
|||
std::set<std::string> allowedNames = {"type", "url", "narHash", "name", "unpack", "rev", "revCount", "lastModified"};
|
||||
for (auto & [name, value] : attrs)
|
||||
if (!allowedNames.count(name))
|
||||
throw Error("unsupported %s input attribute '%s'", *type, name);
|
||||
throw Error("unsupported %s input attribute '%s'. If you wanted to fetch a tarball with a query parameter, please use '{ type = \"tarball\"; url = \"...\"; }'", *type, name);
|
||||
|
||||
Input input;
|
||||
input.attrs = attrs;
|
||||
|
|
|
@ -24,14 +24,14 @@ LogFormat parseLogFormat(const std::string & logFormatStr) {
|
|||
throw Error("option 'log-format' has an invalid value '%s'", logFormatStr);
|
||||
}
|
||||
|
||||
Logger * makeDefaultLogger() {
|
||||
std::unique_ptr<Logger> makeDefaultLogger() {
|
||||
switch (defaultLogFormat) {
|
||||
case LogFormat::raw:
|
||||
return makeSimpleLogger(false);
|
||||
case LogFormat::rawWithLogs:
|
||||
return makeSimpleLogger(true);
|
||||
case LogFormat::internalJSON:
|
||||
return makeJSONLogger(*makeSimpleLogger(true));
|
||||
return makeJSONLogger(makeSimpleLogger(true));
|
||||
case LogFormat::bar:
|
||||
return makeProgressBar();
|
||||
case LogFormat::barWithLogs: {
|
||||
|
|
|
@ -13,6 +13,11 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
// 100 years ought to be enough for anyone (yet sufficiently smaller than max() to not cause signed integer overflow).
|
||||
constexpr const auto A_LONG_TIME = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
100 * 365 * std::chrono::seconds(86400)
|
||||
);
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
static std::string_view getS(const std::vector<Logger::Field> & fields, size_t n)
|
||||
|
@ -36,6 +41,24 @@ static std::string_view storePathToName(std::string_view path)
|
|||
return i == std::string::npos ? base.substr(0, 0) : base.substr(i + 1);
|
||||
}
|
||||
|
||||
ProgressBar::ProgressBar(bool isTTY)
|
||||
: isTTY(isTTY)
|
||||
{
|
||||
if ((state_.lock()->active = isTTY)) {
|
||||
// Only start the update thread when the logger is set to active.
|
||||
// Otherwise, the destructor will std::terminate trying to destroy a joinable thread.
|
||||
updateThread = std::thread([&]() {
|
||||
auto state(state_.lock());
|
||||
auto nextWakeup = A_LONG_TIME;
|
||||
while (state->active) {
|
||||
if (!state->haveUpdate)
|
||||
state.wait_for(updateCV, nextWakeup);
|
||||
nextWakeup = draw(*state, {});
|
||||
state.wait_for(quitCV, std::chrono::milliseconds(50));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ProgressBar::~ProgressBar()
|
||||
{
|
||||
|
@ -402,31 +425,59 @@ std::string ProgressBar::getStatus(State & state)
|
|||
|
||||
expected = std::max(expected, act.expected);
|
||||
|
||||
std::string s;
|
||||
std::string rendered;
|
||||
|
||||
if (running || done || expected || failed) {
|
||||
if (running)
|
||||
if (expected != 0)
|
||||
s = fmt(ANSI_BLUE + numberFmt + ANSI_NORMAL "/" ANSI_GREEN + numberFmt + ANSI_NORMAL "/" + numberFmt,
|
||||
running / unit, done / unit, expected / unit);
|
||||
else
|
||||
s = fmt(ANSI_BLUE + numberFmt + ANSI_NORMAL "/" ANSI_GREEN + numberFmt + ANSI_NORMAL,
|
||||
running / unit, done / unit);
|
||||
else if (expected != done)
|
||||
if (expected != 0)
|
||||
s = fmt(ANSI_GREEN + numberFmt + ANSI_NORMAL "/" + numberFmt,
|
||||
done / unit, expected / unit);
|
||||
else
|
||||
s = fmt(ANSI_GREEN + numberFmt + ANSI_NORMAL, done / unit);
|
||||
else
|
||||
s = fmt(done ? ANSI_GREEN + numberFmt + ANSI_NORMAL : numberFmt, done / unit);
|
||||
s = fmt(itemFmt, s);
|
||||
if (running) {
|
||||
if (expected != 0) {
|
||||
auto const runningPart = fmt(numberFmt, running / unit);
|
||||
auto const donePart = fmt(numberFmt, done / unit);
|
||||
auto const expectedPart = fmt(numberFmt, expected / unit);
|
||||
rendered = fmt(
|
||||
ANSI_BLUE "%s" ANSI_NORMAL "/" ANSI_GREEN "%s" ANSI_NORMAL "/%s",
|
||||
runningPart,
|
||||
donePart,
|
||||
expectedPart
|
||||
);
|
||||
} else {
|
||||
auto const runningPart = fmt(numberFmt, running / unit);
|
||||
auto const donePart = fmt(numberFmt, done / unit);
|
||||
rendered = fmt(
|
||||
ANSI_BLUE "%s" ANSI_NORMAL "/" ANSI_GREEN "%s" ANSI_NORMAL,
|
||||
runningPart,
|
||||
donePart
|
||||
);
|
||||
}
|
||||
} else if (expected != done) {
|
||||
if (expected != 0) {
|
||||
auto const donePart = fmt(numberFmt, done / unit);
|
||||
auto const expectedPart = fmt(numberFmt, expected / unit);
|
||||
rendered = fmt(
|
||||
ANSI_GREEN "%s" ANSI_NORMAL "/%s",
|
||||
donePart,
|
||||
expectedPart
|
||||
);
|
||||
} else {
|
||||
auto const donePart = fmt(numberFmt, done / unit);
|
||||
rendered = fmt(ANSI_GREEN "%s" ANSI_NORMAL, donePart);
|
||||
}
|
||||
} else {
|
||||
auto const donePart = fmt(numberFmt, done / unit);
|
||||
|
||||
// We only color if `done` is non-zero.
|
||||
if (done) {
|
||||
rendered = concatStrings(ANSI_GREEN, donePart, ANSI_NORMAL);
|
||||
} else {
|
||||
rendered = donePart;
|
||||
}
|
||||
}
|
||||
rendered = fmt(itemFmt, rendered);
|
||||
|
||||
if (failed)
|
||||
s += fmt(" (" ANSI_RED "%d failed" ANSI_NORMAL ")", failed / unit);
|
||||
rendered += fmt(" (" ANSI_RED "%d failed" ANSI_NORMAL ")", failed / unit);
|
||||
}
|
||||
|
||||
return s;
|
||||
return rendered;
|
||||
};
|
||||
|
||||
auto showActivity = [&](ActivityType type, const std::string & itemFmt, const std::string & numberFmt = "%d", double unit = 1) {
|
||||
|
@ -506,9 +557,9 @@ void ProgressBar::setPrintMultiline(bool printMultiline)
|
|||
this->printMultiline = printMultiline;
|
||||
}
|
||||
|
||||
Logger * makeProgressBar()
|
||||
std::unique_ptr<Logger> makeProgressBar()
|
||||
{
|
||||
return new ProgressBar(shouldANSI());
|
||||
return std::make_unique<ProgressBar>(shouldANSI());
|
||||
}
|
||||
|
||||
void startProgressBar()
|
||||
|
@ -518,7 +569,7 @@ void startProgressBar()
|
|||
|
||||
void stopProgressBar()
|
||||
{
|
||||
auto progressBar = dynamic_cast<ProgressBar *>(logger);
|
||||
auto progressBar = dynamic_cast<ProgressBar *>(logger.get());
|
||||
if (progressBar) progressBar->stop();
|
||||
|
||||
}
|
||||
|
|
|
@ -8,11 +8,6 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
// 100 years ought to be enough for anyone (yet sufficiently smaller than max() to not cause signed integer overflow).
|
||||
constexpr const auto A_LONG_TIME = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
100 * 365 * std::chrono::seconds(86400)
|
||||
);
|
||||
|
||||
struct ProgressBar : public Logger
|
||||
{
|
||||
struct ActInfo
|
||||
|
@ -68,21 +63,7 @@ struct ProgressBar : public Logger
|
|||
bool printMultiline = false;
|
||||
bool isTTY;
|
||||
|
||||
ProgressBar(bool isTTY)
|
||||
: isTTY(isTTY)
|
||||
{
|
||||
state_.lock()->active = isTTY;
|
||||
updateThread = std::thread([&]() {
|
||||
auto state(state_.lock());
|
||||
auto nextWakeup = A_LONG_TIME;
|
||||
while (state->active) {
|
||||
if (!state->haveUpdate)
|
||||
state.wait_for(updateCV, nextWakeup);
|
||||
nextWakeup = draw(*state, {});
|
||||
state.wait_for(quitCV, std::chrono::milliseconds(50));
|
||||
}
|
||||
});
|
||||
}
|
||||
ProgressBar(bool isTTY);
|
||||
|
||||
~ProgressBar();
|
||||
|
||||
|
@ -130,7 +111,7 @@ struct ProgressBar : public Logger
|
|||
void setPrintMultiline(bool printMultiline) override;
|
||||
};
|
||||
|
||||
Logger * makeProgressBar();
|
||||
std::unique_ptr<Logger> makeProgressBar();
|
||||
|
||||
void startProgressBar();
|
||||
|
||||
|
|
|
@ -760,7 +760,7 @@ void DerivationGoal::tryToBuild()
|
|||
/* Not now; wait until at least one child finishes or
|
||||
the wake-up timeout expires. */
|
||||
if (!actLock)
|
||||
actLock = std::make_unique<Activity>(*logger, lvlWarn, actBuildWaiting,
|
||||
actLock = std::make_unique<Activity>(*logger, lvlTalkative, actBuildWaiting,
|
||||
fmt("waiting for a machine to build '%s'", Magenta(worker.store.printStorePath(drvPath))));
|
||||
worker.waitForAWhile(shared_from_this());
|
||||
outputLocks.unlock();
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#if HAVE_SECCOMP
|
||||
#include "linux/fchmodat2-compat.hh"
|
||||
#include <seccomp.h>
|
||||
#endif
|
||||
#define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old))
|
||||
|
@ -1602,6 +1601,12 @@ void LocalDerivationGoal::chownToBuilder(const Path & path)
|
|||
throw SysError("cannot change ownership of '%1%'", path);
|
||||
}
|
||||
|
||||
#if HAVE_SECCOMP
|
||||
void allowSyscall(scmp_filter_ctx ctx, int syscall) {
|
||||
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall, 0) != 0)
|
||||
throw SysError("unable to add seccomp rule");
|
||||
}
|
||||
#endif
|
||||
|
||||
void setupSeccomp()
|
||||
{
|
||||
|
@ -1609,7 +1614,9 @@ void setupSeccomp()
|
|||
#if HAVE_SECCOMP
|
||||
scmp_filter_ctx ctx;
|
||||
|
||||
if (!(ctx = seccomp_init(SCMP_ACT_ALLOW)))
|
||||
// Pretend that syscalls we don't yet know about don't exist.
|
||||
// This is the best option for compatibility: after all, they did in fact not exist not too long ago.
|
||||
if (!(ctx = seccomp_init(SCMP_ACT_ERRNO(ENOSYS))))
|
||||
throw SysError("unable to initialize seccomp mode 2");
|
||||
|
||||
Finally cleanup([&]() {
|
||||
|
@ -1644,28 +1651,520 @@ void setupSeccomp()
|
|||
seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL64N32) != 0)
|
||||
printError("unable to add mips64el-*abin32 seccomp architecture");
|
||||
|
||||
/* Prevent builders from creating setuid/setgid binaries. */
|
||||
for (int perm : { S_ISUID, S_ISGID }) {
|
||||
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(chmod), 1,
|
||||
SCMP_A1(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
|
||||
// This list is intended for machine consumption.
|
||||
// Please keep its format, order and BEGIN/END markers.
|
||||
//
|
||||
// Currently, it is up to date with libseccomp 2.5.5 and glibc 2.38.
|
||||
// Run check-syscalls to determine which new syscalls should be added.
|
||||
// New syscalls must be audited and handled in a way that blocks the following dangerous operations:
|
||||
// * Creation of non-empty setuid/setgid files
|
||||
// * Creation of extended attributes (including ACLs)
|
||||
//
|
||||
// BEGIN extract-syscalls
|
||||
allowSyscall(ctx, SCMP_SYS(accept));
|
||||
allowSyscall(ctx, SCMP_SYS(accept4));
|
||||
allowSyscall(ctx, SCMP_SYS(access));
|
||||
allowSyscall(ctx, SCMP_SYS(acct));
|
||||
allowSyscall(ctx, SCMP_SYS(add_key));
|
||||
allowSyscall(ctx, SCMP_SYS(adjtimex));
|
||||
allowSyscall(ctx, SCMP_SYS(afs_syscall));
|
||||
allowSyscall(ctx, SCMP_SYS(alarm));
|
||||
allowSyscall(ctx, SCMP_SYS(arch_prctl));
|
||||
allowSyscall(ctx, SCMP_SYS(arm_fadvise64_64));
|
||||
allowSyscall(ctx, SCMP_SYS(arm_sync_file_range));
|
||||
allowSyscall(ctx, SCMP_SYS(bdflush));
|
||||
allowSyscall(ctx, SCMP_SYS(bind));
|
||||
allowSyscall(ctx, SCMP_SYS(bpf));
|
||||
allowSyscall(ctx, SCMP_SYS(break));
|
||||
allowSyscall(ctx, SCMP_SYS(breakpoint));
|
||||
allowSyscall(ctx, SCMP_SYS(brk));
|
||||
allowSyscall(ctx, SCMP_SYS(cachectl));
|
||||
allowSyscall(ctx, SCMP_SYS(cacheflush));
|
||||
allowSyscall(ctx, SCMP_SYS(cachestat));
|
||||
allowSyscall(ctx, SCMP_SYS(capget));
|
||||
allowSyscall(ctx, SCMP_SYS(capset));
|
||||
allowSyscall(ctx, SCMP_SYS(chdir));
|
||||
// skip chmod (dangerous)
|
||||
allowSyscall(ctx, SCMP_SYS(chown));
|
||||
allowSyscall(ctx, SCMP_SYS(chown32));
|
||||
allowSyscall(ctx, SCMP_SYS(chroot));
|
||||
allowSyscall(ctx, SCMP_SYS(clock_adjtime));
|
||||
allowSyscall(ctx, SCMP_SYS(clock_adjtime64));
|
||||
allowSyscall(ctx, SCMP_SYS(clock_getres));
|
||||
allowSyscall(ctx, SCMP_SYS(clock_getres_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(clock_gettime));
|
||||
allowSyscall(ctx, SCMP_SYS(clock_gettime64));
|
||||
allowSyscall(ctx, SCMP_SYS(clock_nanosleep));
|
||||
allowSyscall(ctx, SCMP_SYS(clock_nanosleep_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(clock_settime));
|
||||
allowSyscall(ctx, SCMP_SYS(clock_settime64));
|
||||
allowSyscall(ctx, SCMP_SYS(clone));
|
||||
allowSyscall(ctx, SCMP_SYS(clone3));
|
||||
allowSyscall(ctx, SCMP_SYS(close));
|
||||
allowSyscall(ctx, SCMP_SYS(close_range));
|
||||
allowSyscall(ctx, SCMP_SYS(connect));
|
||||
allowSyscall(ctx, SCMP_SYS(copy_file_range));
|
||||
allowSyscall(ctx, SCMP_SYS(creat));
|
||||
allowSyscall(ctx, SCMP_SYS(create_module));
|
||||
allowSyscall(ctx, SCMP_SYS(delete_module));
|
||||
allowSyscall(ctx, SCMP_SYS(dup));
|
||||
allowSyscall(ctx, SCMP_SYS(dup2));
|
||||
allowSyscall(ctx, SCMP_SYS(dup3));
|
||||
allowSyscall(ctx, SCMP_SYS(epoll_create));
|
||||
allowSyscall(ctx, SCMP_SYS(epoll_create1));
|
||||
allowSyscall(ctx, SCMP_SYS(epoll_ctl));
|
||||
allowSyscall(ctx, SCMP_SYS(epoll_ctl_old));
|
||||
allowSyscall(ctx, SCMP_SYS(epoll_pwait));
|
||||
allowSyscall(ctx, SCMP_SYS(epoll_pwait2));
|
||||
allowSyscall(ctx, SCMP_SYS(epoll_wait));
|
||||
allowSyscall(ctx, SCMP_SYS(epoll_wait_old));
|
||||
allowSyscall(ctx, SCMP_SYS(eventfd));
|
||||
allowSyscall(ctx, SCMP_SYS(eventfd2));
|
||||
allowSyscall(ctx, SCMP_SYS(execve));
|
||||
allowSyscall(ctx, SCMP_SYS(execveat));
|
||||
allowSyscall(ctx, SCMP_SYS(exit));
|
||||
allowSyscall(ctx, SCMP_SYS(exit_group));
|
||||
allowSyscall(ctx, SCMP_SYS(faccessat));
|
||||
allowSyscall(ctx, SCMP_SYS(faccessat2));
|
||||
allowSyscall(ctx, SCMP_SYS(fadvise64));
|
||||
allowSyscall(ctx, SCMP_SYS(fadvise64_64));
|
||||
allowSyscall(ctx, SCMP_SYS(fallocate));
|
||||
allowSyscall(ctx, SCMP_SYS(fanotify_init));
|
||||
allowSyscall(ctx, SCMP_SYS(fanotify_mark));
|
||||
allowSyscall(ctx, SCMP_SYS(fchdir));
|
||||
// skip fchmod (dangerous)
|
||||
// skip fchmodat (dangerous)
|
||||
// skip fchmodat2 (requires glibc 2.39, dangerous)
|
||||
allowSyscall(ctx, SCMP_SYS(fchown));
|
||||
allowSyscall(ctx, SCMP_SYS(fchown32));
|
||||
allowSyscall(ctx, SCMP_SYS(fchownat));
|
||||
allowSyscall(ctx, SCMP_SYS(fcntl));
|
||||
allowSyscall(ctx, SCMP_SYS(fcntl64));
|
||||
allowSyscall(ctx, SCMP_SYS(fdatasync));
|
||||
allowSyscall(ctx, SCMP_SYS(fgetxattr));
|
||||
allowSyscall(ctx, SCMP_SYS(finit_module));
|
||||
allowSyscall(ctx, SCMP_SYS(flistxattr));
|
||||
allowSyscall(ctx, SCMP_SYS(flock));
|
||||
allowSyscall(ctx, SCMP_SYS(fork));
|
||||
allowSyscall(ctx, SCMP_SYS(fremovexattr));
|
||||
allowSyscall(ctx, SCMP_SYS(fsconfig));
|
||||
// skip fsetxattr (dangerous)
|
||||
allowSyscall(ctx, SCMP_SYS(fsmount));
|
||||
allowSyscall(ctx, SCMP_SYS(fsopen));
|
||||
allowSyscall(ctx, SCMP_SYS(fspick));
|
||||
allowSyscall(ctx, SCMP_SYS(fstat));
|
||||
allowSyscall(ctx, SCMP_SYS(fstat64));
|
||||
allowSyscall(ctx, SCMP_SYS(fstatat64));
|
||||
allowSyscall(ctx, SCMP_SYS(fstatfs));
|
||||
allowSyscall(ctx, SCMP_SYS(fstatfs64));
|
||||
allowSyscall(ctx, SCMP_SYS(fsync));
|
||||
allowSyscall(ctx, SCMP_SYS(ftime));
|
||||
allowSyscall(ctx, SCMP_SYS(ftruncate));
|
||||
allowSyscall(ctx, SCMP_SYS(ftruncate64));
|
||||
allowSyscall(ctx, SCMP_SYS(futex));
|
||||
// skip futex_requeue (requires glibc 2.39)
|
||||
allowSyscall(ctx, SCMP_SYS(futex_time64));
|
||||
// skip futex_wait (requires glibc 2.39)
|
||||
allowSyscall(ctx, SCMP_SYS(futex_waitv));
|
||||
// skip futex_wake (requires glibc 2.39)
|
||||
allowSyscall(ctx, SCMP_SYS(futimesat));
|
||||
allowSyscall(ctx, SCMP_SYS(getcpu));
|
||||
allowSyscall(ctx, SCMP_SYS(getcwd));
|
||||
allowSyscall(ctx, SCMP_SYS(getdents));
|
||||
allowSyscall(ctx, SCMP_SYS(getdents64));
|
||||
allowSyscall(ctx, SCMP_SYS(getegid));
|
||||
allowSyscall(ctx, SCMP_SYS(getegid32));
|
||||
allowSyscall(ctx, SCMP_SYS(geteuid));
|
||||
allowSyscall(ctx, SCMP_SYS(geteuid32));
|
||||
allowSyscall(ctx, SCMP_SYS(getgid));
|
||||
allowSyscall(ctx, SCMP_SYS(getgid32));
|
||||
allowSyscall(ctx, SCMP_SYS(getgroups));
|
||||
allowSyscall(ctx, SCMP_SYS(getgroups32));
|
||||
allowSyscall(ctx, SCMP_SYS(getitimer));
|
||||
allowSyscall(ctx, SCMP_SYS(get_kernel_syms));
|
||||
allowSyscall(ctx, SCMP_SYS(get_mempolicy));
|
||||
allowSyscall(ctx, SCMP_SYS(getpeername));
|
||||
allowSyscall(ctx, SCMP_SYS(getpgid));
|
||||
allowSyscall(ctx, SCMP_SYS(getpgrp));
|
||||
allowSyscall(ctx, SCMP_SYS(getpid));
|
||||
allowSyscall(ctx, SCMP_SYS(getpmsg));
|
||||
allowSyscall(ctx, SCMP_SYS(getppid));
|
||||
allowSyscall(ctx, SCMP_SYS(getpriority));
|
||||
allowSyscall(ctx, SCMP_SYS(getrandom));
|
||||
allowSyscall(ctx, SCMP_SYS(getresgid));
|
||||
allowSyscall(ctx, SCMP_SYS(getresgid32));
|
||||
allowSyscall(ctx, SCMP_SYS(getresuid));
|
||||
allowSyscall(ctx, SCMP_SYS(getresuid32));
|
||||
allowSyscall(ctx, SCMP_SYS(getrlimit));
|
||||
allowSyscall(ctx, SCMP_SYS(get_robust_list));
|
||||
allowSyscall(ctx, SCMP_SYS(getrusage));
|
||||
allowSyscall(ctx, SCMP_SYS(getsid));
|
||||
allowSyscall(ctx, SCMP_SYS(getsockname));
|
||||
allowSyscall(ctx, SCMP_SYS(getsockopt));
|
||||
allowSyscall(ctx, SCMP_SYS(get_thread_area));
|
||||
allowSyscall(ctx, SCMP_SYS(gettid));
|
||||
allowSyscall(ctx, SCMP_SYS(gettimeofday));
|
||||
allowSyscall(ctx, SCMP_SYS(get_tls));
|
||||
allowSyscall(ctx, SCMP_SYS(getuid));
|
||||
allowSyscall(ctx, SCMP_SYS(getuid32));
|
||||
allowSyscall(ctx, SCMP_SYS(getxattr));
|
||||
allowSyscall(ctx, SCMP_SYS(gtty));
|
||||
allowSyscall(ctx, SCMP_SYS(idle));
|
||||
allowSyscall(ctx, SCMP_SYS(init_module));
|
||||
allowSyscall(ctx, SCMP_SYS(inotify_add_watch));
|
||||
allowSyscall(ctx, SCMP_SYS(inotify_init));
|
||||
allowSyscall(ctx, SCMP_SYS(inotify_init1));
|
||||
allowSyscall(ctx, SCMP_SYS(inotify_rm_watch));
|
||||
allowSyscall(ctx, SCMP_SYS(io_cancel));
|
||||
allowSyscall(ctx, SCMP_SYS(ioctl));
|
||||
allowSyscall(ctx, SCMP_SYS(io_destroy));
|
||||
allowSyscall(ctx, SCMP_SYS(io_getevents));
|
||||
allowSyscall(ctx, SCMP_SYS(ioperm));
|
||||
allowSyscall(ctx, SCMP_SYS(io_pgetevents));
|
||||
allowSyscall(ctx, SCMP_SYS(io_pgetevents_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(iopl));
|
||||
allowSyscall(ctx, SCMP_SYS(ioprio_get));
|
||||
allowSyscall(ctx, SCMP_SYS(ioprio_set));
|
||||
allowSyscall(ctx, SCMP_SYS(io_setup));
|
||||
allowSyscall(ctx, SCMP_SYS(io_submit));
|
||||
allowSyscall(ctx, SCMP_SYS(io_uring_enter));
|
||||
allowSyscall(ctx, SCMP_SYS(io_uring_register));
|
||||
allowSyscall(ctx, SCMP_SYS(io_uring_setup));
|
||||
allowSyscall(ctx, SCMP_SYS(ipc));
|
||||
allowSyscall(ctx, SCMP_SYS(kcmp));
|
||||
allowSyscall(ctx, SCMP_SYS(kexec_file_load));
|
||||
allowSyscall(ctx, SCMP_SYS(kexec_load));
|
||||
allowSyscall(ctx, SCMP_SYS(keyctl));
|
||||
allowSyscall(ctx, SCMP_SYS(kill));
|
||||
allowSyscall(ctx, SCMP_SYS(landlock_add_rule));
|
||||
allowSyscall(ctx, SCMP_SYS(landlock_create_ruleset));
|
||||
allowSyscall(ctx, SCMP_SYS(landlock_restrict_self));
|
||||
allowSyscall(ctx, SCMP_SYS(lchown));
|
||||
allowSyscall(ctx, SCMP_SYS(lchown32));
|
||||
allowSyscall(ctx, SCMP_SYS(lgetxattr));
|
||||
allowSyscall(ctx, SCMP_SYS(link));
|
||||
allowSyscall(ctx, SCMP_SYS(linkat));
|
||||
allowSyscall(ctx, SCMP_SYS(listen));
|
||||
allowSyscall(ctx, SCMP_SYS(listxattr));
|
||||
allowSyscall(ctx, SCMP_SYS(llistxattr));
|
||||
allowSyscall(ctx, SCMP_SYS(_llseek));
|
||||
allowSyscall(ctx, SCMP_SYS(lock));
|
||||
allowSyscall(ctx, SCMP_SYS(lookup_dcookie));
|
||||
allowSyscall(ctx, SCMP_SYS(lremovexattr));
|
||||
allowSyscall(ctx, SCMP_SYS(lseek));
|
||||
// skip lsetxattr (dangerous)
|
||||
allowSyscall(ctx, SCMP_SYS(lstat));
|
||||
allowSyscall(ctx, SCMP_SYS(lstat64));
|
||||
allowSyscall(ctx, SCMP_SYS(madvise));
|
||||
// skip map_shadow_stack (requires glibc 2.39)
|
||||
allowSyscall(ctx, SCMP_SYS(mbind));
|
||||
allowSyscall(ctx, SCMP_SYS(membarrier));
|
||||
allowSyscall(ctx, SCMP_SYS(memfd_create));
|
||||
allowSyscall(ctx, SCMP_SYS(memfd_secret));
|
||||
allowSyscall(ctx, SCMP_SYS(migrate_pages));
|
||||
allowSyscall(ctx, SCMP_SYS(mincore));
|
||||
allowSyscall(ctx, SCMP_SYS(mkdir));
|
||||
allowSyscall(ctx, SCMP_SYS(mkdirat));
|
||||
allowSyscall(ctx, SCMP_SYS(mknod));
|
||||
allowSyscall(ctx, SCMP_SYS(mknodat));
|
||||
allowSyscall(ctx, SCMP_SYS(mlock));
|
||||
allowSyscall(ctx, SCMP_SYS(mlock2));
|
||||
allowSyscall(ctx, SCMP_SYS(mlockall));
|
||||
allowSyscall(ctx, SCMP_SYS(mmap));
|
||||
allowSyscall(ctx, SCMP_SYS(mmap2));
|
||||
allowSyscall(ctx, SCMP_SYS(modify_ldt));
|
||||
allowSyscall(ctx, SCMP_SYS(mount));
|
||||
allowSyscall(ctx, SCMP_SYS(mount_setattr));
|
||||
allowSyscall(ctx, SCMP_SYS(move_mount));
|
||||
allowSyscall(ctx, SCMP_SYS(move_pages));
|
||||
allowSyscall(ctx, SCMP_SYS(mprotect));
|
||||
allowSyscall(ctx, SCMP_SYS(mpx));
|
||||
allowSyscall(ctx, SCMP_SYS(mq_getsetattr));
|
||||
allowSyscall(ctx, SCMP_SYS(mq_notify));
|
||||
allowSyscall(ctx, SCMP_SYS(mq_open));
|
||||
allowSyscall(ctx, SCMP_SYS(mq_timedreceive));
|
||||
allowSyscall(ctx, SCMP_SYS(mq_timedreceive_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(mq_timedsend));
|
||||
allowSyscall(ctx, SCMP_SYS(mq_timedsend_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(mq_unlink));
|
||||
allowSyscall(ctx, SCMP_SYS(mremap));
|
||||
allowSyscall(ctx, SCMP_SYS(msgctl));
|
||||
allowSyscall(ctx, SCMP_SYS(msgget));
|
||||
allowSyscall(ctx, SCMP_SYS(msgrcv));
|
||||
allowSyscall(ctx, SCMP_SYS(msgsnd));
|
||||
allowSyscall(ctx, SCMP_SYS(msync));
|
||||
allowSyscall(ctx, SCMP_SYS(multiplexer));
|
||||
allowSyscall(ctx, SCMP_SYS(munlock));
|
||||
allowSyscall(ctx, SCMP_SYS(munlockall));
|
||||
allowSyscall(ctx, SCMP_SYS(munmap));
|
||||
allowSyscall(ctx, SCMP_SYS(name_to_handle_at));
|
||||
allowSyscall(ctx, SCMP_SYS(nanosleep));
|
||||
allowSyscall(ctx, SCMP_SYS(newfstatat));
|
||||
allowSyscall(ctx, SCMP_SYS(_newselect));
|
||||
allowSyscall(ctx, SCMP_SYS(nfsservctl));
|
||||
allowSyscall(ctx, SCMP_SYS(nice));
|
||||
allowSyscall(ctx, SCMP_SYS(oldfstat));
|
||||
allowSyscall(ctx, SCMP_SYS(oldlstat));
|
||||
allowSyscall(ctx, SCMP_SYS(oldolduname));
|
||||
allowSyscall(ctx, SCMP_SYS(oldstat));
|
||||
allowSyscall(ctx, SCMP_SYS(olduname));
|
||||
allowSyscall(ctx, SCMP_SYS(open));
|
||||
allowSyscall(ctx, SCMP_SYS(openat));
|
||||
allowSyscall(ctx, SCMP_SYS(openat2));
|
||||
allowSyscall(ctx, SCMP_SYS(open_by_handle_at));
|
||||
allowSyscall(ctx, SCMP_SYS(open_tree));
|
||||
allowSyscall(ctx, SCMP_SYS(pause));
|
||||
allowSyscall(ctx, SCMP_SYS(pciconfig_iobase));
|
||||
allowSyscall(ctx, SCMP_SYS(pciconfig_read));
|
||||
allowSyscall(ctx, SCMP_SYS(pciconfig_write));
|
||||
allowSyscall(ctx, SCMP_SYS(perf_event_open));
|
||||
allowSyscall(ctx, SCMP_SYS(personality));
|
||||
allowSyscall(ctx, SCMP_SYS(pidfd_getfd));
|
||||
allowSyscall(ctx, SCMP_SYS(pidfd_open));
|
||||
allowSyscall(ctx, SCMP_SYS(pidfd_send_signal));
|
||||
allowSyscall(ctx, SCMP_SYS(pipe));
|
||||
allowSyscall(ctx, SCMP_SYS(pipe2));
|
||||
allowSyscall(ctx, SCMP_SYS(pivot_root));
|
||||
allowSyscall(ctx, SCMP_SYS(pkey_alloc));
|
||||
allowSyscall(ctx, SCMP_SYS(pkey_free));
|
||||
allowSyscall(ctx, SCMP_SYS(pkey_mprotect));
|
||||
allowSyscall(ctx, SCMP_SYS(poll));
|
||||
allowSyscall(ctx, SCMP_SYS(ppoll));
|
||||
allowSyscall(ctx, SCMP_SYS(ppoll_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(prctl));
|
||||
allowSyscall(ctx, SCMP_SYS(pread64));
|
||||
allowSyscall(ctx, SCMP_SYS(preadv));
|
||||
allowSyscall(ctx, SCMP_SYS(preadv2));
|
||||
allowSyscall(ctx, SCMP_SYS(prlimit64));
|
||||
allowSyscall(ctx, SCMP_SYS(process_madvise));
|
||||
allowSyscall(ctx, SCMP_SYS(process_mrelease));
|
||||
allowSyscall(ctx, SCMP_SYS(process_vm_readv));
|
||||
allowSyscall(ctx, SCMP_SYS(process_vm_writev));
|
||||
allowSyscall(ctx, SCMP_SYS(prof));
|
||||
allowSyscall(ctx, SCMP_SYS(profil));
|
||||
allowSyscall(ctx, SCMP_SYS(pselect6));
|
||||
allowSyscall(ctx, SCMP_SYS(pselect6_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(ptrace));
|
||||
allowSyscall(ctx, SCMP_SYS(putpmsg));
|
||||
allowSyscall(ctx, SCMP_SYS(pwrite64));
|
||||
allowSyscall(ctx, SCMP_SYS(pwritev));
|
||||
allowSyscall(ctx, SCMP_SYS(pwritev2));
|
||||
allowSyscall(ctx, SCMP_SYS(query_module));
|
||||
allowSyscall(ctx, SCMP_SYS(quotactl));
|
||||
allowSyscall(ctx, SCMP_SYS(quotactl_fd));
|
||||
allowSyscall(ctx, SCMP_SYS(read));
|
||||
allowSyscall(ctx, SCMP_SYS(readahead));
|
||||
allowSyscall(ctx, SCMP_SYS(readdir));
|
||||
allowSyscall(ctx, SCMP_SYS(readlink));
|
||||
allowSyscall(ctx, SCMP_SYS(readlinkat));
|
||||
allowSyscall(ctx, SCMP_SYS(readv));
|
||||
allowSyscall(ctx, SCMP_SYS(reboot));
|
||||
allowSyscall(ctx, SCMP_SYS(recv));
|
||||
allowSyscall(ctx, SCMP_SYS(recvfrom));
|
||||
allowSyscall(ctx, SCMP_SYS(recvmmsg));
|
||||
allowSyscall(ctx, SCMP_SYS(recvmmsg_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(recvmsg));
|
||||
allowSyscall(ctx, SCMP_SYS(remap_file_pages));
|
||||
allowSyscall(ctx, SCMP_SYS(removexattr));
|
||||
allowSyscall(ctx, SCMP_SYS(rename));
|
||||
allowSyscall(ctx, SCMP_SYS(renameat));
|
||||
allowSyscall(ctx, SCMP_SYS(renameat2));
|
||||
allowSyscall(ctx, SCMP_SYS(request_key));
|
||||
allowSyscall(ctx, SCMP_SYS(restart_syscall));
|
||||
allowSyscall(ctx, SCMP_SYS(riscv_flush_icache));
|
||||
allowSyscall(ctx, SCMP_SYS(rmdir));
|
||||
allowSyscall(ctx, SCMP_SYS(rseq));
|
||||
allowSyscall(ctx, SCMP_SYS(rtas));
|
||||
allowSyscall(ctx, SCMP_SYS(rt_sigaction));
|
||||
allowSyscall(ctx, SCMP_SYS(rt_sigpending));
|
||||
allowSyscall(ctx, SCMP_SYS(rt_sigprocmask));
|
||||
allowSyscall(ctx, SCMP_SYS(rt_sigqueueinfo));
|
||||
allowSyscall(ctx, SCMP_SYS(rt_sigreturn));
|
||||
allowSyscall(ctx, SCMP_SYS(rt_sigsuspend));
|
||||
allowSyscall(ctx, SCMP_SYS(rt_sigtimedwait));
|
||||
allowSyscall(ctx, SCMP_SYS(rt_sigtimedwait_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(rt_tgsigqueueinfo));
|
||||
allowSyscall(ctx, SCMP_SYS(s390_guarded_storage));
|
||||
allowSyscall(ctx, SCMP_SYS(s390_pci_mmio_read));
|
||||
allowSyscall(ctx, SCMP_SYS(s390_pci_mmio_write));
|
||||
allowSyscall(ctx, SCMP_SYS(s390_runtime_instr));
|
||||
allowSyscall(ctx, SCMP_SYS(s390_sthyi));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_getaffinity));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_getattr));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_getparam));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_get_priority_max));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_get_priority_min));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_getscheduler));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_rr_get_interval));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_rr_get_interval_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_setaffinity));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_setattr));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_setparam));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_setscheduler));
|
||||
allowSyscall(ctx, SCMP_SYS(sched_yield));
|
||||
allowSyscall(ctx, SCMP_SYS(seccomp));
|
||||
allowSyscall(ctx, SCMP_SYS(security));
|
||||
allowSyscall(ctx, SCMP_SYS(select));
|
||||
allowSyscall(ctx, SCMP_SYS(semctl));
|
||||
allowSyscall(ctx, SCMP_SYS(semget));
|
||||
allowSyscall(ctx, SCMP_SYS(semop));
|
||||
allowSyscall(ctx, SCMP_SYS(semtimedop));
|
||||
allowSyscall(ctx, SCMP_SYS(semtimedop_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(send));
|
||||
allowSyscall(ctx, SCMP_SYS(sendfile));
|
||||
allowSyscall(ctx, SCMP_SYS(sendfile64));
|
||||
allowSyscall(ctx, SCMP_SYS(sendmmsg));
|
||||
allowSyscall(ctx, SCMP_SYS(sendmsg));
|
||||
allowSyscall(ctx, SCMP_SYS(sendto));
|
||||
allowSyscall(ctx, SCMP_SYS(setdomainname));
|
||||
allowSyscall(ctx, SCMP_SYS(setfsgid));
|
||||
allowSyscall(ctx, SCMP_SYS(setfsgid32));
|
||||
allowSyscall(ctx, SCMP_SYS(setfsuid));
|
||||
allowSyscall(ctx, SCMP_SYS(setfsuid32));
|
||||
allowSyscall(ctx, SCMP_SYS(setgid));
|
||||
allowSyscall(ctx, SCMP_SYS(setgid32));
|
||||
allowSyscall(ctx, SCMP_SYS(setgroups));
|
||||
allowSyscall(ctx, SCMP_SYS(setgroups32));
|
||||
allowSyscall(ctx, SCMP_SYS(sethostname));
|
||||
allowSyscall(ctx, SCMP_SYS(setitimer));
|
||||
allowSyscall(ctx, SCMP_SYS(set_mempolicy));
|
||||
allowSyscall(ctx, SCMP_SYS(set_mempolicy_home_node));
|
||||
allowSyscall(ctx, SCMP_SYS(setns));
|
||||
allowSyscall(ctx, SCMP_SYS(setpgid));
|
||||
allowSyscall(ctx, SCMP_SYS(setpriority));
|
||||
allowSyscall(ctx, SCMP_SYS(setregid));
|
||||
allowSyscall(ctx, SCMP_SYS(setregid32));
|
||||
allowSyscall(ctx, SCMP_SYS(setresgid));
|
||||
allowSyscall(ctx, SCMP_SYS(setresgid32));
|
||||
allowSyscall(ctx, SCMP_SYS(setresuid));
|
||||
allowSyscall(ctx, SCMP_SYS(setresuid32));
|
||||
allowSyscall(ctx, SCMP_SYS(setreuid));
|
||||
allowSyscall(ctx, SCMP_SYS(setreuid32));
|
||||
allowSyscall(ctx, SCMP_SYS(setrlimit));
|
||||
allowSyscall(ctx, SCMP_SYS(set_robust_list));
|
||||
allowSyscall(ctx, SCMP_SYS(setsid));
|
||||
allowSyscall(ctx, SCMP_SYS(setsockopt));
|
||||
allowSyscall(ctx, SCMP_SYS(set_thread_area));
|
||||
allowSyscall(ctx, SCMP_SYS(set_tid_address));
|
||||
allowSyscall(ctx, SCMP_SYS(settimeofday));
|
||||
allowSyscall(ctx, SCMP_SYS(set_tls));
|
||||
allowSyscall(ctx, SCMP_SYS(setuid));
|
||||
allowSyscall(ctx, SCMP_SYS(setuid32));
|
||||
// skip setxattr (dangerous)
|
||||
allowSyscall(ctx, SCMP_SYS(sgetmask));
|
||||
allowSyscall(ctx, SCMP_SYS(shmat));
|
||||
allowSyscall(ctx, SCMP_SYS(shmctl));
|
||||
allowSyscall(ctx, SCMP_SYS(shmdt));
|
||||
allowSyscall(ctx, SCMP_SYS(shmget));
|
||||
allowSyscall(ctx, SCMP_SYS(shutdown));
|
||||
allowSyscall(ctx, SCMP_SYS(sigaction));
|
||||
allowSyscall(ctx, SCMP_SYS(sigaltstack));
|
||||
allowSyscall(ctx, SCMP_SYS(signal));
|
||||
allowSyscall(ctx, SCMP_SYS(signalfd));
|
||||
allowSyscall(ctx, SCMP_SYS(signalfd4));
|
||||
allowSyscall(ctx, SCMP_SYS(sigpending));
|
||||
allowSyscall(ctx, SCMP_SYS(sigprocmask));
|
||||
allowSyscall(ctx, SCMP_SYS(sigreturn));
|
||||
allowSyscall(ctx, SCMP_SYS(sigsuspend));
|
||||
allowSyscall(ctx, SCMP_SYS(socket));
|
||||
allowSyscall(ctx, SCMP_SYS(socketcall));
|
||||
allowSyscall(ctx, SCMP_SYS(socketpair));
|
||||
allowSyscall(ctx, SCMP_SYS(splice));
|
||||
allowSyscall(ctx, SCMP_SYS(spu_create));
|
||||
allowSyscall(ctx, SCMP_SYS(spu_run));
|
||||
allowSyscall(ctx, SCMP_SYS(ssetmask));
|
||||
allowSyscall(ctx, SCMP_SYS(stat));
|
||||
allowSyscall(ctx, SCMP_SYS(stat64));
|
||||
allowSyscall(ctx, SCMP_SYS(statfs));
|
||||
allowSyscall(ctx, SCMP_SYS(statfs64));
|
||||
allowSyscall(ctx, SCMP_SYS(statx));
|
||||
allowSyscall(ctx, SCMP_SYS(stime));
|
||||
allowSyscall(ctx, SCMP_SYS(stty));
|
||||
allowSyscall(ctx, SCMP_SYS(subpage_prot));
|
||||
allowSyscall(ctx, SCMP_SYS(swapcontext));
|
||||
allowSyscall(ctx, SCMP_SYS(swapoff));
|
||||
allowSyscall(ctx, SCMP_SYS(swapon));
|
||||
allowSyscall(ctx, SCMP_SYS(switch_endian));
|
||||
allowSyscall(ctx, SCMP_SYS(symlink));
|
||||
allowSyscall(ctx, SCMP_SYS(symlinkat));
|
||||
allowSyscall(ctx, SCMP_SYS(sync));
|
||||
allowSyscall(ctx, SCMP_SYS(sync_file_range));
|
||||
allowSyscall(ctx, SCMP_SYS(sync_file_range2));
|
||||
allowSyscall(ctx, SCMP_SYS(syncfs));
|
||||
allowSyscall(ctx, SCMP_SYS(syscall));
|
||||
allowSyscall(ctx, SCMP_SYS(_sysctl));
|
||||
allowSyscall(ctx, SCMP_SYS(sys_debug_setcontext));
|
||||
allowSyscall(ctx, SCMP_SYS(sysfs));
|
||||
allowSyscall(ctx, SCMP_SYS(sysinfo));
|
||||
allowSyscall(ctx, SCMP_SYS(syslog));
|
||||
allowSyscall(ctx, SCMP_SYS(sysmips));
|
||||
allowSyscall(ctx, SCMP_SYS(tee));
|
||||
allowSyscall(ctx, SCMP_SYS(tgkill));
|
||||
allowSyscall(ctx, SCMP_SYS(time));
|
||||
allowSyscall(ctx, SCMP_SYS(timer_create));
|
||||
allowSyscall(ctx, SCMP_SYS(timer_delete));
|
||||
allowSyscall(ctx, SCMP_SYS(timerfd));
|
||||
allowSyscall(ctx, SCMP_SYS(timerfd_create));
|
||||
allowSyscall(ctx, SCMP_SYS(timerfd_gettime));
|
||||
allowSyscall(ctx, SCMP_SYS(timerfd_gettime64));
|
||||
allowSyscall(ctx, SCMP_SYS(timerfd_settime));
|
||||
allowSyscall(ctx, SCMP_SYS(timerfd_settime64));
|
||||
allowSyscall(ctx, SCMP_SYS(timer_getoverrun));
|
||||
allowSyscall(ctx, SCMP_SYS(timer_gettime));
|
||||
allowSyscall(ctx, SCMP_SYS(timer_gettime64));
|
||||
allowSyscall(ctx, SCMP_SYS(timer_settime));
|
||||
allowSyscall(ctx, SCMP_SYS(timer_settime64));
|
||||
allowSyscall(ctx, SCMP_SYS(times));
|
||||
allowSyscall(ctx, SCMP_SYS(tkill));
|
||||
allowSyscall(ctx, SCMP_SYS(truncate));
|
||||
allowSyscall(ctx, SCMP_SYS(truncate64));
|
||||
allowSyscall(ctx, SCMP_SYS(tuxcall));
|
||||
allowSyscall(ctx, SCMP_SYS(ugetrlimit));
|
||||
allowSyscall(ctx, SCMP_SYS(ulimit));
|
||||
allowSyscall(ctx, SCMP_SYS(umask));
|
||||
allowSyscall(ctx, SCMP_SYS(umount));
|
||||
allowSyscall(ctx, SCMP_SYS(umount2));
|
||||
allowSyscall(ctx, SCMP_SYS(uname));
|
||||
allowSyscall(ctx, SCMP_SYS(unlink));
|
||||
allowSyscall(ctx, SCMP_SYS(unlinkat));
|
||||
allowSyscall(ctx, SCMP_SYS(unshare));
|
||||
allowSyscall(ctx, SCMP_SYS(uselib));
|
||||
allowSyscall(ctx, SCMP_SYS(userfaultfd));
|
||||
allowSyscall(ctx, SCMP_SYS(usr26));
|
||||
allowSyscall(ctx, SCMP_SYS(usr32));
|
||||
allowSyscall(ctx, SCMP_SYS(ustat));
|
||||
allowSyscall(ctx, SCMP_SYS(utime));
|
||||
allowSyscall(ctx, SCMP_SYS(utimensat));
|
||||
allowSyscall(ctx, SCMP_SYS(utimensat_time64));
|
||||
allowSyscall(ctx, SCMP_SYS(utimes));
|
||||
allowSyscall(ctx, SCMP_SYS(vfork));
|
||||
allowSyscall(ctx, SCMP_SYS(vhangup));
|
||||
allowSyscall(ctx, SCMP_SYS(vm86));
|
||||
allowSyscall(ctx, SCMP_SYS(vm86old));
|
||||
allowSyscall(ctx, SCMP_SYS(vmsplice));
|
||||
allowSyscall(ctx, SCMP_SYS(vserver));
|
||||
allowSyscall(ctx, SCMP_SYS(wait4));
|
||||
allowSyscall(ctx, SCMP_SYS(waitid));
|
||||
allowSyscall(ctx, SCMP_SYS(waitpid));
|
||||
allowSyscall(ctx, SCMP_SYS(write));
|
||||
allowSyscall(ctx, SCMP_SYS(writev));
|
||||
// END extract-syscalls
|
||||
|
||||
// chmod family: prevent adding setuid/setgid bits to existing files.
|
||||
// The Nix store does not support setuid/setgid, and even their temporary creation can weaken the security of the sandbox.
|
||||
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod), 1, SCMP_A1(SCMP_CMP_MASKED_EQ, S_ISUID | S_ISGID, 0)) != 0 ||
|
||||
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(chmod), 1, SCMP_A1(SCMP_CMP_MASKED_EQ, S_ISUID, S_ISUID)) != 0 ||
|
||||
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(chmod), 1, SCMP_A1(SCMP_CMP_MASKED_EQ, S_ISGID, S_ISGID)) != 0 ||
|
||||
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmod), 1, SCMP_A1(SCMP_CMP_MASKED_EQ, S_ISUID | S_ISGID, 0)) != 0 ||
|
||||
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmod), 1, SCMP_A1(SCMP_CMP_MASKED_EQ, S_ISUID, S_ISUID)) != 0 ||
|
||||
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmod), 1, SCMP_A1(SCMP_CMP_MASKED_EQ, S_ISGID, S_ISGID)) != 0 ||
|
||||
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat), 1, SCMP_A2(SCMP_CMP_MASKED_EQ, S_ISUID | S_ISGID, 0)) != 0 ||
|
||||
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmodat), 1, SCMP_A2(SCMP_CMP_MASKED_EQ, S_ISUID, S_ISUID)) != 0 ||
|
||||
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmodat), 1, SCMP_A2(SCMP_CMP_MASKED_EQ, S_ISGID, S_ISGID)) != 0)
|
||||
throw SysError("unable to add seccomp rule");
|
||||
|
||||
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmod), 1,
|
||||
SCMP_A1(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
|
||||
throw SysError("unable to add seccomp rule");
|
||||
|
||||
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmodat), 1,
|
||||
SCMP_A2(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
|
||||
throw SysError("unable to add seccomp rule");
|
||||
|
||||
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), NIX_SYSCALL_FCHMODAT2, 1,
|
||||
SCMP_A2(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
|
||||
throw SysError("unable to add seccomp rule");
|
||||
}
|
||||
|
||||
/* Prevent builders from creating EAs or ACLs. Not all filesystems
|
||||
support these, and they're not allowed in the Nix store because
|
||||
they're not representable in the NAR serialisation. */
|
||||
// setxattr family: prevent creation of extended attributes or ACLs.
|
||||
// Not all filesystems support them, and they're incompatible with the NAR format.
|
||||
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(setxattr), 0) != 0 ||
|
||||
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(lsetxattr), 0) != 0 ||
|
||||
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(fsetxattr), 0) != 0)
|
||||
|
@ -1699,11 +2198,7 @@ void LocalDerivationGoal::runChild()
|
|||
|
||||
commonChildInit();
|
||||
|
||||
try {
|
||||
setupSeccomp();
|
||||
} catch (...) {
|
||||
if (buildUser) throw;
|
||||
}
|
||||
|
||||
bool setUser = true;
|
||||
|
||||
|
@ -2141,7 +2636,7 @@ void LocalDerivationGoal::runChild()
|
|||
/* Execute the program. This should not return. */
|
||||
if (drv->isBuiltin()) {
|
||||
try {
|
||||
logger = makeJSONLogger(*logger);
|
||||
logger = makeJSONLogger(std::move(logger));
|
||||
|
||||
BasicDerivation & drv2(*drv);
|
||||
for (auto & e : drv2.env)
|
||||
|
|
|
@ -991,11 +991,13 @@ void processConnection(
|
|||
if (clientVersion < MIN_SUPPORTED_WORKER_PROTO_VERSION)
|
||||
throw Error("the Nix client version is too old");
|
||||
|
||||
auto tunnelLogger = new TunnelLogger(to, clientVersion);
|
||||
auto prevLogger = nix::logger;
|
||||
std::unique_ptr<Logger> savedPrevLogger;
|
||||
auto prevLogger = nix::logger.get();
|
||||
auto ownedTunnelLogger = std::make_unique<TunnelLogger>(to, clientVersion);
|
||||
auto tunnelLogger = ownedTunnelLogger.get();
|
||||
// FIXME
|
||||
if (!recursive)
|
||||
logger = tunnelLogger;
|
||||
savedPrevLogger = std::exchange(logger, std::move(ownedTunnelLogger));
|
||||
|
||||
unsigned int opCount = 0;
|
||||
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Determine the syscall number for `fchmodat2`.
|
||||
*
|
||||
* On most platforms this is 452. Exceptions can be found on
|
||||
* a glibc git checkout via `rg --pcre2 'define __NR_fchmodat2 (?!452)'`.
|
||||
*
|
||||
* The problem is that glibc 2.39 and libseccomp 2.5.5 are needed to
|
||||
* get the syscall number. However, a Lix built against nixpkgs 23.11
|
||||
* (glibc 2.38) should still have the issue fixed without depending
|
||||
* on the build environment.
|
||||
*
|
||||
* To achieve that, the macros below try to determine the platform and
|
||||
* set the syscall number which is platform-specific, but
|
||||
* in most cases 452.
|
||||
*
|
||||
* TODO: remove this when 23.11 is EOL and the entire (supported) ecosystem
|
||||
* is on glibc 2.39.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#if defined(__alpha__)
|
||||
# define NIX_SYSCALL_FCHMODAT2 562
|
||||
#elif defined(__x86_64__) && SIZE_MAX == 0xFFFFFFFF // x32
|
||||
# define NIX_SYSCALL_FCHMODAT2 1073742276
|
||||
#elif defined(__mips__) && defined(__mips64) && defined(_ABIN64) // mips64/n64
|
||||
# define NIX_SYSCALL_FCHMODAT2 5452
|
||||
#elif defined(__mips__) && defined(__mips64) && defined(_ABIN32) // mips64/n32
|
||||
# define NIX_SYSCALL_FCHMODAT2 6452
|
||||
#elif defined(__mips__) && defined(_ABIO32) // mips32
|
||||
# define NIX_SYSCALL_FCHMODAT2 4452
|
||||
#else
|
||||
# define NIX_SYSCALL_FCHMODAT2 452
|
||||
#endif
|
|
@ -27,7 +27,7 @@ void setCurActivity(const ActivityId activityId)
|
|||
curActivity = activityId;
|
||||
}
|
||||
|
||||
Logger * logger = makeSimpleLogger(true);
|
||||
std::unique_ptr<Logger> logger = makeSimpleLogger(true);
|
||||
|
||||
void Logger::warn(const std::string & msg)
|
||||
{
|
||||
|
@ -129,9 +129,9 @@ void writeToStderr(std::string_view s)
|
|||
}
|
||||
}
|
||||
|
||||
Logger * makeSimpleLogger(bool printBuildLogs)
|
||||
std::unique_ptr<Logger> makeSimpleLogger(bool printBuildLogs)
|
||||
{
|
||||
return new SimpleLogger(printBuildLogs);
|
||||
return std::make_unique<SimpleLogger>(printBuildLogs);
|
||||
}
|
||||
|
||||
std::atomic<uint64_t> nextId{0};
|
||||
|
@ -159,9 +159,9 @@ void to_json(nlohmann::json & json, std::shared_ptr<Pos> pos)
|
|||
}
|
||||
|
||||
struct JSONLogger : Logger {
|
||||
Logger & prevLogger;
|
||||
std::unique_ptr<Logger> prevLogger;
|
||||
|
||||
JSONLogger(Logger & prevLogger) : prevLogger(prevLogger) { }
|
||||
JSONLogger(std::unique_ptr<Logger> prevLogger) : prevLogger(std::move(prevLogger)) { }
|
||||
|
||||
bool isVerbose() override {
|
||||
return true;
|
||||
|
@ -182,7 +182,7 @@ struct JSONLogger : Logger {
|
|||
|
||||
void write(const nlohmann::json & json)
|
||||
{
|
||||
prevLogger.log(lvlError, "@nix " + json.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace));
|
||||
prevLogger->log(lvlError, "@nix " + json.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace));
|
||||
}
|
||||
|
||||
void log(Verbosity lvl, std::string_view s) override
|
||||
|
@ -254,9 +254,9 @@ struct JSONLogger : Logger {
|
|||
}
|
||||
};
|
||||
|
||||
Logger * makeJSONLogger(Logger & prevLogger)
|
||||
std::unique_ptr<Logger> makeJSONLogger(std::unique_ptr<Logger> prevLogger)
|
||||
{
|
||||
return new JSONLogger(prevLogger);
|
||||
return std::make_unique<JSONLogger>(std::move(prevLogger));
|
||||
}
|
||||
|
||||
static Logger::Fields getFields(nlohmann::json & json)
|
||||
|
|
|
@ -14,23 +14,71 @@ typedef enum {
|
|||
actRealise = 102,
|
||||
actCopyPaths = 103,
|
||||
actBuilds = 104,
|
||||
|
||||
/** Fields:
|
||||
* 0: string: path to store derivation being built.
|
||||
* 1: string: representing the machine this is being built on. Empty string if local machine.
|
||||
* 2: int: curRound, not used anymore, always 1?
|
||||
* 3: int: nrRounds, not used anymore always 1?
|
||||
*/
|
||||
actBuild = 105,
|
||||
actOptimiseStore = 106,
|
||||
actVerifyPaths = 107,
|
||||
|
||||
/** Fields:
|
||||
* 0: string: store path
|
||||
* 1: string: substituter
|
||||
*/
|
||||
actSubstitute = 108,
|
||||
|
||||
/** Fields:
|
||||
* 0: string: store path
|
||||
* 1: string: substituter
|
||||
*/
|
||||
actQueryPathInfo = 109,
|
||||
|
||||
/** Fields:
|
||||
* 0: string: store path
|
||||
*/
|
||||
actPostBuildHook = 110,
|
||||
actBuildWaiting = 111,
|
||||
} ActivityType;
|
||||
|
||||
typedef enum {
|
||||
/** Fields:
|
||||
* 0: int: bytes linked
|
||||
*/
|
||||
resFileLinked = 100,
|
||||
|
||||
/** Fields:
|
||||
* 0: string: last line
|
||||
*/
|
||||
resBuildLogLine = 101,
|
||||
resUntrustedPath = 102,
|
||||
resCorruptedPath = 103,
|
||||
|
||||
/** Fields:
|
||||
* 0: string: phase name
|
||||
*/
|
||||
resSetPhase = 104,
|
||||
|
||||
/** Fields:
|
||||
* 0: int: done
|
||||
* 1: int: expected
|
||||
* 2: int: running
|
||||
* 3: int: failed
|
||||
*/
|
||||
resProgress = 105,
|
||||
|
||||
/** Fields:
|
||||
* 0: int: ActivityType
|
||||
* 1: int: expected
|
||||
*/
|
||||
resSetExpected = 106,
|
||||
|
||||
/** Fields:
|
||||
* 0: string: last line
|
||||
*/
|
||||
resPostBuildLogLine = 107,
|
||||
} ResultType;
|
||||
|
||||
|
@ -179,11 +227,11 @@ struct PushActivity
|
|||
~PushActivity() { setCurActivity(prevAct); }
|
||||
};
|
||||
|
||||
extern Logger * logger;
|
||||
extern std::unique_ptr<Logger> logger;
|
||||
|
||||
Logger * makeSimpleLogger(bool printBuildLogs = true);
|
||||
std::unique_ptr<Logger> makeSimpleLogger(bool printBuildLogs = true);
|
||||
|
||||
Logger * makeJSONLogger(Logger & prevLogger);
|
||||
std::unique_ptr<Logger> makeJSONLogger(std::unique_ptr<Logger> prevLogger);
|
||||
|
||||
/**
|
||||
* suppress msgs > this
|
||||
|
|
|
@ -230,10 +230,9 @@ Pid startProcess(std::function<void()> fun, const ProcessOptions & options)
|
|||
return Pid{pid};
|
||||
}
|
||||
|
||||
std::string runProgram(Path program, bool searchPath, const Strings & args,
|
||||
const std::optional<std::string> & input, bool isInteractive)
|
||||
std::string runProgram(Path program, bool searchPath, const Strings & args, bool isInteractive)
|
||||
{
|
||||
auto res = runProgram(RunOptions {.program = program, .searchPath = searchPath, .args = args, .input = input, .isInteractive = isInteractive});
|
||||
auto res = runProgram(RunOptions {.program = program, .searchPath = searchPath, .args = args, .isInteractive = isInteractive});
|
||||
|
||||
if (!statusOk(res.first))
|
||||
throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first));
|
||||
|
@ -262,20 +261,9 @@ void runProgram2(const RunOptions & options)
|
|||
{
|
||||
checkInterrupt();
|
||||
|
||||
assert(!(options.standardIn && options.input));
|
||||
|
||||
std::unique_ptr<Source> source_;
|
||||
Source * source = options.standardIn;
|
||||
|
||||
if (options.input) {
|
||||
source_ = std::make_unique<StringSource>(*options.input);
|
||||
source = source_.get();
|
||||
}
|
||||
|
||||
/* Create a pipe. */
|
||||
Pipe out, in;
|
||||
Pipe out;
|
||||
if (options.standardOut) out.create();
|
||||
if (source) in.create();
|
||||
|
||||
ProcessOptions processOptions;
|
||||
|
||||
|
@ -298,8 +286,6 @@ void runProgram2(const RunOptions & options)
|
|||
if (options.mergeStderrToStdout)
|
||||
if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
|
||||
throw SysError("cannot dup stdout into stderr");
|
||||
if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1)
|
||||
throw SysError("dupping stdin");
|
||||
|
||||
if (options.chdir && chdir((*options.chdir).c_str()) == -1)
|
||||
throw SysError("chdir failed");
|
||||
|
@ -328,47 +314,12 @@ void runProgram2(const RunOptions & options)
|
|||
|
||||
out.writeSide.close();
|
||||
|
||||
std::thread writerThread;
|
||||
|
||||
std::promise<void> promise;
|
||||
|
||||
Finally doJoin([&]() {
|
||||
if (writerThread.joinable())
|
||||
writerThread.join();
|
||||
});
|
||||
|
||||
|
||||
if (source) {
|
||||
in.readSide.close();
|
||||
writerThread = std::thread([&]() {
|
||||
try {
|
||||
std::vector<char> buf(8 * 1024);
|
||||
while (true) {
|
||||
size_t n;
|
||||
try {
|
||||
n = source->read(buf.data(), buf.size());
|
||||
} catch (EndOfFile &) {
|
||||
break;
|
||||
}
|
||||
writeFull(in.writeSide.get(), {buf.data(), n});
|
||||
}
|
||||
promise.set_value();
|
||||
} catch (...) {
|
||||
promise.set_exception(std::current_exception());
|
||||
}
|
||||
in.writeSide.close();
|
||||
});
|
||||
}
|
||||
|
||||
if (options.standardOut)
|
||||
drainFD(out.readSide.get(), *options.standardOut);
|
||||
|
||||
/* Wait for the child to finish. */
|
||||
int status = pid.wait();
|
||||
|
||||
/* Wait for the writer thread to finish. */
|
||||
if (source) promise.get_future().get();
|
||||
|
||||
if (status)
|
||||
throw ExecError(status, "program '%1%' %2%", options.program, statusToString(status));
|
||||
}
|
||||
|
|
|
@ -71,8 +71,7 @@ Pid startProcess(std::function<void()> fun, const ProcessOptions & options = Pro
|
|||
* shell backtick operator).
|
||||
*/
|
||||
std::string runProgram(Path program, bool searchPath = false,
|
||||
const Strings & args = Strings(),
|
||||
const std::optional<std::string> & input = {}, bool isInteractive = false);
|
||||
const Strings & args = Strings(), bool isInteractive = false);
|
||||
|
||||
struct RunOptions
|
||||
{
|
||||
|
@ -83,8 +82,6 @@ struct RunOptions
|
|||
std::optional<uid_t> gid;
|
||||
std::optional<Path> chdir;
|
||||
std::optional<std::map<std::string, std::string>> environment;
|
||||
std::optional<std::string> input;
|
||||
Source * standardIn = nullptr;
|
||||
Sink * standardOut = nullptr;
|
||||
bool mergeStderrToStdout = false;
|
||||
bool isInteractive = false;
|
||||
|
|
91
tests/functional/fetchers.sh
Normal file
91
tests/functional/fetchers.sh
Normal file
|
@ -0,0 +1,91 @@
|
|||
source common.sh
|
||||
|
||||
requireGit
|
||||
|
||||
clearStore
|
||||
|
||||
testFetchTreeError() {
|
||||
rawFetchTreeArg="${1?fetchTree arg missing}"
|
||||
messageSubstring="${2?messageSubstring missing}"
|
||||
|
||||
output="$(nix eval --impure --raw --expr "(builtins.fetchTree $rawFetchTreeArg).outPath" 2>&1)" && status=0 || status=$?
|
||||
grepQuiet "$messageSubstring" <<<"$output"
|
||||
test "$status" -ne 0
|
||||
}
|
||||
|
||||
# github/gitlab/sourcehut fetcher input validation
|
||||
for provider in github gitlab sourcehut; do
|
||||
# ref/rev validation
|
||||
testFetchTreeError \
|
||||
"{ type = \"$provider\"; owner = \"foo\"; repo = \"bar\"; ref = \",\"; }" \
|
||||
"URL '$provider:foo/bar' contains an invalid branch/tag name"
|
||||
|
||||
testFetchTreeError \
|
||||
"\"$provider://host/foo/bar/,\"" \
|
||||
"URL '$provider:foo/bar', ',' is not a commit hash or a branch/tag name"
|
||||
|
||||
testFetchTreeError \
|
||||
"\"$provider://host/foo/bar/f16d8f43dd0998cdb315a2cccf2e4d10027e7ca4?rev=abc\"" \
|
||||
"URL '$provider://host/foo/bar/f16d8f43dd0998cdb315a2cccf2e4d10027e7ca4?rev=abc' already contains a ref or rev"
|
||||
|
||||
testFetchTreeError \
|
||||
"\"$provider://host/foo/bar/ref?ref=ref2\"" \
|
||||
"URL '$provider://host/foo/bar/ref?ref=ref2' already contains a ref or rev"
|
||||
|
||||
# host validation
|
||||
testFetchTreeError \
|
||||
"{ type = \"$provider\"; owner = \"foo\"; repo = \"bar\"; host = \"git_hub.com\"; }" \
|
||||
"URL '$provider:foo/bar' contains an invalid instance host"
|
||||
|
||||
testFetchTreeError \
|
||||
"\"$provider://host/foo/bar/ref?host=git_hub.com\"" \
|
||||
"URL '$provider:foo/bar' contains an invalid instance host"
|
||||
|
||||
# invalid attributes
|
||||
testFetchTreeError \
|
||||
"{ type = \"$provider\"; owner = \"foo\"; repo = \"bar\"; wrong = true; }" \
|
||||
"unsupported input attribute 'wrong'"
|
||||
|
||||
testFetchTreeError \
|
||||
"\"$provider://host/foo/bar/ref?wrong=1\"" \
|
||||
"unsupported input attribute 'wrong'"
|
||||
done
|
||||
|
||||
# unsupported attributes w/ tarball fetcher
|
||||
testFetchTreeError \
|
||||
"\"https://host/foo?wrong=1\"" \
|
||||
"unsupported tarball input attribute 'wrong'. If you wanted to fetch a tarball with a query parameter, please use '{ type = \"tarball\"; url = \"...\"; }"
|
||||
|
||||
# test for unsupported attributes / validation in git fetcher
|
||||
testFetchTreeError \
|
||||
"\"git+https://github.com/owner/repo?invalid=1\"" \
|
||||
"unsupported Git input attribute 'invalid'"
|
||||
|
||||
testFetchTreeError \
|
||||
"\"git+https://github.com/owner/repo?url=foo\"" \
|
||||
"URL 'git+https://github.com/owner/repo?url=foo' must not override url via query param!"
|
||||
|
||||
testFetchTreeError \
|
||||
"\"git+https://github.com/owner/repo?ref=foo.lock\"" \
|
||||
"invalid Git branch/tag name 'foo.lock'"
|
||||
|
||||
testFetchTreeError \
|
||||
"{ type = \"git\"; url =\"https://github.com/owner/repo\"; ref = \"foo.lock\"; }" \
|
||||
"invalid Git branch/tag name 'foo.lock'"
|
||||
|
||||
# same for mercurial
|
||||
testFetchTreeError \
|
||||
"\"hg+https://forge.tld/owner/repo?invalid=1\"" \
|
||||
"unsupported Mercurial input attribute 'invalid'"
|
||||
|
||||
testFetchTreeError \
|
||||
"{ type = \"hg\"; url = \"https://forge.tld/owner/repo\"; invalid = 1; }" \
|
||||
"unsupported Mercurial input attribute 'invalid'"
|
||||
|
||||
testFetchTreeError \
|
||||
"\"hg+https://forge.tld/owner/repo?ref=,\"" \
|
||||
"invalid Mercurial branch/tag name ','"
|
||||
|
||||
testFetchTreeError \
|
||||
"{ type = \"hg\"; url = \"https://forge.tld/owner/repo\"; ref = \",\"; }" \
|
||||
"invalid Mercurial branch/tag name ','"
|
|
@ -278,6 +278,19 @@ git -C $flake3Dir commit -m 'Add nonFlakeInputs'
|
|||
# Check whether `nix build` works with a lockfile which is missing a
|
||||
# nonFlakeInputs.
|
||||
nix build -o $TEST_ROOT/result $flake3Dir#sth --commit-lock-file
|
||||
# check that the commit message is broadly correct. we can't check for
|
||||
# exact contents of the message becase the build dirs change too much.
|
||||
[[ "$(git -C $flake3Dir show -s --format=format:%B)" = \
|
||||
"flake.lock: Update
|
||||
|
||||
Flake lock file updates:
|
||||
|
||||
"?" Added input 'nonFlake':
|
||||
'git+file://"*"/flakes/flakes/nonFlake?ref=refs/heads/master&rev="*"' "*"
|
||||
"?" Added input 'nonFlakeFile':
|
||||
'path:"*"/flakes/flakes/nonFlake/README.md?lastModified="*"&narHash=sha256-cPh6hp48IOdRxVV3xGd0PDgSxgzj5N/2cK0rMPNaR4o%3D' "*"
|
||||
"?" Added input 'nonFlakeFile2':
|
||||
'path:"*"/flakes/flakes/nonFlake/README.md?lastModified="*"&narHash=sha256-cPh6hp48IOdRxVV3xGd0PDgSxgzj5N/2cK0rMPNaR4o%3D' "* ]]
|
||||
|
||||
nix build -o $TEST_ROOT/result flake3#fnord
|
||||
[[ $(cat $TEST_ROOT/result) = FNORD ]]
|
||||
|
|
|
@ -93,6 +93,7 @@ functional_tests_scripts = [
|
|||
'fetchGitRefs.sh',
|
||||
'gc-runtime.sh',
|
||||
'tarball.sh',
|
||||
'fetchers.sh',
|
||||
'fetchGit.sh',
|
||||
'fetchurl.sh',
|
||||
'fetchPath.sh',
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main(void) {
|
||||
char *name = getenv("out");
|
||||
FILE *fd = fopen(name, "w");
|
||||
fprintf(fd, "henlo :3");
|
||||
fclose(fd);
|
||||
|
||||
// FIXME use something nicer here that's less
|
||||
// platform-dependent as soon as we go to 24.05
|
||||
// and the glibc is new enough to support fchmodat2
|
||||
long rs = syscall(452, NULL, name, S_ISUID, 0);
|
||||
assert(rs == -1);
|
||||
assert(errno == EPERM);
|
||||
}
|
|
@ -4,17 +4,6 @@
|
|||
|
||||
let
|
||||
pkgs = config.nodes.machine.nixpkgs.pkgs;
|
||||
|
||||
fchmodat2-builder = pkgs.runCommandCC "fchmodat2-suid" {
|
||||
passAsFile = [ "code" ];
|
||||
code = builtins.readFile ./fchmodat2-suid.c;
|
||||
# Doesn't work with -O0, shuts up the warning about that.
|
||||
hardeningDisable = [ "fortify" ];
|
||||
} ''
|
||||
mkdir -p $out/bin/
|
||||
$CC -x c "$codePath" -O0 -g -o $out/bin/fchmodat2-suid
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
name = "setuid";
|
||||
|
@ -27,26 +16,13 @@ in
|
|||
virtualisation.additionalPaths = [
|
||||
pkgs.stdenvNoCC
|
||||
pkgs.pkgsi686Linux.stdenvNoCC
|
||||
fchmodat2-builder
|
||||
];
|
||||
# need at least 6.6 to test for fchmodat2
|
||||
boot.kernelPackages = pkgs.linuxKernel.packages.linux_6_6;
|
||||
|
||||
};
|
||||
|
||||
testScript = { nodes }: ''
|
||||
# fmt: off
|
||||
start_all()
|
||||
|
||||
with subtest("fchmodat2 suid regression test"):
|
||||
machine.succeed("""
|
||||
nix-build -E '(with import <nixpkgs> {}; runCommand "fchmodat2-suid" {
|
||||
BUILDER = builtins.storePath ${fchmodat2-builder};
|
||||
} "
|
||||
exec \\"$BUILDER\\"/bin/fchmodat2-suid
|
||||
")'
|
||||
""")
|
||||
|
||||
# Copying to /tmp should succeed.
|
||||
machine.succeed(r"""
|
||||
nix-build --no-sandbox -E '(with import <nixpkgs> {}; runCommand "foo" {} "
|
||||
|
|
|
@ -69,7 +69,7 @@ in
|
|||
|
||||
# Check that we got redirected to the immutable URL.
|
||||
locked_url = info["locked"]["url"]
|
||||
assert locked_url == "http://localhost/stable/${nixpkgs.rev}.tar.gz", f"{locked_url=} != http://localhost/stable/${nixpkgs.rev}.tar.gz"
|
||||
assert locked_url == "http://localhost/stable/${nixpkgs.rev}.tar.gz?rev=${nixpkgs.rev}&revCount=1234", f"{locked_url=} != http://localhost/stable/${nixpkgs.rev}.tar.gz"
|
||||
|
||||
# Check that we got the rev and revCount attributes.
|
||||
revision = info["revision"]
|
||||
|
|
|
@ -27,20 +27,17 @@ namespace nix {
|
|||
};
|
||||
|
||||
class CaptureLogging {
|
||||
Logger * oldLogger;
|
||||
std::unique_ptr<CaptureLogger> tempLogger;
|
||||
std::unique_ptr<Logger> oldLogger;
|
||||
public:
|
||||
CaptureLogging() : tempLogger(std::make_unique<CaptureLogger>()) {
|
||||
oldLogger = logger;
|
||||
logger = tempLogger.get();
|
||||
}
|
||||
CaptureLogging() : oldLogger(std::exchange(logger, std::make_unique<CaptureLogger>())) {}
|
||||
|
||||
~CaptureLogging() {
|
||||
logger = oldLogger;
|
||||
logger = std::move(oldLogger);
|
||||
}
|
||||
|
||||
std::string get() const {
|
||||
return tempLogger->get();
|
||||
auto captureLogger = dynamic_cast<CaptureLogger *>(logger.get());
|
||||
return captureLogger ? captureLogger->get() : "";
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace nix
|
|||
initGC();
|
||||
|
||||
startProgressBar();
|
||||
ASSERT_NE(dynamic_cast<ProgressBar *>(logger), nullptr);
|
||||
ASSERT_NE(dynamic_cast<ProgressBar *>(logger.get()), nullptr);
|
||||
ProgressBar & progressBar = dynamic_cast<ProgressBar &>(*logger);
|
||||
|
||||
Activity act(
|
||||
|
|
Loading…
Reference in a new issue