diff options
| author | Giacomo Leidi <therewasa@fishinthecalculator.me> | 2026-06-07 23:45:09 +0200 |
|---|---|---|
| committer | Giacomo Leidi <therewasa@fishinthecalculator.me> | 2026-06-15 11:38:46 +0200 |
| commit | 518129e1130f6cc6e128af0729d678e94b7dfefd (patch) | |
| tree | 4fbfbc76fc6348c753802c2dcd6a4b5c7e7fbefc /gnu/build | |
| parent | 1fa2e6739e6d37d5b4234dc065222c29309a1da8 (diff) | |
linux-container: Remount / recursively as MS_PRIVATE, immediately after entering the new mount namespace.
Apply the same workaround that runc, crun, and buildah apply
unconditionally: immediately after entering the new mount namespace,
remount / recursively as MS_PRIVATE. Concretely, the call we will
make in Guile mirrors the verbatim C call already present in crun at
https://github.com/containers/crun/blob/99a8512ef50c5af1b8cfff28eacddf870220ca9f/src/libcrun/linux.c#L4677:
ret = mount (NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL);
and the Go equivalents in:
- runc (defaults to MS_SLAVE for reasons documented in its pivotRoot):
https://github.com/opencontainers/runc/blob/a7e766484c38be1f0cf9b7d960c9324316cb7204/libcontainer/rootfs_linux.go#L1106
- buildah (expands to mount("", "/", "none", MS_REC|MS_PRIVATE, "")):
https://github.com/podman-container-tools/buildah/blob/769d311d739dd4bbde496a9480879ce6aadaa1e0/bind/mount.go#L41
Our implementation:
1. Detaches the container's mount namespace from the host's propagation
peer group, so subsequent mount/umount events inside the container
do not propagate to the host.
2. Makes the kernel's pivot_root(2) preconditions satisfied: both
new_root (the tmpfs we then create) and its parent (/) have propagation
type MS_PRIVATE.
3. Should have no effect on processes outside the new mount namespace. The
host's / retains whatever propagation type it had.
mount-file-systems is only invoked from run-container when both
'mnt namespace is requested and root != "/", so we are
guaranteed to be inside a fresh mount namespace at this point and that
the remount only affects this namespace. The remount must happen before
the tmpfs is created. Once the tmpfs exists as a child of the (shared)
host /, fixing only the host / does not retroactively change the
propagation type the tmpfs already inherited. Doing the remount first
means every subsequent mount this function performs inherits MS_PRIVATE
from its parent.
* guix/build/syscalls.scm (MS_PRIVATE): New variable.
* gnu/build/linux-container.scm (mount-file-systems): Remount / recursively as MS_PRIVATE, immediately after entering the new mount namespace.
* gnu/services/containers.scm (%miniflux-create-admin-credentials,
%rootless-podman-os-with-least-authority-wrapper,
run-rootless-podman-test-with-least-authority-wrapper): New bindings.
(%test-rootless-podman-with-least-authority-wrapper): New regression
test making sure the rootless-podman-service-type does not break again
least-authority-wrapper bases services.
Fixes: https://codeberg.org/guix/guix/issues/3233
Merges: https://codeberg.org/guix/guix/pulls/9140
Diffstat (limited to 'gnu/build')
| -rw-r--r-- | gnu/build/linux-container.scm | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/gnu/build/linux-container.scm b/gnu/build/linux-container.scm index bc1f8851dd2..32990f4dac5 100644 --- a/gnu/build/linux-container.scm +++ b/gnu/build/linux-container.scm | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2015 David Thompson <davet@gnu.org> | 2 | ;;; Copyright © 2015 David Thompson <davet@gnu.org> |
| 3 | ;;; Copyright © 2017-2019, 2022-2023, 2025 Ludovic Courtès <ludo@gnu.org> | 3 | ;;; Copyright © 2017-2019, 2022-2023, 2025 Ludovic Courtès <ludo@gnu.org> |
| 4 | ;;; Copyright © 2026 Giacomo Leidi <therewasa@fishinthecalculator.me> | ||
| 4 | ;;; | 5 | ;;; |
| 5 | ;;; This file is part of GNU Guix. | 6 | ;;; This file is part of GNU Guix. |
| 6 | ;;; | 7 | ;;; |
| @@ -104,6 +105,16 @@ for the process." | |||
| 104 | (mkdir-p target) | 105 | (mkdir-p target) |
| 105 | (mount source target type flags options #:update-mtab? update-mtab?)) | 106 | (mount source target type flags options #:update-mtab? update-mtab?)) |
| 106 | 107 | ||
| 108 | ;; Detach our mount namespace from the host's propagation peer | ||
| 109 | ;; group. Without this, when the host's / is MS_SHARED - as it | ||
| 110 | ;; is on a system running rootless-podman-service-type, and as it | ||
| 111 | ;; is by default on systemd hosts - 'pivot_root' below fails | ||
| 112 | ;; with EINVAL because the new root and its parent must not have | ||
| 113 | ;; propagation type MS_SHARED (pivot_root(2)). This is the same | ||
| 114 | ;; remount that runc, crun and buildah perform immediately after | ||
| 115 | ;; unshare(CLONE_NEWNS). | ||
| 116 | (mount #f "/" #f (logior MS_REC MS_PRIVATE)) | ||
| 117 | |||
| 107 | ;; The container's file system is completely ephemeral, sans directories | 118 | ;; The container's file system is completely ephemeral, sans directories |
| 108 | ;; bind-mounted from the host. | 119 | ;; bind-mounted from the host. |
| 109 | (mount "none" root "tmpfs") | 120 | (mount "none" root "tmpfs") |
