summaryrefslogtreecommitdiff
path: root/nix
AgeCommit message (Collapse)Author
2026-03-29daemon: Dereference symlinks for /etc/services & co.Ludovic Courtès
Fixes a regression on Guix System introduced in c4298638ca27717be4a83cb033dcbfecdea88093 (from guix/guix#4178) where files in /etc, such as /etc/services, would be symlinks. Consequently, the chroot of fixed-output derivations would contain a dangling symlink for /etc/services, leading to name resolution failures in the chroot. This also relates to 82f84f5e7fb34cc719ed6ea538a3d1ca7516f23d. * nix/libstore/build.cc (DerivationGoal::startBuilder): Add call to ‘canonPath’. Change-Id: If34c8e74447ffc03d9fa81a1ea6bc0aef7c4d0b3 Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2026-03-19daemon: Resolve symlinks in /etc/resolv.conf for slirp4netns chroot.Roman Scherer
* nix/libstore/build.cc (prepareSlirpChrootAction): Use canonPath(i, true) to resolve symlinks when adding /etc/resolv.conf and /etc/hosts to the slirp4netns chroot, so that bindMount receives a regular file path instead of a symlink. On systems using systemd-resolved, /etc/resolv.conf is typically a symlink: /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf The slirp4netns chroot creates an empty /run/ directory, so when bindMount copies the symlink verbatim (spawn.cc line 537-542), the target does not exist and slirp4netns cannot determine the upstream DNS server. This causes all DNS resolution to fail for fixed-output derivations that use the Guile-based git-fetch builder (e.g. git-fetch/lfs), since they rely on slirp4netns for network access in the build chroot. Derivations using builtin:git-download are unaffected because they run in the daemon process itself, which has full network access. Change-Id: Ib73e69a8760e74eb8141dd0408c27aa8b3001e37 Signed-off-by: Ludovic Courtès <ludo@gnu.org> Merges: #6959
2026-02-27daemon: Actually remove unreadable directories.Reepca Russelstein
Fixes a regression introduced in 7173c2c0ca. Additional discussion at https://codeberg.org/guix/guix/pulls/5977. * nix/libutil/util.cc (_deletePathAt): chmod directory and retry open when it fails with EACCES. Do this using an O_PATH file descriptor referenced via /proc/self/fd whenever possible to avoid it being replaced by a non-directory immediately before being chmod'ed. * nix/libutil/util.hh (deletePath): document TOCTTOU race on non-linux systems where hardlinks aren't protected. * tests/derivations.scm ("unreadable directories in build tree can be removed"): new test. Fixes: guix/guix#5891 Reported-by: Liliana Marie Prikler <liliana.prikler@gmail.com> Change-Id: I749127fe5254ebabc8387a2f0ef47e3c116bfcc5 Signed-off-by: Ludovic Courtès <ludo@gnu.org> Merges: #6460
2026-02-06daemon: Remove unused entities in globals.{hh, cc}.Congcong Kuo
All these entities are not been used anywhere. * nix/libstore/globals.hh (Settings): Remove 'overrides' member and 'getOverrides' method declaration. (nixVersion): Removed. * nix/libstore/globals.cc (Settings::set): Do not update the 'overrides' map. (Settings::getOverrides): Remove function definition. Change-Id: If7dbb6df79178d2569cda21e1fe5e0ea3d8e59ba Signed-off-by: Ludovic Courtès <ludo@gnu.org> Merges: #6009
2026-01-22Merge branch 'version-1.5.0'Rutherther
Change-Id: Id73c0c74600a3da3373b3a37236b505af65bfe31
2026-01-14nix: Spelling corrections.Efraim Flashner
* nix/libstore/globals.hh, nix/libstore/store-api.hh, nix/libutil/util.hh: Fix misspellings in comments. Change-Id: Id77ea2bde1c2582d1a7bec4ed256ea900998c4b8
2026-01-12daemon: Fix several format strings.Ludovic Courtès
This is a followup to 3af52f845fe2ceb448416ac7b9f48925673c594e and 6f1448ef89c8ad29e2a479099531fd3a87701e46. * nix/libstore/local-store.cc (LocalStore::queryValidPathId): Change %1% to {}. * nix/libstore/optimise-store.cc (LocalStore::optimisePath_): Likewise. * nix/nix-daemon/guix-daemon.cc (open_unix_domain_socket): Likewise. (main): Likewise. * nix/libutil/affinity.cc (restoreAffinity): Remove useless %1%. Change-Id: I3a7cd79cd69ab58f14118662f1dcf2fef067a6b7
2025-12-26daemon: Fix typo in format string.Ludovic Courtès
* nix/libstore/build.cc (Worker::waitForInput): Fix typo in format string. Change-Id: I0a39ada8a347c8c8daddd9f34292cbbb03ba0076
2025-12-22daemon: Ensure store is writable even as non-root.Rutherther
If the store is read only, return an error early. This is bit of a compromise. Not all operations of the daemon need the store as writable. For example, if hello package is built already `guix build hello` could previously succeed even if store is RO. * nix/libstore/local-store.cc (makeStoreWritable): Rename to ensureStoreWritable. (ensureStoreWritable): As non-root, check that the store is writable and if not, throw an error. (LocalStore::LocalStore): Use it. * nix/libstore/local-store.hh: Rename makeStoreWritable to ensureStoreWritable. Change-Id: I94783ba7e32d57bfa77e37e84b6ac316f95e31e2 Signed-off-by: Rutherther <rutherther@ditigal.xyz>
2025-11-12daemon: Use inline functions and variables instead of externCongcong Kuo
Avoid separate declarations and definitions for so-called 'global' objects. * nix/libstore/derivations.{cc, hh} (drvHashes): Use inline instead of separate declaration and definition. * nix/libstore/globals.{cc, hh} (settings, nixVersion): Same. * nix/libstore/local-store.hh (drvsLogDir, deduplicationMinSize): Same. * nix/libstore/optimise-store.cc (deduplicationMinSize): Same. * nix/libstore/store-api.{cc, hh} (store): Same. * nix/libutil/archive.{cc, hh} (defaultPathFilter): Same. * nix/libutil/hash.{cc, hh} (base32Chars): Same and modify header files. * nix/libutil/util.{cc, hh} (logType, verbosity, _writeToStderr, _isInterrupted): Same. * nix/local.mk: Modified according to the rename of shared.hh. * nix/nix-daemon/guix-daemon.cc (blockInt, argvSaved, run): Same and modify header files. * nix/nix-daemon/nix-daemon.cc: Modify header files. * nix/nix-daemon/shared.hh: Renamed to nix-daemon.hh Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-11-04daemon: Fix compilation error while using Zig (LLVM)Congcong Kuo
* nix/libstore/build.cc (guestUID, guestGID): Rename to 'defaultGuestUID' and 'defaultGuestGID' respectively. (initializeUserNamespace, DerivationGoal::startBuilder): Rename references to variables accordingly. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-11-03daemon: Use starts_with() and ends_with() instead of string() or hasSuffix()Congcong Kuo
* nix/libstore/build.cc (DerivationGoal::tryBuildHook): Use starts_with instead of string() * nix/libstore/builtins.cc (lookupBuiltinBuilder): Same. * nix/libstore/builtins.hh (isBuiltin): Same and fix indentation of the file. * nix/libstore/derivations.cc (DerivationOutput::parseHashInfo, isDerivation): Same and clean header files. * nix/libstore/gc.cc (addPermRoot, LocalStore::isActiveTempFile): Same. * nix/libstore/globals.cc: Same. * nix/libstore/local-store.cc: Same. * nix/libstore/misc.cc: Same. * nix/libstore/store-api.cc (checkStoreName): Same. * nix/libutil/affinity.cc: Same. * nix/libutil/archive.cc: Same. * nix/libutil/spawn.cc: Same. * nix/libutil/util.{cc, hh} (hasSuffix): Removed. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-10-19daemon: Bump to C++20 and use ‘std::format’ instead of ‘boost::format’.Congcong Kuo
* nix/boost: This directory and all files inside it are removed. * nix/libstore/build.cc (Goal::trace): Use ‘std::string’ instead of ‘const format &’. (DerivationGoal::startBuilder, ...): Use ‘std::format’ or ‘std::vformat’ instead of ‘boost::format’. * nix/libstore/builtins.cc (builtinDownload): Same. * nix/libstore/derivations.cc (DerivationOutput::parseHashInfo, ...): Same. * nix/libstore/gc.cc (LocalStore::openGCLock, ...): Same. * nix/libstore/globals.cc (Settings::_get): Same. * nix/libstore/local-store.cc: (checkStoreNotSymlink, ...): Same. * nix/libstore/misc.cc (dfsVisit, showBytes): Same * nix/libstore/optimise-store.cc (makeWritable, ...): Same. * nix/libstore/pathlocks.cc (openLockFile, ...): Same. * nix/libstore/references.cc (search, scanForReferences): Same. * nix/libstore/sqlite.hh (throwSQLiteError): Use ‘std::string’ instead of ‘const format &’. * nix/libstore/sqlite.cc (throwSQLiteError): Use ‘std::string’ instead of ‘const format &’. * nix/libstore/store-api.cc (assertStorePath, ...): Use ‘std::format’ instead of ‘boost::format’. * nix/libutil/affinity.cc (setAffinityTo): Same. * nix/libutil/archive.cc (dumpContents, ...): Same. * nix/libutil/hash.cc (parseHash, parseHash32, parseHash16or32, hashFile): Same. * nix/libutil/hash.hh (parseHash, parseHash32, parseHash16or32, isHash): Same. * nix/libutil/serialise.cc : Add ‘<cassert>’ header file. * nix/libutil/spawn.cc (addPhaseAfter, ...): Use ‘std::format’ instead of ‘boost::format’. * nix/libutil/types.hh (FormatOrString): Removed. (BaseError, BaseError::addPrefix, SysError, MakeError): Use ‘std::string or std::string_view’ instead of ‘FormatOrString’. * nix/libutil/util.hh (Nest::open, printMsg_, warnOnce, expect): Same. * nix/libutil/util.cc (BaseError::BaseError, ...): Same. (writeToStderr, _interrupted): Use std::uncaught_exceptions() instead of std::uncaught_exception() * nix/nix-daemon/nix-daemon.cc (performOp, ...): Same. * nix/nix-daemon/guix-daemon.cc (string_to_bool, ...): Same. * nix/local.mk: Remove ‘libformat.a’ from ‘noinst_LIBRARIES’, remove ‘libformat_a_SOURCES’ and ‘libformat_headers’, remove ‘libformat_a_CPPFLAGS’ from ‘libutil_a_CPPFLAGS’ and ‘guix_daemon_LDADD’, update ‘AM_CXXFLAGS’ to ‘-std=c++20’. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-10-16daemon: Attempt to map the “kvm” group inside the build user namespace.Ludovic Courtès
Fixes <https://issues.guix.gnu.org/77862>. Previously, the ‘guix-daemon’ account (for unprivileged execution) would typically have “kvm” as a supplementary group, but that group would not be mapped in the build user namespace. Consequently, attempts to ‘chown’ a file to that supplementary group would fail with EINVAL. The test suites of Coreutils, Python, and Go (among others) exercise this chown-to-supplementary-group behavior, so they would all fail when started by the unprivileged ‘guix-daemon’ even though they succeed when started by ‘guix-daemon’ running as root. Thanks to keinflue <keinflue@posteo.net> and Reepca Russelstein <reepca@russelstein.xyz> for helping out. * nix/libstore/build.cc (initializeUserNamespace): Add ‘extraGIDs’ and ‘haveCapSetGID’ parameters. Invoke ‘newgidmap’ when ‘extraGIDs’ is non-empty and ‘haveCapSetGID’ is false. Honor ‘extraGIDs’ when ‘haveCapSetGID’ is true. (maxGroups, guestKVMGID): New variables. (kvmGIDMapping): New function. (DerivationGoal::startBuilder): Set ‘ctx.lockMountsMapAll’ in the CLONE_NEWUSER case. Pass ‘extraGIDs’ to ‘initializeUserNamespace’. * tests/store.scm ("kvm GID is mapped"): New test. Change-Id: I10ba710fc1b9ca1e3cd3122be1ec8ede5df18b40
2025-10-16daemon: Export as little as needed from libutil/spawn.cc.Ludovic Courtès
* nix/libutil/spawn.cc (reset_writeToStderrAction, restoreAffinityAction) (setsidAction, earlyIOSetupAction, dropAmbientCapabilitiesAction) (chrootAction, chdirAction, closeMostFDsAction, setPersonalityAction) (oomSacrificeAction, setIDsAction, setNoNewPrivsAction) (addSeccompFilterAction, restoreSIGPIPEAction, setupSuccessAction) (usernsInitSyncAction, usernsSetIDsAction, initLoopbackAction) (setHostAndDomainAction, makeFilesystemsPrivateAction) (makeChrootSeparateFilesystemAction, bindMount) (mountIntoChroot, mountIntoChrootAction, mountProcAction) (mountDevshmAction, mountDevptsAction, pivotRootAction) (idMapToIdentityMap, lockMountsAction, runChildSetupEntry): Add ‘static’ qualifier. * nix/libutil/spawn.hh: Remove the corresponding ‘extern’ declarations. Change-Id: I3156d72d866f22fa31aa9a843f116771763ccb61
2025-10-16daemon: ‘runProgram’ exits with 127 upon ENOENT or similar.Ludovic Courtès
This is in accordance with widespread conventions. Previously it would exit with code 1, which was misleading. * nix/libutil/util.cc (runProgram): Exit with 127 if ‘execv’ or ‘execvp’ fails. Change-Id: I5df214afffda69aa329a25afbc48f6cbfdd0961c
2025-09-23daemon: Restore post-canonicalization permissions after moving.Reepca Russelstein
At this point the value of 'st.st_mode' is from before canonicalization, so restoring to that will undo the permissions aspect of the canonicalization for a top-level directory store item. Fixes #1104, introduced in ae18b3d9e6 (https://codeberg.org/guix/guix/commit/ae18b3d9e6bd0c184505a094851448d08555e23e). * nix/libstore/build.cc (DerivationGoal::registerOutputs): update 'st' with post-canonicalization permissions before making actualPath temporarily-writable. * tests/store.scm ("build outputs aren't writable"): new test. Change-Id: I5e5eaa79fa6b7f81e1d12fd285883c762a22ce5a Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-09-18daemon: “cannot read potential root” messages shows errno message.Ludovic Courtès
* nix/libstore/gc.cc (findRoots): Print the message corresponding to errno. Change-Id: Ia0ddfa6512bbeced1fb0c7c0cc69899674330f29
2025-09-06daemon: Avoid comparison of integers of different signs.Ludovic Courtès
Fixes guix/guix#1173. * nix/libstore/gc.cc (LocalStore::removeUnusedLinks): Cast ‘st_size’ as unsigned. Reported-by: Congcong Kuo <congcong.kuo@gmail.com> Change-Id: Ibe4674bcef186befe8a0e536278c87458b098c9d
2025-08-23daemon: Tolerate pipes and sockets in failed build trees.Ludovic Courtès
Fixes <https://issues.guix.gnu.org/78919>. Fixes guix/guix#471. Fixes a bug introduced in ae18b3d9e6bd0c184505a094851448d08555e23e whereby interrupting ‘guix build -K hello’ would leave a build directory with root ownership due ‘secureFilePerms’ bailing out due to the presence of FIFOs in the temporary build directory. * nix/libstore/build.cc (secureFilePerms): Add ‘allowSpecialFiles’ parameter; honor it and pass it in recursive call. (DerivationGoal::deleteTmpDir): Pass true as the second argument to ‘secureFilePerms’. Reported-by: Janneke Nieuwenhuizen <janneke@gnu.org> Reported-by: David Elsing <david.elsing@posteo.net> Change-Id: I638a4ee909a2b5022f9153e1cbb832bfb2e15263
2025-07-28guix gc: Adjust size suffix based on the amount of data.Efraim Flashner
* guix/ui.scm (number->size): New procedure. * guix/scripts/gc.scm (guix-gc)[actions]: Display the amount of collected-garbage using more specific units. [ensure-free-space]: Display the size using an appropriate size unit. * nix/libstore/gc.cc (deletePathRecursive, removeUnusedLinks): Same. * nix/libstore/optimise-store.cc (showBytes): Move function ... * nix/libstore/misc.cc: ... to here. Expand to adjust the output based on the amount of bytes received. Change-Id: Idceb1a13f8e45f959d327f53d1a8accb29d2678b
2025-07-16daemon: Consider the current user as trusted.Ludovic Courtès
This allows use of ‘guix gc --verify=repair’ when running guix-daemon as an unprivileged user. * nix/nix-daemon/nix-daemon.cc (acceptConnection): Consider the current user as trusted. Reported-by: David Elsing <david.elsing@posteo.net> Change-Id: I559e56cf0640e8dc9bbc510317aa2bdc024ff681
2025-07-16daemon: Use std::string or std::vector instead of variable-length array (VLA).Congcong Kuo
* libutil/util.h (waitForMessage): Use std::string instead of char* to unify coding style. * libutil/util.cc (waitForMessage): Use std::string instead of variable-length array (VLA). (readLink, copyFileRecursively, expect): Use std::vector instead of VLA. * libutil/hash.cc (printHash): Use std::vector instead of VLA. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-07-04daemon: Gracefully handle target mount point already existing.Reepca Russelstein
Fixes guix/guix#903. * nix/libutil/spawn.cc (bindMount): in the "regular file" case, only create a placeholder file if one doesn't already exist. Change-Id: Ie46b2fef2cea5b2a052c4ec48d00e97bfc1ee506 Reported-by: Hilton Chain <hako@ultrarare.space> Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-06-30daemon: Conditionally disable seccomp filter on ‘socketcall’ systems.Reepca Russelstein
glibc currently will insist on using 'socketcall' on i686-linux unless built with '--enable-kernel=4.3.0' or above, even on systems that have dedicated system calls available for all the socket-related functionality. This behavior breaks the assumption that socketcall can be safely blocked without impacting functionality in slirp4netns, rendering the seccomp filter unusable with those glibcs. This change makes the slirp4netns seccomp filter opt-in on systems with a 'socketcall' system call. It can either be opted-into at compile-time or at runtime using the NO_SOCKETCALL_LIBC preprocessor define or the GUIX_FORCE_SECCOMP environment variable, respectively. The seccomp filter being disabled on these systems means that it is possible for a compromised slirp4netns to access abstract unix domain sockets in the root network namespace. It does not affect any of the other mechanisms used to isolate slirp4netns (e.g. chroot, namespaces, etc). Fixes guix/guix#808. * nix/libstore/build.cc (spawnSlirp4netns) [__NR_socketcall]: Do not add seccomp filter, unless ‘GUIX_FORCE_SECCOMP’ is set. Change-Id: Ibfe8becc9431f5aff11a21f06858b20496f9cb4a Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-06-26daemon: Fix build of spawn.cc for non-Linux and newer GCC.Reepca Russelstein
* nix/libutil/spawn.cc: Include <fcntl.h> and <cstdint>. (cloneChild): Wrap body in #if CLONE_ENABLED. Change-Id: I0be7e6dbe80ac2f7022793149472270a4e49d23c Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-06-25daemon: Fix build with gcc-14.Andreas Enge
* nix/libutil/seccomp.hh: Include cstdint. Change-Id: I454c7abd56abbe4cf03a5bc8ebc402678e07a0f0
2025-06-24daemon: Protect ‘copyFileRecursively’ from race conditions.Ludovic Courtès
Previously, if an attacker managed to introduce a hard link or a symlink on one of the destination file names before it is opened, ‘copyFileRecursively’ would overwrite the symlink’s target or the hard link’s content. This kind of attack could be carried out while guix-daemon is copying the output or the chroot directory of a failed fixed-output derivation build, possibly allowing the attacker to escalate to the privileges of the build user. * nix/libutil/util.cc (copyFileRecursively): In the ‘S_ISREG’ case, open ‘destination’ with O_NOFOLLOW | O_EXCL. In the ‘S_ISDIR’ case, open ‘destination’ with O_NOFOLLOW. Reported-by: Reepca Russelstein <reepca@russelstein.xyz> Change-Id: I94273efe4e92c1a4270a98c5ec47bd098e9227c9 Signed-off-by: John Kehayias <john.kehayias@protonmail.com>
2025-06-24daemon: add seccomp filter for slirp4netns.Reepca Russelstein
The container that slirp4netns runs in should already be quite difficult to do anything malicious in beyond basic denial of service or sending of network traffic. There is, however, one hole remaining in the case in which there is an adversary able to run code locally: abstract unix sockets. Because these are governed by network namespaces, not IPC namespaces, and slirp4netns is in the root network namespace, any process in the root network namespace can cooperate with the slirp4netns process to take over its user. To close this, we use seccomp to block the creation of unix-domain sockets by slirp4netns. This requires some finesse, since slirp4netns absolutely needs to be able to create other types of sockets - at minimum AF_INET and AF_INET6 Seccomp has many, many pitfalls. To name a few: 1. Seccomp provides you with an "arch" field, but this does not uniquely determine the ABI being used; the actual meaning of a system call number depends on both the number (which is often the result of ORing a related system call with a flag for an alternate ABI) and the architecture. 2. Seccomp provides no direct way of knowing what the native value for the arch field should be; the user must do configure/compile-time testing for every architecture+ABI combination they want to support. Amusingly enough, the linux-internal header files have this exact information (SECCOMP_ARCH_NATIVE), but they aren't sharing it. 3. The only system call numbers we naturally have are the native ones in asm/unistd.h. __NR_socket will always refer to the system call number for the target system's ABI. 4. Seccomp can only manipulate 32-bit words, but represents every system call argument as a uint64. 5. New system call numbers with as-yet-unknown semantics can be added to the kernel at any time. 6. Based on this comment in arch/x86/entry/syscalls/syscall_32.tbl: # 251 is available for reuse (was briefly sys_set_zone_reclaim) previously-invalid system call numbers may later be reused for new system calls. 7. Most architecture+ABI combinations have system call tables with many gaps in them. arm-eabi, for example, has 35 such gaps (note: this is just the number of distinct gaps, not the number of system call numbers contained in those gaps). 8. Seccomp's BPF filters require a fully-acyclic control flow graph. Any operation on a data structure must therefore first be fully unrolled before it can be run. 9. Seccomp cannot dereference pointers. Only the raw bits provided to the system calls can be inspected. 10. Some architecture+ABI combos have multiplexer system calls. For example, socketcall can perform any socket-related system call. The arguments to the multiplexed system call are passed indirectly, via a pointer to user memory. They therefore cannot be inspected by seccomp. 11. Some valid system calls are not listed in any table in the kernel source. For example, __ARM_NR_cacheflush is an "ARM private" system call. It does not appear in any *.tbl file. 12. Conditional branches are limited to relative jumps of at most 256 instructions forward. 13. Prior to Linux 4.8, any process able to spawn another process and call ptrace could bypass seccomp restrictions. To address (1), (2), and (3), we include preprocessor checks to identify the native architecture value, and reject all system calls that don't use the native architecture. To address (4), we use the AC_C_BIGENDIAN autoconf check to conditionally define WORDS_BIGENDIAN, and match up the proper portions of any uint64 we test for with the value in the accumulator being tested against. To address (5) and (6), we use system call pinning. That is, we hardcode a snapshot of all the valid system call numbers at the time of writing, and reject any system call numbers not in the recorded set. A set is recorded for every architecture+ABI combo, and the native one is chosen at compile-time. This ensures that not only are non-native architectures rejected, but so are non-native ABIs. For the sake of conciseness, we represent these sets as sets of disjoint ranges. Due to (7), checking each range in turn could add a lot of overhead to each system call, so we instead binary search through the ranges. Due to (8), this binary search has to be fully unrolled, so we do that too. It can be tedious and error-prone to manually produce the syscall ranges by looking at linux's *.tbl files, since the gaps are often small and uncommented. To address this, a script, build-aux/extract-syscall-ranges.sh, is added that will produce them given a *.tbl filename and an ABI regex (some tables seem to abuse the ABI field with strange values like "memfd_secret"). Note that producing the final values still requires looking at the proper asm/unistd.h file to find any private numbers and to identify any offsets and ABI variants used. (10) used to have no good solution, but in the past decade most architectures have gained dedicated system call alternatives to at least socketcall, so we can (hopefully) just block it entirely. To address (13), we block ptrace also. * build-aux/extract-syscall-ranges.sh: new script. * Makefile.am (EXTRA_DIST): register it. * config-daemon.ac: use AC_C_BIGENDIAN. * nix/libutil/spawn.cc (setNoNewPrivsAction, addSeccompFilterAction): new functions. * nix/libutil/spawn.hh (setNoNewPrivsAction, addSeccompFilterAction): new declarations. (SpawnContext)[setNoNewPrivs, addSeccompFilter]: new fields. * nix/libutil/seccomp.hh: new header file. * nix/libutil/seccomp.cc: new file. * nix/local.mk (libutil_a_SOURCES, libutil_headers): register them. * nix/libstore/build.cc (slirpSeccompFilter, writeSeccompFilterDot): new functions. (spawnSlirp4netns): use them, set seccomp filter for slirp4netns. Change-Id: Ic92c7f564ab12596b87ed0801b22f88fbb543b95 Signed-off-by: John Kehayias <john.kehayias@protonmail.com>
2025-06-24daemon: Use slirp4netns to provide networking to fixed-output derivations.Reepca Russelstein
Previously, the builder of a fixed-output derivation could communicate with an external process via an abstract Unix-domain socket. In particular, it could send an open file descriptor to the store, granting write access to some of its output files in the store provided the derivation build fails—the fix for CVE-2024-27297 did not address this specific case. It could also send an open file descriptor to a setuid program, which could then be executed using execveat to gain the privileges of the build user. With this change, fixed-output derivations other than “builtin:download” and “builtin:git-download” always run in a separate network namespace and have network access provided by a TAP device backed by slirp4netns, thereby closing the abstract Unix-domain socket channel. * nix/libstore/globals.hh (Settings)[useHostLoopback, slirp4netns]: new fields. * config-daemon.ac (SLIRP4NETNS): new C preprocessor definition. * nix/libstore/globals.cc (Settings::Settings): initialize them to defaults. * nix/nix-daemon/guix-daemon.cc (options): add --isolate-host-loopback option. * doc/guix.texi: document it. * nix/libstore/build.cc (DerivationGoal)[slirp]: New field. (setupTap, setupTapAction, waitForSlirpReadyAction, enableRouteLocalnetAction, prepareSlirpChrootAction, spawnSlirp4netns, haveGlobalIPv6Address, remapIdsTo0Action): New functions. (initializeUserNamespace): allow the guest UID and GID to be specified. (DerivationGoal::killChild): When ‘slirp’ is not -1, call ‘kill’. (DerivationGoal::startBuilder): Unconditionally add CLONE_NEWNET to FLAGS. When ‘fixedOutput’ is true, spawn ‘slirp4netns’. When ‘fixedOutput’ and ‘useChroot’ are true, add setupTapAction, waitForSlirpReadyAction, and enableRouteLocalnetAction to builder setup phases. Create a /etc/resolv.conf for fixed-output derivations that directs them to slirp4netns's dns address. When settings.useHostLoopback is true, supply fixed-output derivations with a /etc/hosts that resolves "localhost" to slirp4netns's address for accessing the host loopback. * nix/libutil/util.cc (keepOnExec, decodeOctalEscaped, sendFD, receiveFD, findProgram): New functions. * nix/libutil/util.hh (keepOnExec, decodeOctalEscaped, sendFD, receiveFD, findProgram): New declarations. * gnu/packages/package-management.scm (guix): add slirp4netns input for linux targets. * tests/derivations.scm (builder-network-isolated?): new variable. ("fixed-output derivation, network access, localhost", "fixed-output derivation, network access, external host"): skip test case if fixed output derivations are isolated from the network. Change-Id: Ia3fea2ab7add56df66800071cf15cdafe7bfab96 Signed-off-by: John Kehayias <john.kehayias@protonmail.com>
2025-06-24daemon: add and use spawn.cc and spawn.hh.Reepca Russelstein
This adds a mechanism for manipulating and running "spawn phases" similarly to how builder-side code manipulates "build phases". The main difference is that spawn phases take a (reference to a) single structure that they can both read from and write to, with their writes being visible to subsequent phases. The base structure type for this is SpawnContext. It also adds some predefined phase sequences, namely basicSpawnPhases and cloneSpawnPhases, and exposes each of the actions performed by these phases. Finally, it modifies build.cc to replace runChild() with use of this new code. * nix/libutil/util.cc (keepOnExec, waitForMessage): new functions. * nix/libutil.util.hh (keepOnExec, waitForMessage): add prototypes. * nix/libutil/spawn.cc, nix/libutil/spawn.hh: new files. (addPhaseAfter, addPhaseBefore, prependPhase, appendPhase, deletePhase, replacePhase, reset_writeToStderrAction, restoreAffinityAction, setsidAction, earlyIOSetupAction, dropAmbientCapabilitiesAction, chrootAction, chdirAction, closeMostFDsAction, setPersonalityAction, oomSacrificeAction, setIDsAction, restoreSIGPIPEAction, setupSuccessAction, execAction, getBasicSpawnPhases, usernsInitSyncAction, usernsSetIDsAction, initLoopbackAction, setHostAndDomainAction, makeFilesystemsPrivateAction, makeChrootSeparateFilesystemAction, statfsToMountFlags, bindMount, mountIntoChroot, mountIntoChrootAction, mountProcAction, mountDevshmAction, mountDevptsAction, pivotRootAction, lockMountsAction, getCloneSpawnPhases, runChildSetup, runChildSetupEntry, cloneChild, idMapToIdentityMap, unshareAndInitUserns): new procedures. * nix/local.mk (libutil_a_SOURCES): add spawn.cc. (libutil_headers): add spawn.hh. * nix/libstore/build.cc (restoreSIGPIPE, DerivationGoal::runChild, childEntry): removed procedures. (DerivationGoal::{dirsInChroot,env,readiness}): removed. (execBuilderOrBuiltin, execBuilderOrBuiltinAction, clearRootWritePermsAction): new procedures. (DerivationGoal::startBuilder): modified to use a CloneSpawnContext if chroot builds are available, otherwise a SpawnContext. Change-Id: Ifd50110de077378ee151502eda62b99973d083bf Change-Id: I76e10d3f928cc30566e1e6ca79077196972349f8 spawn.cc, util.cc, util.hh changes Change-Id: I287320e63197cb4f65665ee5b3fdb3a0e125ebac Signed-off-by: John Kehayias <john.kehayias@protonmail.com>
2025-06-24daemon: Implement ‘deletePath’ in terms of the *at functions.Reepca Russelstein
deletePath needs to be able to operate securely in unfriendly environments, where adversaries may be concurrently modifying the files being operated on. For example, directories that we are currently recursing through may be replaced with symbolic links. We err on the side of early failure here: if a file or directory is concurrently modified in a way that causes one of the system calls to fail, we throw an exception immediately instead of trying to adapt to the change. Note that we use fstat instead of fstatat for verifying the directory's st_mode field because AT_EMPTY_PATH is linux-specific. * nix/libutil/util.cc (_deletePathAt): new procedure. (_deletePath): use it. Change-Id: I7ccfe6f1f74dbab95617b24034494e0f63030582 Signed-off-by: Ludovic Courtès <ludo@gnu.org> Signed-off-by: John Kehayias <john.kehayias@protonmail.com>
2025-06-09daemon: Remove ‘foreach’ and ‘foreach_reverse’Congcong Kuo
‘foreach_reverse’ is not used anywhere * nix/libutil/util.hh (foreach, foreach_reverse): Remove. * nix/libstore/build.cc (addToWeakGoals): Use ‘std::none_of’ instead of macro ‘foreach’. (Goal::waiteeDone, Goal::amDone, UserLock::acquire, rewriteHashes, DerivationGoal::addWantedOutputs, DerivationGoal::haveDerivation, DerivationGoal::outputsSubstituted, DerivationGoal::repairClosure, DerivationGoal::inputsRealised, DerivationGoal::tryToBuild, DerivationGoal::buildDone, DerivationGoal::tryBuildHook, DerivationGoal::startBuilder, DerivationGoal::runChild, parseReferenceSpecifiers, DerivationGoal::registerOutputs, DerivationGoal::checkPathValidity, SubstitutionGoal::tryNext, SubstitutionGoal::referencesValid, Worker::removeGoal, Worker::childTerminated, Worker::run, Worker::waitForInput): Use range-based ‘for’ instead of macro ‘foreach’. * nix/libstore/derivations.cc (writeDerivation, unparseDerivation, hashDerivationModulo): Likewise. * nix/libstore/gc.cc (addAdditionalRoots, LocalStore::deletePathRecursive, LocalStore::canReachRoot, LocalStore::collectGarbage): Likewise. * nix/libstore/globals.cc (Settings::pack): Likewise. * nix/libstore/local-store.cc (checkDerivationOutputs, queryValidPaths, querySubstitutablePaths, querySubstitutablePathInfos, registerValidPaths, verifyStore, verifyPath): Likewise. * nix/libstore/misc.cc (computeFSClosure, dfsVisit, topoSortPaths): Likewise. * nix/libstore/optimise-store.cc (LocalStore::optimisePath_, LocalStore::optimiseStore): Likewise. * nix/libstore/pathlocks.cc (PathLocks::lockPaths, PathLocks::~PathLocks): Likewise. * nix/libstore/references.cc (search, scanForReferences): Likewise. * nix/libstore/store-api.cc (checkStoreName, computeStorePathForText, StoreAPI::makeValidityRegistration, showPaths, readStorePaths): Likewise. * nix/libutil/serialise.cc (writeStrings): Likewise. * nix/libutil/util.cc (concatStringsSep): Likewise. * nix/nix-daemon/nix-daemon.cc (performOp): Likewise. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-06-03daemon: Remove ‘singleton’ and replace ‘typedef’ with ‘using’ in ↵Congcong Kuo
‘types.hh’ * nix/libutil/util.hh (singleton): Remove. * nix/libstore/build.cc (DerivationGoal::startBuilder) (SubstitutionGoal::tryNext, SubstitutionGoal::tryToRun) (LocalStore::ensurePath, LocalStore::repairPath): Use normal construction function instead of ‘singleton’. * nix/libstore/local-store.cc (LocalStore::addToStoreFromDump) (LocalStore::addTextToStore, LocalStore::importPath): Likewise. * nix/nix-daemon/nix-daemon.cc (performOp): Likewise. Change-Id: If0d929407c09482f3b506a1c51dfda70e29696dd Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-06-01daemon: Fix build failure with gcc@15.wrobell
* nix/libstore/build.cc (CompareGoalPtrs::operator): Add const keyword. * nix/libstore/store-api.hh: Add missing include for uint64_t. Change-Id: I56368da9eb10dc376f7e6eeae6a61746bb36c9cf Signed-off-by: Andreas Enge <andreas@enge.fr>
2025-05-28daemon: Remove ‘AutoDeleteArray’.Congcong Kuo
* libutil/util.hh (AutoDeleteArray): Remove. * libutil/util.cc (readString, readStrings): Use ‘std::vector’ instead of ‘AutoDeleteArray’. * libutil/serialise.cc (readFile): Likewise. Change-Id: I45362998dbb8226874f66b77cd19f071f7bb2ab3 Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-05-25daemon: Remove ‘defined’ in macro definition.Congcong Kuo
Closes #6. * nix/libstore/build.cc (CHROOT_ENABLED, CLONE_ENABLED): Wrap in #ifdefs. Change-Id: I217e46fc2cac579a199fcd7c28ef5a8155a12750 Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-05-14build: Fix substitutions for .service files.Ludovic Courtès
Fixes <https://issues.guix.gnu.org/78318>. This is a followup to 107eb8ee8f5f9192c795abeb47885b49a57bacd4. * nix/local.mk (etc/guix-%.service): Add ‘g’ for ‘@localstatedir@’ substitution. Substitute ‘@storedir@’. Reported-by: Ido Yariv <yarivido@gmail.com> Change-Id: I9b53d3a6d713a000bc0a7a57f667badc00d2dff8
2025-05-12daemon: Replace ‘random_shuffle’ with ‘shuffle’.Congcong Kuo
‘std::random_shuffle’ was removed in C++14. * nix/libstore/gc.cc (LocalStore::collectGarbage): Use ‘std::random’ and ‘std::shuffle’. Change-Id: If91ed3ec3596a419ae7c87d7ce677e0970853e9f Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2025-04-25daemon: Use the guest GID in /etc/group.Ludovic Courtès
Partly fixes <https://issues.guix.gnu.org/77862>. Fixes a bug whereby, when running guix-daemon unprivileged, /etc/group would contain the wrong GID for the “nixbld” group. This inconsistency would lead to failures in the Coreutils test suite, for instance. * nix/libstore/build.cc (DerivationGoal::startBuilder): Use ‘guestGID’ when writing /etc/group. * tests/store.scm ("/etc/passwd and /etc/group"): New test. Reported-by: keinflue <keinflue@posteo.net> Change-Id: I739bc96c4c935fd9015a45e2bfe5b3e3f90554a9
2025-04-14daemon: Catch SIGINT, SIGTERM, and SIGHUP for proper termination.Ludovic Courtès
Previously the daemon would not install handlers for these signals. It would thus terminate abruptly when receiving them, without properly closing the SQLite database. Consequently, the database’s WAL file, which is normally deleted by the last client closing the database (via ‘sqlite3_close’), would not be deleted when the guix-daemon process is terminated; instead, it would persist and possibly keep growing beyond reason. This patch fixes that. * nix/nix-daemon/nix-daemon.cc (handleSignal, setTerminationSignalHandler): New functions. (processConnection): Call it. Reported-by: Christopher Baines <mail@cbaines.net> Change-Id: I07e510a1242e92b6a629d60eb840e029c0f921be
2025-04-11daemon: Do not make chroot root directory read-only.Ludovic Courtès
Fixes <https://issues.guix.gnu.org/77570>. Commit 40f69b586a440d0397fa3dfe03b95a0f44e4d242 made chroot root directory read-only; as a consequence, build processes attempting to write to the root directory would now get EROFS instead of EACCES. It turns out that a number of test suites (Go, Ruby, SCons, Shepherd) would fail because of this observable difference. To restore previous behavior in build environments while still preventing build processes from exposing their root directory to outside processes, this patch (1) keeps the root writable but #o555 by default, thereby restoring the EACCES behavior, and (2) ensures that the parent of the chroot root directory is itself user-accessible only. * nix/libstore/build.cc (class DerivationGoal)[chrootRootTop]: New field. (DerivationGoal::startBuilder): Initialize ‘chrootRootTop’ and make it ‘AutoDelete’. Replace ‘mount’ call that made the root directory read-only by a mere ‘chmod_’ call. * tests/store.scm ("build root cannot be made world-readable"): Remove. ("writing to build root leads to EACCES"): New test. Reported-by: Ada Stevenson <adanskana@gmail.com> Reported-by: keinflue <keinflue@posteo.net> Suggested-by: Reepca Russelstein <reepca@russelstein.xyz> Change-Id: I5912e8b3b293f8242a010cfc79255fc981314445
2025-03-26daemon: Move comments where they belong.Ludovic Courtès
* nix/libstore/build.cc (DerivationGoal::startBuilder): Shuffle comments for clarity. Change-Id: I6557c103ade4a3ab046354548ea193c68f8c9c05
2025-03-26daemon: Drop Linux ambient capabilities before executing builder.Ludovic Courtès
* config-daemon.ac: Check for <sys/prctl.h>. * nix/libstore/build.cc (DerivationGoal::runChild): When ‘useChroot’ is true, call ‘prctl’ to drop all ambient capabilities. Change-Id: If34637fc508e5fb6d278167f5df7802fc595284f
2025-03-26daemon: Create /var/guix/profiles/per-user unconditionally.Ludovic Courtès
* nix/libstore/local-store.cc (LocalStore::LocalStore): Create ‘perUserDir’ unconditionally. Change-Id: I5188320f9630a81d16f79212d0fffabd55d94abe
2025-03-26daemon: Allow running as non-root with unprivileged user namespaces.Ludovic Courtès
Many thanks to Reepca Russelstein for their review and guidance on these changes. * nix/libstore/build.cc (guestUID, guestGID): New variables. (DerivationGoal)[readiness]: New field. (initializeUserNamespace): New function. (DerivationGoal::runChild): When ‘readiness.readSide’ is positive, read from it. (DerivationGoal::startBuilder): Call ‘chown’ only when ‘buildUser.enabled()’ is true. Pass CLONE_NEWUSER to ‘clone’ when ‘buildUser.enabled()’ is false or not running as root. Retry ‘clone’ without CLONE_NEWUSER upon EPERM. (DerivationGoal::registerOutputs): Make ‘actualPath’ writable before ‘rename’. (DerivationGoal::deleteTmpDir): Catch ‘SysError’ around ‘_chown’ call. * nix/libstore/local-store.cc (LocalStore::createUser): Do nothing if ‘dirs’ already exists. Warn instead of failing when failing to chown ‘dir’. * guix/substitutes.scm (%narinfo-cache-directory): Check for ‘_NIX_OPTIONS’ rather than getuid() == 0 to determine the cache location. * doc/guix.texi (Build Environment Setup): Reorganize a bit. Add section headings “Daemon Running as Root” and “The Isolated Build Environment”. Add “Daemon Running Without Privileges” subsection. Remove paragraph about ‘--disable-chroot’. (Invoking guix-daemon): Warn against ‘--disable-chroot’ and explain why. * tests/derivations.scm ("builder is outside the store"): New test. Reviewed-by: Reepca Russelstein <reepca@russelstein.xyz>
2025-03-26daemon: Remount root directory as read-only.Ludovic Courtès
* nix/libstore/build.cc (DerivationGoal::runChild): Bind-mount the store and /tmp under ‘chrootRootDir’ to themselves as read-write. Remount / as read-only. Change-Id: I79565094c8ec8448401897c720aad75304fd1948
2025-03-26daemon: Remount inputs as read-only.Ludovic Courtès
* nix/libstore/build.cc (DerivationGoal::runChild): Remount ‘target’ as read-only. Reported-by: Reepca Russelstein <reepca@russelstein.xyz> Change-Id: Ib7201bcf4363be566f205d23d17fe2f55d3ad666
2025-03-26daemon: Bind-mount all the inputs, not just directories.Ludovic Courtès
* nix/libstore/build.cc (DerivationGoal::startBuilder): Add all of ‘inputPaths’ to ‘dirsInChroot’ instead of hard-linking regular files. Special-case symlinks. (DerivationGoal)[regularInputPaths]: Remove. Reported-by: Reepca Russelstein <reepca@russelstein.xyz> Change-Id: I070987f92d73f187f7826a975bee9ee309d67f56
2025-03-26daemon: Bind-mount /etc/nsswitch.conf & co. only if it exists.Ludovic Courtès
Those files may be missing in some contexts, for instance within the build environment. * nix/libstore/build.cc (DerivationGoal::runChild): Add /etc/resolv.conf and related files to ‘ss’ only if they exist. Change-Id: Ie19664a86c8101a1dc82cf39ad4b7abb10f8250a