| Age | Commit message (Collapse) | Author | Files | Lines |
|
I want to use the build-max-log-size feature since it's useful for the
bordeaux build farm to cap the log size. I can't see any reason to limit this
functionality as I think it has the same security implications as the
build-timeout and build-max-silent-time settings.
* nix/nix-daemon/nix-daemon.cc (performOp): Allow any client to set
build-max-log-size.
Change-Id: I87825c43ef914c85866e82fe1ed899f13a559b38
|
|
This puts ‘importPaths’ on par with ‘addToStore’ and ‘addTextToStore’: since
the two latter RPCs let anyone add content-addressed items in the store,
there’s no reason for ‘importPaths’ to require signatures by authorized keys
on these content-addressed items.
This will allow for things like ‘guix copy’ of .drv items without
authorization, or ‘guix deploy’ with (build-locally? #f) without
authorization.
* nix/libstore/store-api.hh (isContentAddressedPath): New prototype.
* nix/libstore/store-api.cc (isContentAddressedPath): New function.
* nix/libutil/util.hh (isPlainFile): New prototype.
* nix/libutil/util.cc (isPlainFile): New function.
* nix/libstore/local-store.cc (LocalStore::importPath): Define ‘narHash’ and
‘contentAddressed’. Allow unsigned imports when ‘contentAddressed’ is true;
bypass signature verification when ‘contentAddressed’ is true.
* tests/store.scm ("import not signed"): Rewrite to not use a
content-addressed store item.
("import signed by unauthorized key"): Likewise.
("import not signed but content-addressed tree"): New test.
("import not signed but content-addressed regular file"): New test.
("import signed by unauthorized key but content-addressed"): New test.
("import with corrupt signature"): New test.
("import signed by authorized key but hash doesn't match"): New test.
("import with corrupt signature but content-addressed"): New test.
("import signed by authorized key, hash doesn't match, but content-addressed"):
New test.
* doc/guix.texi (Invoking guix archive): Document the exception for
content-addressed store items. Add anchor for ‘--authorize’.
(Invoking guix deploy): Document the benefit of (build-locally? #f).
Add cross-reference for ‘authorize?’.
Co-authored-by: Reepca Russelstein <reepca@russelstein.xyz>
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Merges: #8979
|
|
* nix/libstore/local-store.hh (AuthenticationError): New error type.
* nix/libstore/local-store.cc (readAuthenticateReply): Throw it.
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
|
|
* nix/libstore/store-api.cc (textTypeWithReferences): New function.
(computeStorePathForText): Use it.
Change-Id: I9d82ac04619d736ce737dec745416396b7b18751
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
|
|
In ‘guix-daemon’ the value of ‘requireSignature’ has always been true.
* nix/libstore/local-store.hh (LocalStore)[importPath]: Remove
‘requireSignature’ argument.
* nix/libstore/local-store.cc (LocalStore::importPath): Adjust accordingly.
Change-Id: I4e2d781c85107770cb64ab71d2e7fb711859e0c7
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
|
|
For ‘guix-daemon’ the value of ‘requireSignature’ has always been true.
* nix/libstore/store-api.hh (StoreAPI)[importPaths]: Remove ‘requireSignature’
argument.
* nix/libstore/local-store.hh (LocalStore)[importPaths]: Likewise.
* nix/libstore/local-store.cc (LocalStore::importPaths): Adjust accordingly.
* nix/nix-daemon/nix-daemon.cc (performOp): Remove first argument to
‘importPaths’.
Change-Id: I7ed87f3af03cca7078e224788114c499773f01c2
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
|
|
This fixes surprising error message like as follows,
which looks like an overlook:
@ unsupported-platform /gnu/store/4xb677bysagk7pl4xba9xz4gzwvsh0zn-guile-bootstrap-2.0.drv x86_64-gnu
while setting up the child process: in phase exec: a `x86_64-gnu' is required to build `x86_64-linux',
but I am a `/gnu/store/4xb677bysagk7pl4xba9xz4gzwvsh0zn-guile-bootstrap-2.0.drv'
* nix/libstore/build.cc (execBuilderOrBuiltin):
Fix the error message when canBuildLocally fails.
Fixes: 3af52f845fe2 ("[...] use std::format instead of boost::format.")
Merges: https://codeberg.org/guix/guix/pulls/10080
Signed-off-by: Nguyễn Gia Phong <cnx@loang.net>
|
|
The prior implementation of 'parse' was, to put it mildly, very accepting of
invalid input. This made it very difficult to review its security properties,
which ended up relying entirely on the fact that it still didn't allow "/" in
directory entry names and that O_CREAT|O_EXCL implicitly causes symlinks to
not be followed in the final component, and mkdir and symlink never follow
symlinks in the final component, and all of the above throw exceptions when
they fail.
Some examples of what was allowed prior:
1. Empty archives:
"nix-archive-1" "(" ")"
2. Archives with only a type:
"nix-archive-1" "(" "type" "regular" ")"
3. Archives of regular files with multiple contents, which would be
concatenated (e.g. this has contents "foobar"):
"nix-archive-1" "(" "type" "regular" "contents" "foo" "contents" "bar" ")"
4. Archives of directories with multiple entries with the same name, and that
aren't sorted:
"nix-archive-1" "(" "type" "directory"
"entry" "(" "name" "c" "node" "(" ")" ")"
"entry" "(" "name" "b" "node" "(" ")" ")"
"entry" "(" "name" "b" "node" "(" ")" ")"
"entry" "(" "name" "a" "node" "(" ")" ")" ")"
5. Archives of directories with empty entries:
"nix-archive-1" "(" "type" "directory" "entry" "(" ")" ")"
6. Archives of directories with entries with no name:
"nix-archive-1" "(" "type" "directory" "entry" "(" "node" "(" ")" ")" ")"
7. Archives of directories with entries with no node:
"nix-archive-1" "(" "type" "directory" "entry" "(" "name" "a" ")" ")"
7. Archives of directories with entries with multiple names:
"nix-archive-1" "(" "type" "directory" "entry" "(" "name" "a"
"node" "(" ")"
"name" "b" ")" ")"
8. Archives of directories with entries with multiple nodes:
"nix-archive-1" "(" "type" "directory" "entry" "(" "node" "(" ")"
"node" "(" ")" ")" ")"
9. Archives of directories with entries with multiple names and multiple
nodes:
"nix-archive-1" "(" "type" "directory"
"entry" "(" "name" "a" "node" "(" ")"
"name" "b" "node" "(" ")" ")" ")"
Such permissiveness rather defeats the "normalized" part of "Normalized
ARchive".
Additionally, 'parse' previously used recursion with no explicit depth limit.
In practice Linux would still limit the depth to around 2048, since filenames
longer than 4096 bytes yield ENAMETOOLONG, but no such restriction exists on
Hurd.
The permissiveness issue is resolved by rewriting 'parse', and the unbounded
recursion issue is resolved by adding a nestLimit parameter so that no more
than DIRECTORY_NESTING_LIMIT (currently 256) levels of recursion are used. An
alternate implementation that doesn't use recursion, 'parse_unbounded', is
included in case it is determined that the nesting limit should be removed,
but currently only 'parse' is used.
* nix/libutil/archive.cc (parse): rewrite to add nestLimit parameter.
(parseDump): pass DIRECTORY_NESTING_LIMIT as nestLimit argument to 'parse'.
(parse_unbounded): new function.
Change-Id: Ia3c32cc645b609f6ae7f3bcafc491ec0073cbb51
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
|
|
Specifying all three of -K, --check, --rounds=3 caused valid packages to be
deleted from the store.
When `buildMode == bmCheck`, the built package is not renamed from
`actualPath` to `i.second.path. Then later, when `settings.keepFailed` and
`curRound < nrRounds`, `i.second.path` was renamed to `i.second.path + "-check"`
anyway.
* nix/libstore/build.cc (DerivationGoal::registerOutputs): Add check for bmCheck
before renaming store path.
* tests/store.scm ("build-things, check mode"): Ensure file is a valid path.
("build-things, check mode + keep-failed"): New test.
Fixes: #9631.
Change-Id: I31d24b2349f563867b8101a1b5ce3c10896ce165
Co-authored-by: Ludovic Courtès <ludo@gnu.org>
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Merges: #9632
|
|
Previously an authorized substitute server could produce invalid store paths -
that is, paths that do denote a top-level file in the store, but that do not
obey the syntax restrictions beyond what that implies. Given that an
authorized substitute server can already potentially do a lot of damage if it
really wanted to, this isn't a major issue, but closing off this opportunity
does simplify the analysis somewhat.
* nix/libstore/local-store.cc (LocalStore::importPath): use
strict readStorePath(s) variants.
* tests/store.scm ("import path not in store, unsigned", "import path not in
store, signed", "import invalid path, unsigned", "import invalid path,
signed" test cases): new test cases. The "not in store" cases succeeded
previously, while the "invalid path" cases did not succeed prior to this
commit.
Fixes: guix/guix#9078
Change-Id: Ib81c19ec1ae0fff5b7c7268f4f7429b16a870996
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Merges: #9434
|
|
isStorePath is a lightweight check that only verifies that the given path is
in the store and doesn't have any '/' characters after the store prefix. This
is insufficiently strict for verifying that a given path is actually a valid
store path.
isStoreName is extracted from checkStoreName, and to preserve the error
messages may have a second argument giving a string to write to with the
problem description in the case that isStoreName returns false.
* nix/libstore/store-api.hh (assertStorePathStrict, isStoreName,
isStoreBasenameStrict, isStorePathStrict): new functions.
* nix/libstore/worker-protocol.hh (readStorePathStrict): new function.
(readStorePathsStrict): new template.
* nix/libstore/store-api.cc (assertStorePathStrict, isStoreName,
isStoreBasenameStrict, isStorePathStrict, readStorePathStrict,
readStorePathsStrict): provide implementations.
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
|
|
* nix/libutil/hash.hh (isHash32): new function.
* nix/libutil/hash.hh (isHash32): provide implementation.
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
|
|
Recognizing base32 characters and/or parsing them into byte sequences is done
in several places, so it makes sense to provide a common lookup table.
* nix/libutil/hash.hh (base32Values, base32ValuesInitialized): new variables.
(initializeBase32Values, getBase32Value): new functions.
* nix/libutil/hash.cc (base32Values, base32ValuesInitialized): provide
definition for variables.
(initializeBase32Values, getBase32Value): provide function implementations.
(parseHash32): use base32Values.
* nix/libstore/references.cc (search): use base32Values.
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
|
|
Config files like /etc/services may be symbolic links to files not available
in the build environment; copy them instead of creating dangling symlinks.
This also reverts 425aa1bf7c35839f5e500515ff3b5a861a7533d6, which would
potentially create dangling symlinks in the chroot, as reported by @cnx in
guix/guix#9072.
* nix/libstore/build.cc (DerivationGoal::startBuilder): copy network config
files.
Fixes: guix/guix#4225
Change-Id: I38fc6374c5cecdcd16de06161db00b3825688f2a
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Modified-by: Ludovic Courtès <ludo@gnu.org>
|
|
Docker's default seccomp filter prevents use of the ADDR_NO_RANDOMIZE flag
with the personality system call. It causes personality to return EPERM. In
general, we assume that any result other than the only documented one, EINVAL,
is caused by seccomp. If we detect that ADDR_NO_RANDOMIZE is blocked, and the
--allow-aslr option was passed, we simply don't use it.
This allows guix-daemon to continue to work even in these containers, without
any implicit weakening of reproducibility.
Since it is presumably desirable to be able to build guix itself in such an
environment, also pass --allow-aslr to guix-daemon in test-env.
* nix/libstore/globals.hh (Settings::allowASLR): new field.
* nix/nix-daemon/guix-daemon.cc (options): add --allow-aslr option.
(parse_opt): use it to set Settings::allowASLR.
* nix/libstore/build.cc (DerivationGoal::startBuilder): detect when
ADDR_NO_RANDOMIZE is blocked and --allow-aslr is passed and don't use it in
that case.
* doc/guix.texi: document --allow-aslr in "Invoking guix-daemon".
* build-aux/test-env.in: always pass --allow-aslr.
Fixes: guix/guix#3917
Change-Id: I51c5899a9559e161f9e107c2e6a36df395ab3134
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Modified-by: Ludovic Courtès <ludo@gnu.org>
Merges: #4616
|
|
* doc/local.mk (lang_to_texinfo): Refer to .texi files using srcdir.
(xref_command): Reference pre-inst-env using builddir.
($(srcdir)/%D%/guix.%.texi):
($(srcdir)/%D%/guix-cookbook.%.texi):
($(srcdir)/%D%/contributing.%.texi): Refer to source files using srcdir.
* nix/local.mk (etc/guix-gc.timer): Use the name of the prerequisite,
not just its file name.
Change-Id: I247bcd873c8355d0eae07870ec849d2eb8cfa6c5
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Merges: #8267
|
|
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>
|
|
* 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
|
|
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
|
|
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
|
|
Change-Id: Id73c0c74600a3da3373b3a37236b505af65bfe31
|
|
* nix/libstore/globals.hh,
nix/libstore/store-api.hh,
nix/libutil/util.hh: Fix misspellings in comments.
Change-Id: Id77ea2bde1c2582d1a7bec4ed256ea900998c4b8
|
|
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
|
|
* nix/libstore/build.cc (Worker::waitForInput): Fix typo in format string.
Change-Id: I0a39ada8a347c8c8daddd9f34292cbbb03ba0076
|
|
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>
|
|
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>
|
|
* 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>
|
|
* 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>
|
|
* 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>
|
|
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
|
|
* 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
|
|
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
|
|
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>
|
|
* nix/libstore/gc.cc (findRoots): Print the message corresponding to errno.
Change-Id: Ia0ddfa6512bbeced1fb0c7c0cc69899674330f29
|
|
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
|
|
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
|
|
* 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
|
|
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
|
|
* 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>
|
|
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>
|
|
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>
|
|
* 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>
|
|
* nix/libutil/seccomp.hh: Include cstdint.
Change-Id: I454c7abd56abbe4cf03a5bc8ebc402678e07a0f0
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
‘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>
|
|
‘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>
|