summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xetc/guix-install.sh12
-rw-r--r--gnu/packages/admin.scm4
-rw-r--r--gnu/packages/audio.scm2
-rw-r--r--gnu/packages/bioinformatics.scm29
-rw-r--r--gnu/packages/fediverse.scm4
-rw-r--r--gnu/packages/guile-xyz.scm4
-rw-r--r--gnu/packages/machine-learning.scm43
-rw-r--r--gnu/packages/maths.scm6
-rw-r--r--gnu/packages/networking.scm27
-rw-r--r--gnu/packages/python-science.scm1
-rw-r--r--gnu/packages/python-xyz.scm37
-rw-r--r--gnu/packages/wm.scm4
-rw-r--r--gnu/services/cuirass.scm29
-rw-r--r--nix/libstore/build.cc95
-rw-r--r--nix/libutil/spawn.cc70
-rw-r--r--nix/libutil/spawn.hh43
-rw-r--r--nix/libutil/util.cc4
-rw-r--r--tests/store.scm23
18 files changed, 307 insertions, 130 deletions
diff --git a/etc/guix-install.sh b/etc/guix-install.sh
index 3918930472..57fd88e509 100755
--- a/etc/guix-install.sh
+++ b/etc/guix-install.sh
@@ -91,6 +91,11 @@ SYSV_INIT_REQUIRE=(
"daemonize"
)
+# Unprivileged guix-daemon requires 'newgidmap'.
+SYSTEMD_REQUIRE=(
+ "newgidmap"
+)
+
PAS=$'[ \033[32;1mPASS\033[0m ] '
ERR=$'[ \033[31;1mFAIL\033[0m ] '
WAR=$'[ \033[33;1mWARN\033[0m ] '
@@ -516,6 +521,13 @@ sys_create_build_user()
guix-daemon"$KVMGROUP" \
"Unprivileged Guix Daemon User"
+ if getent group kvm > /dev/null; then
+ # Allow 'newgidmap' to map the "kvm" group.
+ local kvmgid="$(getent group kvm | cut -f3 -d:)"
+ _msg_info "allowing kvm mapping (GID $kvmgid) for unprivileged guix-daemon"
+ echo "guix-daemon:$kvmgid:1" >> /etc/subgid
+ fi
+
# ‘tar xf’ creates root:root files. Change that.
chown -R guix-daemon:guix-daemon /gnu /var/guix
chown -R root:root /var/guix/profiles/per-user/root
diff --git a/gnu/packages/admin.scm b/gnu/packages/admin.scm
index bbb16b7a84..d549f41211 100644
--- a/gnu/packages/admin.scm
+++ b/gnu/packages/admin.scm
@@ -3034,7 +3034,7 @@ environment variable is set and output is to tty.")
(define-public lr
(package
(name "lr")
- (version "2.0")
+ (version "2.0.1")
(source
(origin
(method git-fetch)
@@ -3043,7 +3043,7 @@ environment variable is set and output is to tty.")
(commit (string-append "v" version))))
(file-name (git-file-name name version))
(sha256
- (base32 "05k971vf6080igfila8iav5d4j7sgh301123yng9lvsmr8frf8mf"))))
+ (base32 "0mqhcgi4v3zzic0ikf7ja4km1mik29gdp15q8qwjw5bmh22d74ff"))))
(build-system gnu-build-system)
(arguments
(list #:tests? #f ; There are no tests.
diff --git a/gnu/packages/audio.scm b/gnu/packages/audio.scm
index 12b6eb91f2..b03d2d4fe5 100644
--- a/gnu/packages/audio.scm
+++ b/gnu/packages/audio.scm
@@ -6814,7 +6814,7 @@ default and preferred audio driver but also supports native drivers like ALSA.")
(list cmake-minimal pkg-config))
(inputs
(list bash-minimal
- asio
+ asio-1.28
bitsery
clap-1.1
dbus
diff --git a/gnu/packages/bioinformatics.scm b/gnu/packages/bioinformatics.scm
index e94fca2935..cab61ef45a 100644
--- a/gnu/packages/bioinformatics.scm
+++ b/gnu/packages/bioinformatics.scm
@@ -24552,48 +24552,45 @@ populations.")
(license license:bsd-3)))
(define-public scregseg
+ ;; 0.1.3 was released in 2023, there are a lot of comparability fixes on
+ ;; master branch, use the latest commit for now.
+ (let ((commit "78ebff8c3507752c3bfbc4db3f72f7e8a733e92f")
+ (revision "0"))
(package
(name "scregseg")
- (version "0.1.3")
+ (version (git-version "0.1.3" revision commit))
(source (origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/BIMSBbioinfo/scregseg")
- (commit (string-append "v" version))))
+ (commit commit)))
(file-name (git-file-name name version))
(sha256
(base32
- "07g2barywa1wi8mggbxkbxqjw1fzd0a0l9cjdbkx4s40imb1dbxb"))
+ "19iasx6zh305cn8p390ack78f4iklyk61xmnf99c2b8ibml7jmzj"))
(snippet
'(delete-file "src/scregseg/_utils.c"))))
(build-system pyproject-build-system)
(arguments
(list
+ #:test-flags
+ #~(list "--pyargs" "scregseg")
#:phases
'(modify-phases %standard-phases
;; Numba needs a writable dir to cache functions.
(add-before 'check 'set-numba-cache-dir
(lambda _
(setenv "NUMBA_CACHE_DIR" "/tmp")))
- ;; Cython extensions have to be built before running the tests.
- (add-before 'check 'build-extensions
- (lambda _
- (invoke "python" "setup.py" "build_ext" "--inplace")))
;; NumPy 1.20 deprecated the type wrappers for int and float.
(add-after 'unpack 'compatibility
(lambda _
(substitute* "src/scregseg/_utils.pyx"
- (("np.float") "float"))))
- (add-after 'unpack 'do-not-fail-to-find-sklearn
- (lambda _
- ;; XXX: I have no idea why it cannot seem to find sklearn.
- (substitute* "setup.py"
- (("'sklearn',") "")))))))
+ (("np.float") "float")))))))
(native-inputs
(list python-cython
- python-wheel))
+ python-setuptools))
(propagated-inputs
- (list python-scikit-learn
+ (list python-scikit-learn-1.6
python-scipy
python-numpy
python-hmmlearn
@@ -24615,7 +24612,7 @@ Dirichlet-Multinomial emission probabilities to segment the genome either
according to distinct relative cross-cell accessibility profiles or (after
collapsing the single-cell tracks to pseudo-bulk tracks) to capture distinct
cross-cluster accessibility profiles.")
- (license license:gpl3+)))
+ (license license:gpl3+))))
(define-public megadepth
(package
diff --git a/gnu/packages/fediverse.scm b/gnu/packages/fediverse.scm
index e2bbb622ed..6cad92f38e 100644
--- a/gnu/packages/fediverse.scm
+++ b/gnu/packages/fediverse.scm
@@ -274,7 +274,7 @@ seamlessly with your desktop environment.")
(define-public snac2
(package
(name "snac")
- (version "2.81")
+ (version "2.83")
(source
(origin
(method git-fetch)
@@ -283,7 +283,7 @@ seamlessly with your desktop environment.")
(commit version)))
(file-name (git-file-name name version))
(sha256
- (base32 "12wnd7r9k1fmf9yikczhiplbjjvpi66c7n22hs6xla3qqm7vwcm3"))))
+ (base32 "0xh108p148mqlj1da05yrng0d82rw34n1i97cjzz7p606ll4j6p4"))))
(build-system gnu-build-system)
(inputs (list curl openssl))
(arguments
diff --git a/gnu/packages/guile-xyz.scm b/gnu/packages/guile-xyz.scm
index 92b70b2318..9f393ef82d 100644
--- a/gnu/packages/guile-xyz.scm
+++ b/gnu/packages/guile-xyz.scm
@@ -7769,14 +7769,14 @@ application to open a given file or URL based on given configurations.")
(define-public guile-goblins
(package
(name "guile-goblins")
- (version "0.16.1")
+ (version "0.17.0")
(source
(origin
(method url-fetch)
(uri (string-append "https://files.spritely.institute/releases"
"/guile-goblins/guile-goblins-" version ".tar.gz"))
(sha256
- (base32 "10ffdr98nck05pnsq5qagp7wpyky5wdk83n3qrnh9aphm9qq5frh"))))
+ (base32 "16jkmfspsnza2fdk5jr05a5pfh7x856gpg031i21s1yvy43l8mi0"))))
(build-system gnu-build-system)
(arguments
(list
diff --git a/gnu/packages/machine-learning.scm b/gnu/packages/machine-learning.scm
index 01b7c49de5..529841aad4 100644
--- a/gnu/packages/machine-learning.scm
+++ b/gnu/packages/machine-learning.scm
@@ -2133,6 +2133,49 @@ computing environments.")
data analysis.")
(license license:bsd-3)))
+;; 1.7 intorduced breaking changes in API.
+(define-public python-scikit-learn-1.6
+ (package
+ (inherit python-scikit-learn)
+ (name "python-scikit-learn")
+ (version "1.6.1")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/scikit-learn/scikit-learn")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "08z1b58n31grfvl42wi6rdwrfhrdhnzkkxhg19iag3zkvkcvxqjl"))))
+ (arguments
+ (substitute-keyword-arguments (package-arguments python-scikit-learn)
+ ((#:test-flags flags)
+ #~(list "--numprocesses" (number->string (min 8 (parallel-job-count)))
+ "-m" "not network"
+ "-k" (string-join
+ (list "not test_ard_accuracy_on_easy_problem"
+ "test_check_inplace_ensure_writeable"
+ "test_check_is_fitted_with_attributes"
+ "test_covariance"
+ "test_estimators"
+ "test_ledoit_wolf"
+ "test_mcd"
+ "test_mcd_issue1127"
+ "test_mcd_support_covariance_is_zero"
+ "test_oas"
+ "test_shrunk_covariance"
+ "test_toy_ard_object")
+ " and not ")))
+ ((#:phases phases)
+ #~(modify-phases #$phases
+ (add-after 'unpack 'remove-broken-tests
+ (lambda _
+ ;; ImportError: cannot import name 'ColMajor' from
+ ;; 'sklearn.utils._cython_blas'
+ ;; (<...>/_cython_blas.cpython-311-x86_64-linux-gnu.so)
+ (delete-file-recursively "sklearn/utils/tests/test_cython_blas.py")))))))))
+
(define-public python-scikit-learn-extra
;; This commit fixes an incompatibility with newer versions of scikit-learn
(let ((commit "0f95d8dda4c69f9de4fb002366041adcb1302f3b")
diff --git a/gnu/packages/maths.scm b/gnu/packages/maths.scm
index c0987f699e..ae9e2a2553 100644
--- a/gnu/packages/maths.scm
+++ b/gnu/packages/maths.scm
@@ -2657,7 +2657,7 @@ scientific data storage.")
(define-public n2p2
(package
(name "n2p2")
- (version "2.1.4")
+ (version "2.3.0")
(source (origin
(method git-fetch)
(uri (git-reference
@@ -2666,7 +2666,7 @@ scientific data storage.")
(file-name (git-file-name name version))
(sha256
(base32
- "1lw195ihpxwh08387i4gamk1glhalpq888q6nj8l5vswbgnrv1pq"))))
+ "01090j477gh9zk7wj416fvv1hxdnnxwhzy67bn96a04zhnayzkkj"))))
(build-system gnu-build-system)
(arguments
`(#:make-flags '("MODE=shared" "-C" "src")
@@ -2674,6 +2674,8 @@ scientific data storage.")
(modify-phases %standard-phases
(add-after 'unpack 'post-unpack
(lambda* (#:key inputs #:allow-other-keys)
+ (substitute* "src/makefile"
+ (("shell") "bash"))
(substitute* "src/makefile.gnu"
(("PROJECT_EIGEN=/usr/include/eigen3")
(string-append "PROJECT_EIGEN="
diff --git a/gnu/packages/networking.scm b/gnu/packages/networking.scm
index b31350b145..fb585008c2 100644
--- a/gnu/packages/networking.scm
+++ b/gnu/packages/networking.scm
@@ -977,7 +977,7 @@ publish/subscribe, RPC-style request/reply, or service discovery.")
(define-public nanomsg
(package
(name "nanomsg")
- (version "1.2.1")
+ (version "1.2.2")
(source
(origin
(method git-fetch)
@@ -987,7 +987,7 @@ publish/subscribe, RPC-style request/reply, or service discovery.")
(commit version)))
(file-name (git-file-name name version))
(sha256
- (base32 "0dnnz054czajkdq60z5xw28iiv2qwqhigv9wj54388rk4ak0y3ya"))))
+ (base32 "1vd7kgmljbifa61y6by4ywk4pfxv9kwwcls87iyr32grfyd0v0yl"))))
(build-system cmake-build-system)
(arguments
`(#:configure-flags
@@ -1967,7 +1967,7 @@ of the same name.")
libssh
libxml2
lz4
- lua-5.2
+ lua-5.4
mit-krb5
`(,nghttp2 "lib")
minizip
@@ -2884,7 +2884,7 @@ that block port 22.")
(define-public iperf
(package
(name "iperf")
- (version "3.19")
+ (version "3.19.1")
(source
(origin
(method git-fetch)
@@ -2893,7 +2893,7 @@ that block port 22.")
(commit version)))
(file-name (git-file-name name version))
(sha256
- (base32 "0hddhjzcr6j5sbsb2dllhn4f7pazvh0h3zykalky5m1gnh1virgw"))))
+ (base32 "1kj2p3dprxv1r77whd5g1wak2k71c7khhrkkx60lcnkf70qy5q67"))))
(build-system gnu-build-system)
(arguments
`(#:configure-flags
@@ -3414,7 +3414,7 @@ updates to the zebra daemon.")
(define-public bgpq3
(package
(name "bgpq3")
- (version "0.1.36.1")
+ (version "0.1.38")
(source
(origin
(method git-fetch)
@@ -3423,7 +3423,7 @@ updates to the zebra daemon.")
(commit (string-append "v" version))))
(file-name (git-file-name name version))
(sha256
- (base32 "0768hihx7idmn2dk8ii21m0dm052amlnfpqq53vsfaapb60n1smc"))))
+ (base32 "11zm2z2cxazzr1x6mwmjc167cclkgaah7b1k8pfpfm555bpli9mf"))))
(build-system gnu-build-system)
(arguments
'(#:tests? #f)) ; no test suite
@@ -3770,6 +3770,17 @@ low-level I/O programming that provides developers with a consistent
asynchronous model using a modern C++ approach.")
(license license:boost1.0)))
+(define-public asio-1.28
+ (package/inherit asio
+ (version "1.28.2")
+ (source
+ (origin
+ (method url-fetch)
+ (uri (string-append "mirror://sourceforge/asio/asio/"
+ version " (Stable)/asio-" version ".tar.bz2"))
+ (sha256
+ (base32 "1479z0pa9781dx1crsyaa9fvlcmyhb22m355f8cil77jjh13xf7i"))))))
+
(define-public shadowsocks
(package
(name "shadowsocks")
@@ -4194,7 +4205,7 @@ and targeted primarily for asynchronous processing of HTTP-requests.")
(string-append "extra_link_args=[" args
", '-Wl,-rpath=" #$output "/lib']")))))
;; This is due to an upstream issue:
- ;; https://git.jami.net/savoirfairelinux/opendht/-/issues/69
+ ;; https://git.jami.net/savoirfairelinux/opendht/-/issues/69
(add-after 'unpack 'fix-llhttp-lib-substitution
(lambda _
(substitute* "configure.ac"
diff --git a/gnu/packages/python-science.scm b/gnu/packages/python-science.scm
index 65f385d494..22ee57c4b1 100644
--- a/gnu/packages/python-science.scm
+++ b/gnu/packages/python-science.scm
@@ -318,6 +318,7 @@ possibility to differentiate functions that contain matrix functions as
python-boltons
python-dask
python-distributed
+ python-filelock
python-hatch-vcs
python-hatchling
python-joblib
diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index 1841903e60..f16aff83aa 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -28985,12 +28985,10 @@ tool).")
(list c-blosc lz4 zlib
`(,zstd "lib")))
(propagated-inputs
- (list python-coverage
- python-google-crc32c
+ (list python-google-crc32c
python-importlib-metadata
python-msgpack
- python-numpy
- python-numpydoc))
+ python-numpy))
(native-inputs
(list python-cython
python-py-cpuinfo
@@ -37154,6 +37152,31 @@ other.")
nested data structures in Python like lists and dictionaries.")
(license license:expat)))
+(define-public python-durationpy
+ (package
+ (name "python-durationpy")
+ (version "0.10")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/icholy/durationpy")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "1617wg77j68z7v4rbjrhv6n7bchznhgjn21qrmb034sf4hwg77dl"))))
+ (build-system pyproject-build-system)
+ (arguments
+ (list #:test-backend #~'custom
+ #:test-flags #~(list "test.py")))
+ (native-inputs (list python-setuptools))
+ (home-page "https://github.com/icholy/durationpy")
+ (synopsis "Python <-> Golang time duration formats converter")
+ (description
+ "This package implements a functionality to convert between
+Python's @code{datetime.timedelta} and Golang's @code{time.Duration} formats.")
+ (license license:expat)))
+
(define-public python-murmurhash3
(let ((commit "01f1128a2c5ea08e6dc33515e140bedd68393a2d")
(revision "0"))
@@ -40444,12 +40467,8 @@ and XML respectively. The processing is done through @command{jq},
(propagated-inputs
(list python-asciitree
python-fasteners
- python-ipywidgets
- python-notebook
python-numcodecs
- python-numpy
- python-numpydoc
- python-pydata-sphinx-theme))
+ python-numpy))
(native-inputs
(list python-pytest
python-pytest-xdist
diff --git a/gnu/packages/wm.scm b/gnu/packages/wm.scm
index bc3e55ad70..07cb4e8dfd 100644
--- a/gnu/packages/wm.scm
+++ b/gnu/packages/wm.scm
@@ -3954,7 +3954,7 @@ read and write, and compatible with JSON.")
(define-public labwc
(package
(name "labwc")
- (version "0.9.1")
+ (version "0.9.2")
(source (origin
(method git-fetch)
(uri (git-reference
@@ -3963,7 +3963,7 @@ read and write, and compatible with JSON.")
(file-name (git-file-name name version))
(sha256
(base32
- "0p475vjn9gg314spf89di6i1l2lr9xx59mz4hq4shvbh64hr48pi"))))
+ "1qgjfc9glynpd39qdsdfznmn7ggki1kgxnhi1vlc54ianmpdxa38"))))
(build-system meson-build-system)
(native-inputs
(list pkg-config gettext-minimal scdoc))
diff --git a/gnu/services/cuirass.scm b/gnu/services/cuirass.scm
index 27ff87ca56..e813b7cfdb 100644
--- a/gnu/services/cuirass.scm
+++ b/gnu/services/cuirass.scm
@@ -134,6 +134,28 @@
(web-extra-options cuirass-configuration-web-extra-options
(default '())))
+(define (cuirass-configuration->specification-file config)
+ "Return a specification file built from CONFIG and validate it."
+ (define cuirass
+ (cuirass-configuration-cuirass config))
+
+ (define build
+ #~(begin
+ (use-modules (ice-9 pretty-print))
+
+ (call-with-output-file #$output
+ (lambda (port)
+ (pretty-print '#$(cuirass-configuration-specifications config)
+ port)))
+
+ ;; Validate the spec file upfront.
+ (unless (zero?
+ (system* #$(file-append cuirass "/bin/cuirass") "register"
+ "--check" "-S" #$output))
+ (exit 1))))
+
+ (computed-file "cuirass-specs.scm" build))
+
(define (cuirass-shepherd-service config)
"Return a <shepherd-service> for the Cuirass service with CONFIG."
(define (endpoint name)
@@ -162,9 +184,7 @@
(database (cuirass-configuration-database config))
(port (cuirass-configuration-port config))
(host (cuirass-configuration-host config))
- (config-file (scheme-file
- "cuirass-specs.scm"
- (cuirass-configuration-specifications config)))
+ (config-file (cuirass-configuration->specification-file config))
(one-shot? (cuirass-configuration-one-shot? config))
(fallback? (cuirass-configuration-fallback? config))
(extra-options (cuirass-configuration-extra-options config))
@@ -223,6 +243,9 @@
(list #$(endpoint "bridge")
#$(endpoint "remote-builds"))
+ ;; Start working right away.
+ #:lazy-start? #f
+
#:environment-variables
(list "LC_ALL=C.UTF-8" ;for proper file name decoding
"GIT_SSL_CAINFO=/etc/ssl/certs/ca-certificates.crt"
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index a48214a9c0..f455343c18 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -25,6 +25,7 @@
#include <sys/utsname.h>
#include <fcntl.h>
#include <unistd.h>
+#include <grp.h>
#include <errno.h>
#include <stdio.h>
#include <cstring>
@@ -1646,15 +1647,81 @@ static void initializeUserNamespace(pid_t child,
uid_t hostUID = getuid(),
gid_t hostGID = getgid(),
uid_t guestUID = guestUID,
- gid_t guestGID = guestGID)
+ gid_t guestGID = guestGID,
+ const std::vector<std::pair<gid_t, gid_t>> extraGIDs = {},
+ bool haveCapSetGID = false)
{
writeFile("/proc/" + std::to_string(child) + "/uid_map",
(format("%d %d 1") % guestUID % hostUID).str());
- writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny");
+ if (!haveCapSetGID && !extraGIDs.empty()) {
+ try {
+ Strings args = {
+ std::to_string(child),
+ std::to_string(guestGID), std::to_string(hostGID), "1"
+ };
+ for (auto &pair: extraGIDs) {
+ args.push_back(std::to_string(pair.second));
+ args.push_back(std::to_string(pair.first));
+ args.push_back("1");
+ }
+
+ runProgram("newgidmap", true, args);
+ printMsg(lvlChatty,
+ format("mapped %1% extra GIDs into namespace of PID %2%")
+ % extraGIDs.size() % child);
+
+ return;
+ } catch (const ExecError &e) {
+ ignoreException();
+ }
+ }
+
+ if (!haveCapSetGID)
+ writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny");
+
+ auto content = (format("%d %d 1\n") % guestGID % hostGID).str();
+ if (haveCapSetGID) {
+ for (auto &mapping: extraGIDs) {
+ content += (format("%d %d 1\n") % mapping.second % mapping.first).str();
+ }
+ }
+ writeFile("/proc/" + std::to_string(child) + "/gid_map", content);
+}
+
+/* Maximum number of supplementary groups per user account. */
+static const size_t maxGroups = 64;
+
+/* Return the ID of the "kvm" group or -1 if it does not exist or is not part
+ of the current user's supplementary groups. */
+static gid_t kvmGID()
+{
+ struct group *kvm = getgrnam("kvm");
+ if (kvm == NULL) return -1;
+
+ gid_t groups[maxGroups];
+ int count = getgroups(maxGroups, groups);
+ if (count < 0) return -1;
+
+ for (int i = 0; i < count; i++) {
+ if (groups[i] == kvm->gr_gid) return kvm->gr_gid;
+ }
- writeFile("/proc/" + std::to_string(child) + "/gid_map",
- (format("%d %d 1") % guestGID % hostGID).str());
+ return -1;
+}
+
+/* GID of the "kvm" group in guest user namespaces. */
+static gid_t guestKVMGID = 40000;
+
+static std::vector<std::pair<gid_t, gid_t>> kvmGIDMapping()
+{
+ gid_t kvm = kvmGID();
+ if (kvm == (gid_t) -1)
+ return {};
+ else {
+ std::pair<gid_t, gid_t> mapping(kvm, guestKVMGID);
+ return { mapping };
+ }
}
#if CHROOT_ENABLED
@@ -2931,13 +2998,29 @@ void DerivationGoal::startBuilder()
enableRouteLocalnetAction);
}
+ if ((ctx.cloneFlags & CLONE_NEWUSER) != 0) {
+ /* Have the 'lockMounts' phase re-map supplementary GIDs such as
+ that of the "kvm" group. */
+ ctx.lockMountsMapAll = true;
+ }
+
pid = cloneChild(ctx);
if(childSetupSocket >= 0) childSetupSocket.close();
if ((ctx.cloneFlags & CLONE_NEWUSER) != 0) {
- /* Initialize the UID/GID mapping of the builder. */
- initializeUserNamespace(pid);
+ /* Initialize the UID/GID mapping of the child process.
+
+ Try hard to map the "kvm" GID inside the user namespace ("kvm"
+ is usually the only supplementary group of the 'guix-daemon'
+ privilege separation user) so that package test suites that
+ expect to be able to chown to supplementary groups can do so
+ (without that mapping, attempts to chown to the supplementary
+ group fail with EINVAL). */
+ auto extraGIDs = kvmGIDMapping();
+ initializeUserNamespace(pid,
+ getuid(), getgid(),
+ guestUID, guestGID, extraGIDs);
writeFull(parentSetupSocket, (unsigned char*)"go\n", 3);
}
diff --git a/nix/libutil/spawn.cc b/nix/libutil/spawn.cc
index d3f4e5bf19..7855275494 100644
--- a/nix/libutil/spawn.cc
+++ b/nix/libutil/spawn.cc
@@ -144,19 +144,19 @@ void replacePhase(Phases & phases, string replaceLabel, Action newAction)
/* A curated selection of predefined actions */
-void reset_writeToStderrAction(SpawnContext & ctx)
+static void reset_writeToStderrAction(SpawnContext & ctx)
{
_writeToStderr = 0;
}
-void restoreAffinityAction(SpawnContext & ctx)
+static void restoreAffinityAction(SpawnContext & ctx)
{
restoreAffinity();
}
-void setsidAction(SpawnContext & ctx)
+static void setsidAction(SpawnContext & ctx)
{
/* Puts the current process in a separate session, which implies a
separate process group, so it doesn't receive group-directed signals
@@ -168,7 +168,7 @@ void setsidAction(SpawnContext & ctx)
}
-void earlyIOSetupAction(SpawnContext & ctx)
+static void earlyIOSetupAction(SpawnContext & ctx)
{
for(auto i = ctx.earlyCloseFDs.begin(); i != ctx.earlyCloseFDs.end(); i++)
if(close(*i) == -1)
@@ -198,7 +198,7 @@ void earlyIOSetupAction(SpawnContext & ctx)
}
-void dropAmbientCapabilitiesAction(SpawnContext & ctx)
+static void dropAmbientCapabilitiesAction(SpawnContext & ctx)
{
/* Drop ambient capabilities such as CAP_CHOWN that might have been granted
when starting guix-daemon. */
@@ -211,7 +211,7 @@ void dropAmbientCapabilitiesAction(SpawnContext & ctx)
}
-void chrootAction(SpawnContext & ctx)
+static void chrootAction(SpawnContext & ctx)
{
if(ctx.doChroot)
#if HAVE_CHROOT
@@ -223,7 +223,7 @@ void chrootAction(SpawnContext & ctx)
}
-void chdirAction(SpawnContext & ctx)
+static void chdirAction(SpawnContext & ctx)
{
if(ctx.setcwd)
if(chdir(ctx.cwd.c_str()) == -1)
@@ -231,7 +231,7 @@ void chdirAction(SpawnContext & ctx)
}
-void closeMostFDsAction(SpawnContext & ctx)
+static void closeMostFDsAction(SpawnContext & ctx)
{
if(ctx.closeMostFDs) closeMostFDs(ctx.preserveFDs);
for(auto i = ctx.preserveFDs.begin(); i != ctx.preserveFDs.end(); i++)
@@ -239,7 +239,7 @@ void closeMostFDsAction(SpawnContext & ctx)
}
-void setPersonalityAction(SpawnContext & ctx)
+static void setPersonalityAction(SpawnContext & ctx)
{
if(ctx.setPersona)
#ifdef __linux__
@@ -251,7 +251,7 @@ void setPersonalityAction(SpawnContext & ctx)
}
-void oomSacrificeAction(SpawnContext & ctx)
+static void oomSacrificeAction(SpawnContext & ctx)
{
#ifdef __linux__
if(ctx.oomSacrifice)
@@ -265,7 +265,7 @@ void oomSacrificeAction(SpawnContext & ctx)
}
-void setIDsAction(SpawnContext & ctx)
+static void setIDsAction(SpawnContext & ctx)
{
if(ctx.setSupplementaryGroups)
if(setgroups(ctx.supplementaryGroups.size(),
@@ -285,7 +285,7 @@ void setIDsAction(SpawnContext & ctx)
throw SysError("setuid failed");
}
-void setNoNewPrivsAction(SpawnContext & ctx)
+static void setNoNewPrivsAction(SpawnContext & ctx)
{
if(ctx.setNoNewPrivs)
#if __linux__ && defined(PR_SET_NO_NEW_PRIVS)
@@ -296,7 +296,7 @@ void setNoNewPrivsAction(SpawnContext & ctx)
#endif
}
-void addSeccompFilterAction(SpawnContext & ctx)
+static void addSeccompFilterAction(SpawnContext & ctx)
{
if(ctx.addSeccompFilter) {
#if __linux__ && defined(PR_SET_SECCOMP) && defined(SECCOMP_MODE_FILTER)
@@ -316,7 +316,7 @@ void addSeccompFilterAction(SpawnContext & ctx)
}
-void restoreSIGPIPEAction(SpawnContext & ctx)
+static void restoreSIGPIPEAction(SpawnContext & ctx)
{
/* Restore default handling of SIGPIPE, otherwise some programs will
randomly say "Broken pipe". */
@@ -328,14 +328,14 @@ void restoreSIGPIPEAction(SpawnContext & ctx)
}
-void setupSuccessAction(SpawnContext & ctx)
+static void setupSuccessAction(SpawnContext & ctx)
{
if(ctx.signalSetupSuccess)
writeFull(STDERR_FILENO, "\n");
}
-void execAction(SpawnContext & ctx)
+void execAction(SpawnContext & ctx) // kept public for use in 'build.cc'
{
Strings envStrs;
std::vector<char *> envPtrs;
@@ -378,7 +378,7 @@ Phases getBasicSpawnPhases()
}
-void usernsInitSyncAction(SpawnContext & sctx)
+static void usernsInitSyncAction(SpawnContext & sctx)
{
#if CLONE_ENABLED
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -397,7 +397,7 @@ void usernsInitSyncAction(SpawnContext & sctx)
}
-void usernsSetIDsAction(SpawnContext & sctx)
+static void usernsSetIDsAction(SpawnContext & sctx)
{
#if CLONE_ENABLED
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -420,7 +420,7 @@ void usernsSetIDsAction(SpawnContext & sctx)
}
-void initLoopbackAction(SpawnContext & sctx)
+static void initLoopbackAction(SpawnContext & sctx)
{
#if CLONE_ENABLED
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -440,7 +440,7 @@ void initLoopbackAction(SpawnContext & sctx)
}
-void setHostAndDomainAction(SpawnContext & sctx)
+static void setHostAndDomainAction(SpawnContext & sctx)
{
#if CLONE_ENABLED
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -456,7 +456,7 @@ void setHostAndDomainAction(SpawnContext & sctx)
}
-void makeFilesystemsPrivateAction(SpawnContext & sctx)
+static void makeFilesystemsPrivateAction(SpawnContext & sctx)
{
#if CLONE_ENABLED && HAVE_SYS_MOUNT_H && defined(MS_REC) && defined(MS_PRIVATE)
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -468,7 +468,7 @@ void makeFilesystemsPrivateAction(SpawnContext & sctx)
}
-void makeChrootSeparateFilesystemAction(SpawnContext & sctx)
+static void makeChrootSeparateFilesystemAction(SpawnContext & sctx)
{
#if CLONE_ENABLED && HAVE_SYS_MOUNT_H && defined(MS_BIND)
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -521,7 +521,7 @@ static int statfsToMountFlags(int f_flags)
}
-void bindMount(Path source, Path target, bool readOnly)
+static void bindMount(Path source, Path target, bool readOnly)
{
#if HAVE_SYS_MOUNT_H && defined(MS_BIND)
struct stat st;
@@ -595,9 +595,9 @@ void bindMount(Path source, Path target, bool readOnly)
}
-void mountIntoChroot(std::map<Path, Path> filesInChroot,
- set<Path> readOnlyFiles,
- Path chrootRootDir)
+static void mountIntoChroot(std::map<Path, Path> filesInChroot,
+ set<Path> readOnlyFiles,
+ Path chrootRootDir)
{
#if HAVE_SYS_MOUNT_H && defined(MS_BIND)
for(auto i = filesInChroot.begin(); i != filesInChroot.end(); i++) {
@@ -612,7 +612,7 @@ void mountIntoChroot(std::map<Path, Path> filesInChroot,
}
-void mountIntoChrootAction(SpawnContext & sctx)
+static void mountIntoChrootAction(SpawnContext & sctx)
{
#if CLONE_ENABLED && HAVE_SYS_MOUNT_H && defined(MS_BIND)
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -623,7 +623,7 @@ void mountIntoChrootAction(SpawnContext & sctx)
}
-void mountProcAction(SpawnContext & sctx)
+static void mountProcAction(SpawnContext & sctx)
{
#if CLONE_ENABLED && HAVE_SYS_MOUNT_H
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -637,7 +637,7 @@ void mountProcAction(SpawnContext & sctx)
}
-void mountDevshmAction(SpawnContext & sctx)
+static void mountDevshmAction(SpawnContext & sctx)
{
#if CLONE_ENABLED && HAVE_SYS_MOUNT_H
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -651,7 +651,7 @@ void mountDevshmAction(SpawnContext & sctx)
}
-void mountDevptsAction(SpawnContext & sctx)
+static void mountDevptsAction(SpawnContext & sctx)
{
#if CLONE_ENABLED && HAVE_SYS_MOUNT_H
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -673,7 +673,7 @@ void mountDevptsAction(SpawnContext & sctx)
}
-void pivotRootAction(SpawnContext & sctx)
+static void pivotRootAction(SpawnContext & sctx)
{
#if CLONE_ENABLED && HAVE_SYS_MOUNT_H
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -700,7 +700,7 @@ void pivotRootAction(SpawnContext & sctx)
}
-string idMapToIdentityMap(const string & map)
+static string idMapToIdentityMap(const string & map)
{
std::vector<string> mapLines =
tokenizeString<std::vector<string> >(map, "\n");
@@ -720,7 +720,7 @@ string idMapToIdentityMap(const string & map)
* processes in it after unshare is called. So fork a child and have it do
* the initialization. */
void unshareAndInitUserns(int flags, const string & uidMap,
- const string & gidMap, bool allowSetgroups)
+ const string & gidMap, bool allowSetgroups)
{
#if CLONE_ENABLED
pid_t pid_ = getpid();
@@ -767,7 +767,7 @@ void unshareAndInitUserns(int flags, const string & uidMap,
}
-void lockMountsAction(SpawnContext & sctx)
+static void lockMountsAction(SpawnContext & sctx)
{
#if CLONE_ENABLED && HAVE_SYS_MOUNT_H
CloneSpawnContext & ctx = (CloneSpawnContext &) sctx;
@@ -868,7 +868,7 @@ void runChildSetup(SpawnContext & ctx)
}
-int runChildSetupEntry(void *data)
+static int runChildSetupEntry(void *data)
{
runChildSetup(* (SpawnContext *)data);
return 1;
diff --git a/nix/libutil/spawn.hh b/nix/libutil/spawn.hh
index 5e75bcfb09..ac6f0d1c41 100644
--- a/nix/libutil/spawn.hh
+++ b/nix/libutil/spawn.hh
@@ -115,48 +115,13 @@ void deletePhase(Phases & phases, string delLabel);
void replacePhase(Phases & phases, string replaceLabel, Action newAction);
-Action reset_writeToStderrAction;
-Action restoreAffinityAction;
-Action setsidAction;
-Action earlyIOSetupAction;
-Action dropAmbientCapabilitiesAction;
-Action chrootAction;
-Action chdirAction;
-Action closeMostFDsAction;
-Action setPersonalityAction;
-Action oomSacrificeAction;
-Action setIDsAction;
-Action setNoNewPrivsAction;
-Action addSeccompFilterAction;
-Action restoreSIGPIPEAction;
-Action setupSuccessAction;
-Action execAction;
+Action execAction; // used from 'build.cc'
Phases getBasicSpawnPhases();
-
-void bindMount(Path source, Path target, bool readOnly);
-
-void mountIntoChroot(std::map<Path, Path> filesInChroot,
- set<Path> readOnlyFiles,
- Path chrootRootDir);
-
-Action usernsInitSyncAction;
-Action usernsSetIDsAction;
-Action initLoopbackAction;
-Action setHostAndDomainAction;
-Action makeFilesystemsPrivateAction;
-Action makeChrootSeparateFilesystemAction;
-Action mountIntoChrootAction;
-Action mountProcAction;
-Action mountDevshmAction;
-Action mountDevptsAction;
-Action pivotRootAction;
-Action lockMountsAction;
-
Phases getCloneSpawnPhases();
/* Helpers */
-string idMapToIdentityMap(const string & map);
+
void unshareAndInitUserns(int flags, const string & uidMap,
const string & gidMap, bool allowSetgroups);
@@ -164,10 +129,6 @@ void unshareAndInitUserns(int flags, const string & uidMap,
* exiting in all cases. */
void runChildSetup(SpawnContext & ctx);
-/* Helper to call runChildSetup that can be passed to the variant of clone
- * that expects a callback. */
-int runChildSetupEntry(void *data);
-
/* Create a new process using clone that will immediately call runChildSetup
* with the provided CloneSpawnContext. Return the pid of the new process. */
int cloneChild(CloneSpawnContext & ctx);
diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc
index 9a97270af9..77f2547b0a 100644
--- a/nix/libutil/util.cc
+++ b/nix/libutil/util.cc
@@ -1193,7 +1193,9 @@ string runProgram(Path program, bool searchPath, const Strings & args)
else
execv(program.c_str(), stringsToCharPtrs(args_).data());
- throw SysError(format("executing `%1%'") % program);
+ int err = errno;
+ printMsg(lvlError, format("executing `%1%': %2%") % program % strerror(err));
+ _exit(127);
});
pipe.writeSide.close();
diff --git a/tests/store.scm b/tests/store.scm
index 16dcbf2396..82fb7a96ce 100644
--- a/tests/store.scm
+++ b/tests/store.scm
@@ -476,6 +476,29 @@
(build-derivations %store (list d))
(call-with-input-file (derivation->output-path d) read)))
+(unless (and (unprivileged-user-namespace-supported?)
+ (false-if-exception
+ (= (stat:gid (stat "/dev/kvm"))
+ (group:gid (getgrnam "kvm"))))
+ (= 1 (status:exit-val (system* "newgidmap"))))
+ (test-skip 1))
+(test-assert "kvm GID is mapped"
+ ;; Ensure that the "kvm" GID is mapped into the build user namespace such
+ ;; that chown'ing a file to that GID works as expected. See
+ ;; <https://issues.guix.gnu.org/77862>.
+ (let ((d (build-expression->derivation
+ %store "chown-to-supplementary-group"
+ `(let ((st (stat "/dev/kvm")))
+ ',(gettimeofday)
+ (pk 'supplementary-groups (getgroups))
+ (pk 'kvm-group (stat:gid st))
+ (unless (member (stat:gid st) (vector->list (getgroups)))
+ (error "supplementary groups lack 'kvm' GID"))
+ (mkdir "test")
+ (chown "test" (getuid) (stat:gid st))
+ (mkdir %output)))))
+ (build-derivations %store (list d))))
+
(unless (unprivileged-user-namespace-supported?)
(test-skip 1))
(test-equal "inputs are read-only"