Commit graph

260 commits

Author SHA1 Message Date
Reepca Russelstein
78da695178
daemon: Explicitly unlock output path in the has-become-valid case.
Fixes <https://issues.guix.gnu.org/31785>.

Similar to <https://github.com/NixOS/nix/issues/178>, fixed in
<29cde917fe>.

We can't rely on Goal deletion to release our locks in a timely manner.  In
the case in which multiple guix-daemon processes simultaneously try producing
an output path path1, the one that gets there first (P1) will get the lock,
and the second one (P2) will continue trying to acquire the lock until it is
released.  Once it has acquired the lock, it checks to see whether the path
has already become valid in the meantime, and if so it reports success to
those Goals waiting on its completion and finishes.  Unfortunately, it fails
to release the locks it holds first, so those stay held until that Goal gets
deleted.

Suppose we have the following store path dependency graph:

          path4
      /     |     \
   path1   path2   path3

P2 is now sitting on path1's lock, and will continue to do so until path4 is
completed.  Suppose there is also a P3, and it has been blocked while P1
builds path2.  Now P3 is sitting on path2's lock, and can't acquire path1's
lock to determine that it has been completed.  Likewise P2 is sitting on
path1's lock, and now can't acquire path2's lock to determine that it has been
completed.  Finally, P3 completes path3 while P2 is blocked.

Now:

- P1 knows that path1 and path2 are complete, and holds no locks, but can't
  determine that path3 is complete
- P2 knows that path1 and path3 are complete, and holds locks on path1 and
  path3, but can't determine that path2 is complete
- P3 knows that path2 and path3 are complete, and holds a lock on path2, but
  can't determine that path1 is complete

And none of these locks will be released until path4 is complete.  Thus, we
have a deadlock.

To resolve this, we should explicitly release these locks as soon as they
should be released.

* nix/libstore/build.cc
  (DerivationGoal::tryToBuild, SubstitutionGoal::tryToRun):
  Explicitly release locks in the has-become-valid case.
* tests/store-deadlock.scm: New file.
* Makefile.am (SCM_TESTS): Add it.

Change-Id: Ie510f84828892315fe6776c830db33d0f70bcef8
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2024-12-30 00:51:57 +01:00
Doğan Çeçen
dcaccc8b72
daemon: Fix linking gcrypt when --as-needed linker arg is used
This is a followup to 8a7bd211d2.

As it is mentioned in autoconf manual that library names should be
specified in LIBS, not LDFLAGS. See:

https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.72/html_node/Preset-Output-Variables.html#index-LDFLAGS-2

This change also brings back the save_* vars trick that was there
before. I missed in my earlier change that nix/local.mk was referring
LIBGCRYPT_* vars directly.

And, instead of CXXFLAGS, CPPFLAGS is used since the latter is probably
more correct as this is used for include dirs, therefore using
preprocessor flags.

Tested with ./configure LDFLAGS="-Wl,--as-needed" --with-libgcrypt-prefix=... combinations.

* config-daemon.ac: Set ‘LIBGCRYPT_CPPFLAGS’ instead of
‘LIBGCRYPT_CXXFLAGS’.  Set ‘LIBGCRYPT_LIBS’ in addition to
‘LIBGCRYPT_LDFLAGS’.  Save and restore ‘CPPFLAGS’, ‘LDFLAGS’, and ‘LIBS’
around test.
* nix/local.mk (libutil_a_CPPFLAGS): Add $(LIBGCRYPT_CPPFLAGS).
(libstore_a_CXXFLAGS): Remove $(LIBGCRYPT_CFLAGS).
(guix_daemon_LDFLAGS): New variable.

Change-Id: Iadb10e1994c9a78e2927847af2cfe5e096fbb2a8
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2024-12-09 23:15:45 +01:00
Brennan Vincent
cf10268a77
daemon: Improve error message in ‘checkStoreName’.
* nix/libstore/store-api.cc (checkStoreName): Clarify message when NAME
starts with a dot.

Change-Id: I045a663bc6cd9844677c65b38a31d3941cf212b5
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2024-11-17 23:15:49 +01:00
Reepca Russelstein
5ab3c4c1e4
daemon: Sanitize successful build outputs prior to exposing them.
There is currently a window of time between when the build outputs are exposed
and when their metadata is canonicalized.

