diff options
-rwxr-xr-x | etc/guix-install.sh | 12 | ||||
-rw-r--r-- | gnu/packages/admin.scm | 4 | ||||
-rw-r--r-- | gnu/packages/audio.scm | 2 | ||||
-rw-r--r-- | gnu/packages/bioinformatics.scm | 29 | ||||
-rw-r--r-- | gnu/packages/fediverse.scm | 4 | ||||
-rw-r--r-- | gnu/packages/guile-xyz.scm | 4 | ||||
-rw-r--r-- | gnu/packages/machine-learning.scm | 43 | ||||
-rw-r--r-- | gnu/packages/maths.scm | 6 | ||||
-rw-r--r-- | gnu/packages/networking.scm | 27 | ||||
-rw-r--r-- | gnu/packages/python-science.scm | 1 | ||||
-rw-r--r-- | gnu/packages/python-xyz.scm | 37 | ||||
-rw-r--r-- | gnu/packages/wm.scm | 4 | ||||
-rw-r--r-- | gnu/services/cuirass.scm | 29 | ||||
-rw-r--r-- | nix/libstore/build.cc | 95 | ||||
-rw-r--r-- | nix/libutil/spawn.cc | 70 | ||||
-rw-r--r-- | nix/libutil/spawn.hh | 43 | ||||
-rw-r--r-- | nix/libutil/util.cc | 4 | ||||
-rw-r--r-- | tests/store.scm | 23 |
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" |