aboutsummaryrefslogtreecommitdiff
path: root/src/nix
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix')
-rw-r--r--src/nix/add-to-store.cc14
-rw-r--r--src/nix/bundle.cc2
-rw-r--r--src/nix/daemon.cc63
-rw-r--r--src/nix/eval.cc2
-rw-r--r--src/nix/flake.cc2
-rw-r--r--src/nix/flake.md10
-rw-r--r--src/nix/prefetch.cc10
-rw-r--r--src/nix/profile.cc16
8 files changed, 86 insertions, 33 deletions
diff --git a/src/nix/add-to-store.cc b/src/nix/add-to-store.cc
index 5168413d2..16e48a39b 100644
--- a/src/nix/add-to-store.cc
+++ b/src/nix/add-to-store.cc
@@ -42,14 +42,18 @@ struct CmdAddToStore : MixDryRun, StoreCommand
}
ValidPathInfo info {
- store->makeFixedOutputPath(ingestionMethod, hash, *namePart),
+ *store,
+ std::move(*namePart),
+ FixedOutputInfo {
+ .hash = {
+ .method = std::move(ingestionMethod),
+ .hash = std::move(hash),
+ },
+ .references = {},
+ },
narHash,
};
info.narSize = sink.s.size();
- info.ca = std::optional { FixedOutputHash {
- .method = ingestionMethod,
- .hash = hash,
- } };
if (!dryRun) {
auto source = StringSource(sink.s);
diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc
index 57c355f0c..bcc00d490 100644
--- a/src/nix/bundle.cc
+++ b/src/nix/bundle.cc
@@ -98,7 +98,7 @@ struct CmdBundle : InstallableValueCommand
if (!attr1)
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
- PathSet context2;
+ NixStringContext context2;
auto drvPath = evalState->coerceToStorePath(attr1->pos, *attr1->value, context2, "");
auto attr2 = vRes->attrs->get(evalState->sOutPath);
diff --git a/src/nix/daemon.cc b/src/nix/daemon.cc
index 7ae7b4ea6..c1a91c63d 100644
--- a/src/nix/daemon.cc
+++ b/src/nix/daemon.cc
@@ -273,8 +273,12 @@ static std::pair<TrustedFlag, std::string> authPeer(const PeerInfo & peer)
/**
* Run a server. The loop opens a socket and accepts new connections from that
* socket.
+ *
+ * @param forceTrustClientOpt If present, force trusting or not trusted
+ * the client. Otherwise, decide based on the authentication settings
+ * and user credentials (from the unix domain socket).
*/
-static void daemonLoop()
+static void daemonLoop(std::optional<TrustedFlag> forceTrustClientOpt)
{
if (chdir("/") == -1)
throw SysError("cannot change current directory");
@@ -317,9 +321,18 @@ static void daemonLoop()
closeOnExec(remote.get());
- PeerInfo peer = getPeerInfo(remote.get());
- auto [_trusted, user] = authPeer(peer);
- auto trusted = _trusted;
+ PeerInfo peer { .pidKnown = false };
+ TrustedFlag trusted;
+ std::string user;
+
+ if (forceTrustClientOpt)
+ trusted = *forceTrustClientOpt;
+ else {
+ peer = getPeerInfo(remote.get());
+ auto [_trusted, _user] = authPeer(peer);
+ trusted = _trusted;
+ user = _user;
+ };
printInfo((std::string) "accepted connection from pid %1%, user %2%" + (trusted ? " (trusted)" : ""),
peer.pidKnown ? std::to_string(peer.pid) : "<unknown>",
@@ -410,38 +423,47 @@ static void forwardStdioConnection(RemoteStore & store) {
* Unlike `forwardStdioConnection()` we do process commands ourselves in
* this case, not delegating to another daemon.
*
- * @note `Trusted` is unconditionally passed because in this mode we
- * blindly trust the standard streams. Limiting access to those is
- * explicitly not `nix-daemon`'s responsibility.
+ * @param trustClient Whether to trust the client. Forwarded directly to
+ * `processConnection()`.
*/
-static void processStdioConnection(ref<Store> store)
+static void processStdioConnection(ref<Store> store, TrustedFlag trustClient)
{
FdSource from(STDIN_FILENO);
FdSink to(STDOUT_FILENO);
- processConnection(store, from, to, Trusted, NotRecursive);
+ processConnection(store, from, to, trustClient, NotRecursive);
}
/**
* Entry point shared between the new CLI `nix daemon` and old CLI
* `nix-daemon`.
+ *
+ * @param forceTrustClientOpt See `daemonLoop()` and the parameter with
+ * the same name over there for details.
*/
-static void runDaemon(bool stdio)
+static void runDaemon(bool stdio, std::optional<TrustedFlag> forceTrustClientOpt)
{
if (stdio) {
auto store = openUncachedStore();
- if (auto remoteStore = store.dynamic_pointer_cast<RemoteStore>())
+ // If --force-untrusted is passed, we cannot forward the connection and
+ // must process it ourselves (before delegating to the next store) to
+ // force untrusting the client.
+ if (auto remoteStore = store.dynamic_pointer_cast<RemoteStore>(); remoteStore && (!forceTrustClientOpt || *forceTrustClientOpt != NotTrusted))
forwardStdioConnection(*remoteStore);
else
- processStdioConnection(store);
+ // `Trusted` is passed in the auto (no override case) because we
+ // cannot see who is on the other side of a plain pipe. Limiting
+ // access to those is explicitly not `nix-daemon`'s responsibility.
+ processStdioConnection(store, forceTrustClientOpt.value_or(Trusted));
} else
- daemonLoop();
+ daemonLoop(forceTrustClientOpt);
}
static int main_nix_daemon(int argc, char * * argv)
{
{
auto stdio = false;
+ std::optional<TrustedFlag> isTrustedOpt = std::nullopt;
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
if (*arg == "--daemon")
@@ -452,11 +474,20 @@ static int main_nix_daemon(int argc, char * * argv)
printVersion("nix-daemon");
else if (*arg == "--stdio")
stdio = true;
- else return false;
+ else if (*arg == "--force-trusted") {
+ experimentalFeatureSettings.require(Xp::DaemonTrustOverride);
+ isTrustedOpt = Trusted;
+ } else if (*arg == "--force-untrusted") {
+ experimentalFeatureSettings.require(Xp::DaemonTrustOverride);
+ isTrustedOpt = NotTrusted;
+ } else if (*arg == "--default-trust") {
+ experimentalFeatureSettings.require(Xp::DaemonTrustOverride);
+ isTrustedOpt = std::nullopt;
+ } else return false;
return true;
});
- runDaemon(stdio);
+ runDaemon(stdio, isTrustedOpt);
return 0;
}
@@ -482,7 +513,7 @@ struct CmdDaemon : StoreCommand
void run(ref<Store> store) override
{
- runDaemon(false);
+ runDaemon(false, std::nullopt);
}
};
diff --git a/src/nix/eval.cc b/src/nix/eval.cc
index c7af9c92c..d880bef0a 100644
--- a/src/nix/eval.cc
+++ b/src/nix/eval.cc
@@ -62,7 +62,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption
auto state = getEvalState();
auto [v, pos] = installable->toValue(*state);
- PathSet context;
+ NixStringContext context;
if (apply) {
auto vApply = state->allocValue();
diff --git a/src/nix/flake.cc b/src/nix/flake.cc
index a6c6b947f..3db655aeb 100644
--- a/src/nix/flake.cc
+++ b/src/nix/flake.cc
@@ -438,7 +438,7 @@ struct CmdFlakeCheck : FlakeCommand
if (auto attr = v.attrs->get(state->symbols.create("path"))) {
if (attr->name == state->symbols.create("path")) {
- PathSet context;
+ NixStringContext context;
auto path = state->coerceToPath(attr->pos, *attr->value, context, "");
if (!path.pathExists())
throw Error("template '%s' refers to a non-existent path '%s'", attrPath, path);
diff --git a/src/nix/flake.md b/src/nix/flake.md
index d70f34eeb..456fd0ea1 100644
--- a/src/nix/flake.md
+++ b/src/nix/flake.md
@@ -381,10 +381,12 @@ The following attributes are supported in `flake.nix`:
* `nixConfig`: a set of `nix.conf` options to be set when evaluating any
part of a flake. In the interests of security, only a small set of
- whitelisted options (currently `bash-prompt`, `bash-prompt-prefix`,
- `bash-prompt-suffix`, and `flake-registry`) are allowed to be set without
- confirmation so long as `accept-flake-config` is not set in the global
- configuration.
+ set of options is allowed to be set without confirmation so long as [`accept-flake-config`](@docroot@/command-ref/conf-file.md#conf-accept-flake-config) is not enabled in the global configuration:
+ - [`bash-prompt`](@docroot@/command-ref/conf-file.md#conf-bash-prompt)
+ - [`bash-prompt-prefix`](@docroot@/command-ref/conf-file.md#conf-bash-prompt-prefix)
+ - [`bash-prompt-suffix`](@docroot@/command-ref/conf-file.md#conf-bash-prompt-suffix)
+ - [`flake-registry`](@docroot@/command-ref/conf-file.md#conf-flake-registry)
+ - [`commit-lockfile-summary`](@docroot@/command-ref/conf-file.md#conf-commit-lockfile-summary)
## Flake inputs
diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc
index 039608d48..3b2e225f6 100644
--- a/src/nix/prefetch.cc
+++ b/src/nix/prefetch.cc
@@ -70,7 +70,13 @@ std::tuple<StorePath, Hash> prefetchFile(
the store. */
if (expectedHash) {
hashType = expectedHash->type;
- storePath = store->makeFixedOutputPath(ingestionMethod, *expectedHash, *name);
+ storePath = store->makeFixedOutputPath(*name, FixedOutputInfo {
+ .hash = {
+ .method = ingestionMethod,
+ .hash = *expectedHash,
+ },
+ .references = {},
+ });
if (store->isValidPath(*storePath))
hash = expectedHash;
else
@@ -121,7 +127,7 @@ std::tuple<StorePath, Hash> prefetchFile(
auto info = store->addToStoreSlow(*name, tmpFile, ingestionMethod, hashType, expectedHash);
storePath = info.path;
assert(info.ca);
- hash = getContentAddressHash(*info.ca);
+ hash = info.ca->getHash();
}
return {storePath.value(), hash.value()};
diff --git a/src/nix/profile.cc b/src/nix/profile.cc
index 88d4a3ce5..fd63b3519 100644
--- a/src/nix/profile.cc
+++ b/src/nix/profile.cc
@@ -200,12 +200,22 @@ struct ProfileManifest
auto narHash = hashString(htSHA256, sink.s);
ValidPathInfo info {
- store->makeFixedOutputPath(FileIngestionMethod::Recursive, narHash, "profile", references),
+ *store,
+ "profile",
+ FixedOutputInfo {
+ .hash = {
+ .method = FileIngestionMethod::Recursive,
+ .hash = narHash,
+ },
+ .references = {
+ .others = std::move(references),
+ // profiles never refer to themselves
+ .self = false,
+ },
+ },
narHash,
};
- info.references = std::move(references);
info.narSize = sink.s.size();
- info.ca = FixedOutputHash { .method = FileIngestionMethod::Recursive, .hash = info.narHash };
StringSource source(sink.s);
store->addToStore(info, source);