* nix/libstore/build.cc (DerivationGoal::registerOutputs): wait until after
  metadata canonicalization to move successful build outputs to the store.

Change-Id: Ia995136f3f965eaf7b0e1d92af964b816f3fb276
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2024-10-21 00:09:24 +02:00
Reepca Russelstein
558224140d
daemon: Sanitize failed build outputs prior to exposing them.
The only thing keeping a rogue builder and a local user from collaborating to
usurp control over the builder's user during the build is the fact that
whatever files the builder may produce are not accessible to any other users
yet.  If we're going to make them accessible, we should probably do some
sanity checking to ensure that sort of collaborating can't happen.

Currently this isn't happening when failed build outputs are moved from the
chroot as an aid to debugging.

* nix/libstore/build.cc (secureFilePerms): new function.
  (DerivationGoal::buildDone): use it.

Change-Id: I9dce1e3d8813b31cabd87a0e3219bf9830d8be96
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2024-10-21 00:09:10 +02:00
Ludovic Courtès
d11b96eb54
etc: Add explicit ‘--substitute-urls’ in guix-daemon service files.
Having substitute URLs explicitly listed in the service startup file
makes it clearer what should be modified to permanently change the list
of substitute URLs.

* config-daemon.ac: Rename ‘guix_substitute_urls’ to
‘GUIX_SUBSTITUTE_URLS’ and substitute it.
* nix/local.mk (etc/guix-%.service, etc/init.d/guix-daemon)
(etc/guix-%.conf): Substitute it.
* etc/guix-daemon.conf.in, etc/guix-daemon.service.in,
etc/init.d/guix-daemon.in: Add an explicit ‘--substitute-urls’ option.

Change-Id: Ie491b7fab5c42e54dca582801c03805a85de2bf9
2024-06-26 22:59:55 +02:00
Ludovic Courtès
7757fdd491
daemon: Loop over ‘copy_file_range’ upon short writes.
Fixes <https://issues.guix.gnu.org/70877>.

* nix/libutil/util.cc (copyFile): Loop over ‘copy_file_range’ instead of
throwing upon short write.

Reported-by: Ricardo Wurmus <rekado@elephly.net>
Change-Id: Id7b8a65ea59006c2d91bc23732309a68665b9ca0
2024-05-13 16:31:34 +02:00
Ludovic Courtès
ff1251de0b
daemon: Address shortcoming in previous security fix for CVE-2024-27297.
This is a followup to 8f4ffb3fae.

Commit 8f4ffb3fae fell short in two
ways: (1) it didn’t have any effet for fixed-output derivations
performed in a chroot, which is the case for all of them except those
using “builtin:download” and “builtin:git-download”, and (2) it did not
preserve ownership when copying, leading to “suspicious ownership or
permission […] rejecting this build output” errors.

* nix/libstore/build.cc (DerivationGoal::buildDone): Account for
‘chrootRootDir’ when copying ‘drv.outputs’.
* nix/libutil/util.cc (copyFileRecursively): Add ‘fchown’ and ‘fchownat’
calls to preserve file ownership; this is necessary for chrooted
fixed-output derivation builds.
* nix/libutil/util.hh: Update comment.

Change-Id: Ib59f040e98fed59d1af81d724b874b592cbef156
2024-03-12 14:07:28 +01:00
Ludovic Courtès
8f4ffb3fae
daemon: Protect against FD escape when building fixed-output derivations (CVE-2024-27297).
This fixes a security issue (CVE-2024-27297) whereby a fixed-output
derivation build process could open a writable file descriptor to its
output, send it to some outside process for instance over an abstract
AF_UNIX socket, which would then allow said process to modify the file
in the store after it has been marked as “valid”.

Vulnerability discovered by puck <https://github.com/puckipedia>.

Nix security advisory:
https://github.com/NixOS/nix/security/advisories/GHSA-2ffj-w4mj-pg37

Nix fix:
244f3eee0b

* nix/libutil/util.cc (readDirectory): Add variants that take a DIR* and
a file descriptor.  Rewrite the ‘Path’ variant accordingly.
(copyFile, copyFileRecursively): New functions.
* nix/libutil/util.hh (copyFileRecursively): New declaration.
* nix/libstore/build.cc (DerivationGoal::buildDone): When ‘fixedOutput’
is true, call ‘copyFileRecursively’ followed by ‘rename’ on each output.

