From be4890747051de0e489d608fdba65489c45d2b02 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Fri, 17 Feb 2023 19:23:09 +0100 Subject: [PATCH 1/4] ci: Always run with sandbox, even on Darwin And fix a test failure in the sandbox due to /home existing on Darwin but not being accessible in the sandbox since it's a symlink to /System/Volumes/Data/home, see https://github.com/NixOS/nix/actions/runs/4205378453/jobs/7297384658#step:6:2127: C++ exception with description "error: getting status of /home/schnitzel/darmstadt/pommes: Operation not permitted" thrown in the test body. On Linux this wasn't a problem because there /home doesn't exist in the sandbox --- .github/workflows/ci.yml | 3 +++ src/libutil/tests/tests.cc | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c06c77043..61e7f4560 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,9 @@ jobs: with: fetch-depth: 0 - uses: cachix/install-nix-action@v20 + with: + # The sandbox would otherwise be disabled by default on Darwin + extra_nix_config: "sandbox = true" - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - uses: cachix/cachix-action@v12 if: needs.check_secrets.outputs.cachix == 'true' diff --git a/src/libutil/tests/tests.cc b/src/libutil/tests/tests.cc index 250e83a38..f3c1e8248 100644 --- a/src/libutil/tests/tests.cc +++ b/src/libutil/tests/tests.cc @@ -202,7 +202,7 @@ namespace nix { } TEST(pathExists, bogusPathDoesNotExist) { - ASSERT_FALSE(pathExists("/home/schnitzel/darmstadt/pommes")); + ASSERT_FALSE(pathExists("/schnitzel/darmstadt/pommes")); } /* ---------------------------------------------------------------------------- From b7cde90c6b479562eb9f1d9df399d04cf9c42aad Mon Sep 17 00:00:00 2001 From: Yorick van Pelt Date: Thu, 11 May 2023 13:09:02 +0200 Subject: [PATCH 2/4] Call getDefaultSSLCertFile() only when none is specified This does pathExists on various paths, which crashes on EPERM in the macOS sandbox. --- src/libstore/globals.cc | 2 ++ src/libstore/globals.hh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 4c66d08ee..a196c10e6 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -57,6 +57,8 @@ Settings::Settings() auto sslOverride = getEnv("NIX_SSL_CERT_FILE").value_or(getEnv("SSL_CERT_FILE").value_or("")); if (sslOverride != "") caFile = sslOverride; + else if (caFile == "") + caFile = getDefaultSSLCertFile(); /* Backwards compatibility. */ auto s = getEnv("NIX_REMOTE_SYSTEMS"); diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 31dfe5b4e..34b4f24a7 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -842,7 +842,7 @@ public: )"}; Setting caFile{ - this, getDefaultSSLCertFile(), "ssl-cert-file", + this, "", "ssl-cert-file", R"( The path of a file containing CA certificates used to authenticate `https://` downloads. Nix by default will use From a6c78ba367725a81aa631a7df2d0840ddd25faf5 Mon Sep 17 00:00:00 2001 From: Yorick van Pelt Date: Thu, 11 May 2023 13:44:16 +0200 Subject: [PATCH 3/4] getDefaultNixPath: ignore EPERM --- src/libexpr/eval.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 585670e69..61012f2ab 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -2620,12 +2620,17 @@ Strings EvalSettings::getDefaultNixPath() { Strings res; auto add = [&](const Path & p, const std::string & s = std::string()) { - if (pathExists(p)) { - if (s.empty()) { - res.push_back(p); - } else { - res.push_back(s + "=" + p); + try { + if (pathExists(p)) { + if (s.empty()) { + res.push_back(p); + } else { + res.push_back(s + "=" + p); + } } + } catch (SysError & e) { + // swallow EPERM + if (e.errNo != EPERM) throw; } }; From 2c462486fe0c1bcb5b1142507d2875e98b2418df Mon Sep 17 00:00:00 2001 From: Yorick van Pelt Date: Fri, 26 May 2023 15:32:28 +0200 Subject: [PATCH 4/4] create pathAccessible, use it to infer default dirs --- src/libexpr/eval.cc | 15 +++++---------- src/libstore/globals.cc | 4 +--- src/libstore/globals.hh | 2 +- src/libutil/util.cc | 11 +++++++++++ src/libutil/util.hh | 8 ++++++++ 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 61012f2ab..71fd6e6e4 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -2620,17 +2620,12 @@ Strings EvalSettings::getDefaultNixPath() { Strings res; auto add = [&](const Path & p, const std::string & s = std::string()) { - try { - if (pathExists(p)) { - if (s.empty()) { - res.push_back(p); - } else { - res.push_back(s + "=" + p); - } + if (pathAccessible(p)) { + if (s.empty()) { + res.push_back(p); + } else { + res.push_back(s + "=" + p); } - } catch (SysError & e) { - // swallow EPERM - if (e.errNo != EPERM) throw; } }; diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index a196c10e6..32e9a6ea9 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -57,8 +57,6 @@ Settings::Settings() auto sslOverride = getEnv("NIX_SSL_CERT_FILE").value_or(getEnv("SSL_CERT_FILE").value_or("")); if (sslOverride != "") caFile = sslOverride; - else if (caFile == "") - caFile = getDefaultSSLCertFile(); /* Backwards compatibility. */ auto s = getEnv("NIX_REMOTE_SYSTEMS"); @@ -185,7 +183,7 @@ bool Settings::isWSL1() Path Settings::getDefaultSSLCertFile() { for (auto & fn : {"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"}) - if (pathExists(fn)) return fn; + if (pathAccessible(fn)) return fn; return ""; } diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 34b4f24a7..31dfe5b4e 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -842,7 +842,7 @@ public: )"}; Setting caFile{ - this, "", "ssl-cert-file", + this, getDefaultSSLCertFile(), "ssl-cert-file", R"( The path of a file containing CA certificates used to authenticate `https://` downloads. Nix by default will use diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 3a8309149..aa0a154fd 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -266,6 +266,17 @@ bool pathExists(const Path & path) return false; } +bool pathAccessible(const Path & path) +{ + try { + return pathExists(path); + } catch (SysError & e) { + // swallow EPERM + if (e.errNo == EPERM) return false; + throw; + } +} + Path readLink(const Path & path) { diff --git a/src/libutil/util.hh b/src/libutil/util.hh index a7907cd14..00fcb9b79 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -120,6 +120,14 @@ struct stat lstat(const Path & path); */ bool pathExists(const Path & path); +/** + * A version of pathExists that returns false on a permission error. + * Useful for inferring default paths across directories that might not + * be readable. + * @return true iff the given path can be accessed and exists + */ +bool pathAccessible(const Path & path); + /** * Read the contents (target) of a symbolic link. The result is not * in any way canonicalised.