Change-Id: I7952d41093eed26e123e38c14a4c1424be1ce1c4

Reported-by: Picnoir <picnoir@alternativebit.fr>, Théophane Hufschmitt <theophane.hufschmitt@tweag.io>
Change-Id: Idb5f2757f35af86b032a9851cecb19b70227bd88
2024-03-11 22:12:34 +01:00
Ludovic Courtès
d5724111ea
daemon: Change default ‘timeout’ and ‘max-silent-time’ values.
Having a timeout seems generally preferable as it makes sure build slots
are not kept busy for no good reason (few package builds, if any, are
expected to exceed these values).

* nix/libstore/globals.cc (Settings::Settings): Change ‘maxSilentTime’
and ‘buildTimeout’.
* gnu/services/base.scm (<guix-configuration>)[max-silent-time]
[timeout]: Change default values.
* doc/guix.texi (Invoking guix-daemon, Base Services): Adjust
accordingly.

Change-Id: I25c50893f3f7fcca451b8f093d9d4d1a15fa58d8
2024-01-05 17:27:21 +01:00
Tobias Geerinckx-Rice
892ec53b7e
daemon: Fix my own whitespace errors.
This follows up on commit d993ed43b2 and
was entirely predictable.  The noise, sorry for it.

Change-Id: I8ddb8cfe33db3864949f6589cc091616a90ebc5b
2023-12-17 01:00:00 +01:00
Tobias Geerinckx-Rice
d993ed43b2
daemon: Sacrifice builders on OOM.
* nix/libstore/build.cc (DerivationGoal::runChild):
Maximise our OOM score adjustment.

Change-Id: I418c763b499ca16e1ffe3c6033319112b9744f51
2023-12-10 01:00:00 +01:00
Ludovic Courtès
1e47148f46
daemon: Implement ‘substitute-urls’ RPC.
* nix/libstore/worker-protocol.hh (PROTOCOL_VERSION): Bump.
(WorkerOp): Add ‘wopSubstituteURLs’.
* nix/nix-daemon/nix-daemon.cc (performOp): Implement it.
* guix/store.scm (%protocol-version): Bump.
(operation-id): Add ‘substitute-urls’.
(substitute-urls): New procedure.
* tests/store.scm ("substitute-urls, default")
("substitute-urls, client-specified URLs")
("substitute-urls, disabled"): New tests.

Change-Id: I2c0119500c3a1eecfa5ebf32463ffb0f173161de
2023-12-11 23:18:53 +01:00
Ludovic Courtès
d83d4488da
daemon: Simplify “empty status” substitute error message.
* nix/libstore/build.cc (SubstitutionGoal::finished): Don’t show what
the empty status looks like.

Change-Id: Ie898432aeb047aff3d59024de6ed6d18f68903c4
2023-12-04 22:26:36 +01:00
Tobias Geerinckx-Rice
0500af5556
Revert "build: Add missing guix-gc.timer file to binary tarball."
This reverts commit 69f6edc1a8.

The intention is good, but nodist_systemdservice_DATA are meant to be
disposable artefacts generated from corresponding ‘.in’ files.

etc/guix-gc.timer doesn't fit that description, breaking builds:

  $ make clean && make
  …
  make[2]: *** No rule to make target 'etc/guix-gc.timer', needed by 'all-am'.  Stop.
2023-09-24 02:00:00 +02:00
Ludovic Courtès
95f2123135
daemon: Add “git-download” built-in builder.
The new builder makes it possible to break cycles that occurs when the
fixed-output derivation for the source of a dependency of ‘git’ would
itself depend on ‘git’.

* guix/scripts/perform-download.scm (perform-git-download): New
procedure.
(perform-download): Move fixed-output derivation check to…
(guix-perform-download): … here.  Invoke ‘perform-download’ or
‘perform-git-download’ depending on what ‘derivation-builder’ returns.
* nix/libstore/builtins.cc (builtins): Add “git-download”.
* tests/derivations.scm ("built-in-builders"): Update.
("'git-download' built-in builder")
("'git-download' built-in builder, invalid hash")
("'git-download' built-in builder, invalid commit")
("'git-download' built-in builder, not found"): New tests.
2023-09-26 17:36:58 +02:00
Sören Tempel
cd46993275
daemon: Fix build with GCC 13.
The sqlite.hh file uses fixed-width integer types from stdint.h. As
such, it needs to include <cstdint>. Without this include, the file
doesn't compile successfully with GCC13.

See: https://gcc.gnu.org/gcc-13/porting_to.html#header-dep-changes

* nix/libstore/sqlite.hh: include <cstdint>

Signed-off-by: Sören Tempel <soeren@soeren-tempel.net>
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2023-09-09 18:47:35 +02:00
Maxim Cournoyer
69f6edc1a8
build: Add missing guix-gc.timer file to binary tarball.
Partially fixes <https://issues.guix.gnu.org/65117>.

* nix/local.mk (nodist_systemdservice_DATA): Add etc/guix-gc.timer.
2023-08-31 23:31:49 -04:00
Ludovic Courtès
407175a1d0
daemon: Improve error message for wrong hash sizes.
* nix/libutil/hash.cc (parseHash): Show the hash algorithm name and
expected size in the error message.
* tests/derivations.scm ("fixed-output derivation, invalid hash size"):
New test.
2023-01-09 17:40:54 +01:00
Ludovic Courtès
2d4d26769d
daemon: Make "opening file" error messages distinguishable.
* nix/libstore/build.cc (DerivationGoal::openLogFile): Customize
"opening file" error message.
* nix/libutil/hash.cc (hashFile): Likewise.
* nix/libutil/util.cc (readFile, writeFile): Likewise.
2022-12-18 01:16:47 +01:00
Ludovic Courtès
eec920ba93
Revert "nix: Guard against removing temporary roots of living processes."
This reverts commit bb0beaecde.  This
change broke a number of tests that assumed the previous behavior.
2022-10-17 09:37:27 +02:00
Ludovic Courtès
bb0beaecde
nix: Guard against removing temporary roots of living processes.
Fixes <https://issues.guix.gnu.org/25018>.

* nix/libstore/gc.cc (readTempRoots): Add a check to guard against removing
the temporary roots of a living process.

Signed-off-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
2022-10-07 16:54:20 -04:00
Maxime Devos
4b32f87e9a
daemon: Remove unused function findOutput.
* nix/libstore/misc.cc (findOutput): Remove it.
* nix/libstore/misc.hh (findOutput): Likewise.

Signed-off-by: Mathieu Othacehe <othacehe@gnu.org>
2022-09-11 16:43:30 +02:00
Maxime Devos
93032586df
daemon: Remove unused function exportPaths.
* nix/libstore/store-api.cc (exportPaths): Remove it.
* nix/libstore/store-api.hh (exportPaths): Likewise.

Signed-off-by: Mathieu Othacehe <othacehe@gnu.org>
2022-09-11 16:43:30 +02:00
Maxime Devos
1c5f5d6d8c
daemon: Remove unused function openStore.
* nix/libstore/store-api.cc (openStore): Remove it.
* nix/libstore/store-api.hh (openStore): Likewise.

Signed-off-by: Mathieu Othacehe <othacehe@gnu.org>
2022-09-11 16:43:30 +02:00
Tobias Geerinckx-Rice
0ace58b99c
daemon: Quote consistently within a string.
* nix/libstore/build.cc (DerivationGoal::registerOutput): ‘’ → `'.
2022-06-05 02:00:00 +02:00
Tobias Geerinckx-Rice
82b06436b4
daemon: Clarify ‘--check’ error when outputs are missing.
Drop the confusing ‘invalid’ jargon and display a hint like we do
for ‘--fallback’.

* nix/libstore/build.cc (DerivationGoal::outputsSubstituted): Rewrite error message.
2022-05-29 02:00:00 +02:00
yarl-baudig@mailoo.org
32916e04f7
daemon: runChild() is forbidden to talk during environment set up
DerivationGoal::startBuilder() is waiting for an empty line as a check that
the environment set up is fine.

Fixes <https://issues.guix.gnu.org/55324>.

* nix/libstore/build.cc (DerivationGoal::runChild): Remove 'debug'
statement corresponding to bind mounts.

Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2022-05-18 22:29:55 +02:00
Ludovic Courtès
5f74169e8e
daemon: Support systemd-style socket activation.
* nix/nix-daemon/guix-daemon.cc (SD_LISTEN_FDS_START): New macro.
(systemd_activation_sockets): New function.
(main): Use it.  Remove obsolete 'printMsg' call.
* doc/guix.texi (Invoking guix-daemon): Document socket activation.
2022-04-14 14:48:20 +02:00
Ludovic Courtès
575e52ac2b
daemon: Always default to gzip for log compression.
* nix/libstore/globals.cc (Settings::Settings): Have 'logCompression'
default to COMPRESSION_GZIP unconditionally.
* gnu/services/base.scm (<guix-configuration>)[log-compression]: Default
to 'gzip.
* doc/guix.texi (Invoking guix-daemon, Base Services): Adjust accordingly.
2022-01-18 18:46:51 +01:00
Tobias Geerinckx-Rice
1b1f557d88
daemon: Print the line whence we expect an integer.
* nix/libstore/local-store.cc (LocalStore::getLineFromSubstituter):
Include the malformed substituter stream line in the error message.
2021-11-27 00:49:53 +01:00
Ludovic Courtès
f9b1bb916c
daemon: Read substitute nar size as 'unsigned long long'.
Fixes <https://issues.guix.gnu.org/46212>.
Reported by Christopher Baines <mail@cbaines.net>.

Previously, the nar size returned by 'guix substitute' would be read as
an 'int'; thus, values above 2^31 - 1 would be read and then stored as
negative integers in the database.

Regression introduced in 9dfa20a22a.

* nix/libstore/build.cc (SubstitutionGoal::finished): Use templatized
'string2Int' instead of 'std::atoi' to get an 'unsigned long long',
which is the type of 'hash.second'.
* tests/store.scm ("substitute and large size"): New test.
2021-11-25 00:17:21 +01:00
Ludovic Courtès
1eb40a6dc4
daemon: Read unsigned nar size and download size from substituter.
Fixes <https://issues.guix.gnu.org/51983>.
Reported by Tobias Geerinckx-Rice <me@tobias.gr>.

* nix/libstore/local-store.cc (LocalStore::querySubstitutablePathInfos):
Expect 'unsigned long long' for 'downloadSize' and 'narSize'.
* tests/store.scm ("substitute query and large size"): New test.
2021-11-25 00:17:21 +01:00
Ludovic Courtès
24224530d1
daemon: Micro-optimize 'deletePath'.
'remove' calls 'unlink' first and falls back to 'rmdir' upon EISDIR.
This change gets rid of the 'unlink' call for every directory being
removed.

* nix/libutil/util.cc (_deletePath): Call 'unlink' or 'rmdir' depending
on 'st.st_mode', rather than call 'remove'.
2021-11-19 23:04:19 +01:00
Ludovic Courtès
472a0e82a5
daemon: Do not deduplicate files smaller than 8 KiB.
Files smaller than 8 KiB typically represent ~70% of the entries in
/gnu/store/.links but only contribute to ~4% of the space savings
afforded by deduplication.

Not considering these files for deduplication speeds up file insertion
in the store and, more importantly, leaves 'removeUnusedLinks' with
fewer entries to traverse, thereby speeding it up proportionally.

Partly fixes <https://issues.guix.gnu.org/24937>.

* config-daemon.ac: Remove symlink hard link check and CAN_LINK_SYMLINK
definition.
* guix/store/deduplication.scm (%deduplication-minimum-size): New
variable.
(deduplicate)[loop]: Do not recurse when FILE's size is below
%DEDUPLICATION-MINIMUM-SIZE.
(dump-port): New procedure.
(dump-file/deduplicate)[hash]: Turn into...
[dump-and-compute-hash]: ... this thunk.
Call 'deduplicate' only when SIZE is greater than
%DEDUPLICATION-MINIMUM-SIZE; otherwise call 'dump-port'.
* nix/libstore/gc.cc (LocalStore::removeUnusedLinks): Drop files where
st.st_size < deduplicationMinSize.
* nix/libstore/local-store.hh (deduplicationMinSize): New declaration.
* nix/libstore/optimise-store.cc (deduplicationMinSize): New variable.
(LocalStore::optimisePath_): Return when PATH is a symlink or smaller
than 'deduplicationMinSize'.
* tests/derivations.scm ("identical files are deduplicated"): Produce
files bigger than %DEDUPLICATION-MINIMUM-SIZE.
* tests/nar.scm ("restore-file-set with directories (signed, valid)"):
Likewise.
* tests/store-deduplication.scm ("deduplicate, below %deduplication-minimum-size"):
New test.
("deduplicate", "deduplicate, ENOSPC"): Produce files bigger than
%DEDUPLICATION-MINIMUM-SIZE.
* tests/store.scm ("substitute, deduplication"): Likewise.
2021-11-16 14:34:28 +01:00
Xinglu Chen
8579304e8f
build: Don’t delete ‘guix-gc.timer’ file.
Without this invoking ‘make clean’ would remove ‘guix-gc.timer’, and ‘make’
would fail with.

  make[2]: *** No rule to make target 'etc/guix-gc.timer', needed by 'all-am'.  Stop.

* nix/local.mk (nodist_systemdservice_DATA): Remove ‘guix-gc.timer’.
2021-10-01 08:58:06 +00:00
Thiago Jung Bauermann
5c4fd77097
etc: Add systemd files for running ‘guix gc’ periodically
* etc/guix-gc.service.in: New file.
* etc/guix-gc.timer: Likewise.
* .gitignore: Ignore generated ‘guix-gc.service’.
* nix/local.mk (nodist_systemdservice_DATA): Add ‘guix-gc.service’ and
‘guix-gc.timer’.
(EXTRA_DIST): Add ‘guix-gc.service.in’ and ‘guix-gc.timer’.
* doc/guix.texi (Binary Installation): Mention the new systemd files.

Signed-off-by: Mathieu Othacehe <othacehe@gnu.org>
2021-09-20 14:18:21 +00:00
Ludovic Courtès
2d73086262
daemon: 'guix substitute' replies on FD 4.
This avoids the situation where error messages would unintentionally go
to stderr and be wrongfully interpreted as a reply by the daemon.

Fixes <https://bugs.gnu.org/46362>.
This is a followup to ee3226e9d5.

* guix/scripts/substitute.scm (display-narinfo-data): Add 'port'
parameter and honor it.
(process-query): Likewise.
(process-substitution): Likewise.
(%error-to-file-descriptor-4?, with-redirected-error-port): Remove.
(%reply-file-descriptor): New variable.
(guix-substitute): Remove use of 'with-redirected-error-port'.  Define
'reply-port' and pass it to 'process-query' and 'process-substitution'.
* nix/libstore/build.cc (SubstitutionGoal::handleChildOutput): Swap
'builderOut' and 'fromAgent'.
* nix/libstore/local-store.cc (LocalStore::getLineFromSubstituter):
Likewise.
* tests/substitute.scm <top level>: Set '%reply-file-descriptor'
rather than '%error-to-file-descriptor-4?'.
2021-04-09 17:46:38 +02:00
Ludovic Courtès
222fff253c
daemon: Remove dead code.
Reported by Noisytoot on #guix.

* nix/nix-daemon/shared.hh (showManPage): Remove.
* nix/nix-daemon/nix-daemon.cc (printHelp, programId): Remove.
2021-04-03 22:08:33 +02:00
zimoun
aed51ecea8
gnu: guix: Fix openrc init scripts.
Fixes <https://bugs.gnu.org/46871>.

* gnu/packages/package-management.scm (guix)[arguments]: Fix openrc init.
* nix/local.mk (openrcservicedir): Likewise.

Signed-off-by: Efraim Flashner <efraim@flashner.co.il>
2021-03-30 10:29:33 +03:00
Ludovic Courtès
ec7fb66994
daemon: Prevent privilege escalation with '--keep-failed' [security].
Fixes <https://bugs.gnu.org/47229>.
Reported by Nathan Nye of WhiteBeam Security.

* nix/libstore/build.cc (DerivationGoal::startBuilder): When 'useChroot'
is true, add "/top" to 'tmpDir'.
(DerivationGoal::deleteTmpDir): Adjust accordingly.  When
'settings.keepFailed' is true, chown in two steps: first the "/top"
sub-directory, and then rename "/top" to its parent.
2021-03-18 12:18:56 +01:00
Ludovic Courtès
bc3896db25
daemon: Correctly handle '--discover' with no value.
Previously, we'd get:

  $ guix-daemon --discover
  error: basic_string::_M_construct null not valid

* nix/nix-daemon/guix-daemon.cc (parse_opt): Change second argument to
'settings.set' to properly handle case where ARG is NULL.
2021-03-17 12:03:23 +01:00
Ludovic Courtès
c7c7f068c1
daemon: Delegate deduplication to 'guix substitute'.
This removes the main source of latency between subsequent downloads.

* nix/libstore/build.cc (SubstitutionGoal::tryToRun): Add a
"deduplicate" key to ENV.
(SubstitutionGoal::finished): Remove call to 'optimisePath'.
* guix/scripts/substitute.scm (process-substitution)[destination-in-store?]
[dump-file/deduplicate*]: New variables.
Pass #:dump-file to 'restore-file'.
* guix/scripts/substitute.scm (guix-substitute)[deduplicate?]: New
variable.
Pass #:deduplicate? to 'process-substitution'.
* guix/serialization.scm (dump-file): Export and augment 'dump-file'.
2020-12-19 23:25:01 +01:00
Ludovic Courtès
15cf28fbb4
daemon: Do not reset timestamps and permissions on substituted items.
'guix substitute' now takes care of it via 'restore-file'.

* nix/libstore/build.cc (SubstitutionGoal::finished): Remove call to
'canonicalisePathMetaData'.
2020-12-19 23:25:01 +01:00
Ludovic Courtès
9dfa20a22a
daemon: Let 'guix substitute' perform hash checks.
This way, the hash of the store item can be computed as it is restored,
thereby avoiding an additional file tree traversal ('hashPath' call)
later on in the daemon.  Consequently, it should reduce latency between
subsequent substitute downloads.

This is a followup to 5ff521452b.

* guix/scripts/substitute.scm (narinfo-hash-algorithm+value): New
procedure.
(process-substitution): Wrap INPUT into a hash input port, 'hashed', and
read from it.  Compare the actual and expected hashes, and print a
"hash-mismatch" status line when they differ.  When they match, print
not just "success" but also the nar hash and size.
* nix/libstore/build.cc (class SubstitutionGoal)[expectedHashStr]:
Remove.
(SubstitutionGoal::finished): Tokenize 'status'.  Parse it and handle
"success" and "hash-mismatch" accordingly.  Call 'hashPath' only when
the returned hash is not SHA256.
(SubstitutionGoal::handleChildOutput): Remove 'expectedHashStr'
handling.
* tests/substitute.scm ("substitute, invalid hash"): Rename to...
("substitute, invalid narinfo hash"): ... this.
("substitute, invalid hash"): New test.
2020-12-19 23:25:00 +01:00
Ludovic Courtès
bfe4cdf88e
daemon: Raise an error if substituter doesn't send the expected hash.
It was already impossible in practice for 'expectedHashStr' to be empty
if 'status' == "success".

* nix/libstore/build.cc (SubstitutionGoal::finished): Throw 'SubstError'
when 'expectedHashStr' is empty.
2020-12-08 22:30:08 +01:00
Ludovic Courtès
5ff521452b
substitute: Cache and reuse connections while substituting.
That way, when fetching a series of substitutes from the same server(s),
the connection is reused instead of being closed/opened for each
substitutes, which saves on network round trips and TLS handshakes.

* guix/http-client.scm (http-fetch): Add #:keep-alive? and honor it.
* guix/progress.scm (progress-report-port): Add #:close? parameter and
honor it.
* guix/scripts/substitute.scm (at-most): Return the tail as a second
value.
(fetch): Add #:port and #:keep-alive? and honor them.
(%max-cached-connections): New variable.
(open-connection-for-uri/cached, call-with-cached-connection): New
procedures.
(with-cached-connection): New macro.
(process-substitution): Wrap 'fetch' call in 'with-cached-connection'.
Pass #:close? to 'progress-report-port'.
2020-12-08 22:30:08 +01:00
Ludovic Courtès
711df9ef3c
daemon: Run 'guix substitute --substitute' as an agent.
This avoids spawning one substitute process per substitution.

* nix/libstore/build.cc (class Worker)[substituter]: New field.
[outPipe, logPipe, pid]: Remove.
(class SubstitutionGoal)[expectedHashStr, status, substituter]: New fields.
(SubstitutionGoal::timedOut): Adjust to check 'substituter'.
(SubstitutionGoal::tryToRun): Remove references to 'outPipe' and
'logPipe'.  Run "guix substitute --substitute" as an 'Agent'.  Send the
request with 'writeLine'.
(SubstitutionGoal::finished): Likewise.
(SubstitutionGoal::handleChildOutput): Change to fill in
'expectedHashStr' and 'status'.
(SubstitutionGoal::handleEOF): Call 'wakeUp' unconditionally.
(SubstitutionGoal::~SubstitutionGoal): Adjust to check 'substituter'.
* guix/scripts/substitute.scm (process-substitution): Write "success\n"
to stdout upon success.
(%error-to-file-descriptor-4?): New variable.
(guix-substitute): Set 'current-error-port' to file descriptor 4
unless (%error-to-file-descriptor-4?) is false.
Remove "--substitute" arguments.  Loop reading line from stdin.
* tests/substitute.scm <top level>: Call '%error-to-file-descriptor-4?'.
(request-substitution): New procedure.
("substitute, no signature")
("substitute, invalid hash")
("substitute, unauthorized key")
("substitute, authorized key")
("substitute, unauthorized narinfo comes first")
("substitute, unsigned narinfo comes first")
("substitute, first narinfo is unsigned and has wrong hash")
("substitute, first narinfo is unsigned and has wrong refs")
("substitute, two invalid narinfos")
("substitute, narinfo with several URLs"): Adjust to new "guix
substitute --substitute" calling convention.
2020-12-08 22:30:08 +01:00
Ludovic Courtès
a618a8c620
daemon: Factorize substituter agent spawning.
* nix/libstore/local-store.hh (class LocalStore)[substituter]: New
method.
[runningSubstituter]: Turn into a shared_ptr.
* nix/libstore/local-store.cc (LocalStore::querySubstitutablePaths):
Call 'substituter' instead of using inline code.
(LocalStore::querySubstitutablePathInfos): Likewise.
(LocalStore::substituter): New method.
2020-12-08 22:30:08 +01:00
Ludovic Courtès
79c6614f58
daemon: Use 'Agent' to spawn 'guix substitute --query'.
* nix/libstore/local-store.hh (RunningSubstituter): Remove.
(LocalStore)[runningSubstituter]: Change to unique_ptr<Agent>.
[setSubstituterEnv, didSetSubstituterEnv]: Remove.
[getLineFromSubstituter, getIntLineFromSubstituter]: Take an 'Agent'.
* nix/libstore/local-store.cc (LocalStore::~LocalStore): Remove
reference to 'runningSubstituter'.
(LocalStore::setSubstituterEnv, LocalStore::startSubstituter): Remove.
(LocalStore::getLineFromSubstituter): Adjust to 'run' being an 'Agent'.
(LocalStore::querySubstitutablePaths): Spawn substituter agent if
needed.  Adjust to 'Agent' interface.
(LocalStore::querySubstitutablePathInfos): Likewise.
* nix/libstore/build.cc (SubstitutionGoal::tryToRun): Remove call to
'setSubstituterEnv' and add 'setenv' call for "_NIX_OPTIONS" instead.
(SubstitutionGoal::finished): Remove 'readLine' call for 'dummy'.
* guix/scripts/substitute.scm (%allow-unauthenticated-substitutes?):
Remove second argument to 'make-parameter'.
(process-query): Call 'warn-about-missing-authentication'
when (%allow-unauthenticated-substitutes?) is #t.
(guix-substitute): Wrap body in 'parameterize'.  Set 'guix-warning-port'
too.  No longer exit when 'substitute-urls' returns the empty list.  No
longer print newline initially.
* tests/substitute.scm (test-quit): Parameterize 'current-error-port' to
account for the port changes in 'guix-substitute'.
2020-12-08 22:30:08 +01:00