deploy: NoNewPrivileges=no so rootless podman can start !304

merged merged by cmc on 2026-09-06 23:34 UTC · krz/gitbay:runner-nonewprivs into main

3 files changed, +32 −4

Layout: unified · split

.gitbay/wiki/Admin.org +5
@@ -449,6 +449,11 @@ The script installs podman, delegates a subuid/subgid range to
449449assuming, enables lingering, and verifies rootless podman actually runs
450450as that user. It is idempotent.
451451
452The drop-in sets =NoNewPrivileges=no=, without which rootless podman
453cannot call =newuidmap= and the runner refuses to start. That is a
454considered trade, explained in the file and in the Threat-Model; if you
455run with =-isolation none=, set it back to =yes=.
456
452457*Do not deploy an isolating runner to a host that has not been
453458prepared.* The runner is specified to refuse to start without a working
454459podman rather than fall back to running builds unsandboxed — a fallback
.gitbay/wiki/Threat-Model.org +9 −3
@@ -145,9 +145,15 @@ runner, polling over SSH, clones the commit and runs its steps.
145145 repository is trusted; there is no automatic fallback to it — a runner
146146 configured for podman that cannot find one refuses to start, because
147147 dropping isolation silently is worse than a stopped runner. The
148 systemd drop-in still adds =NoNewPrivileges=, =ProtectSystem=full= and
149 the kernel and cgroup protections, and =-repos= still limits a runner
150 to named repositories.
148 systemd drop-in still adds =ProtectSystem=full= and the kernel and
149 cgroup protections, and =-repos= still limits a runner to named
150 repositories. =NoNewPrivileges= is *off*: rootless podman sets up its
151 namespace with the setuid =newuidmap=, which that flag blocks, so the
152 choice is between it and containers at all. Containers are the stronger
153 boundary — the flag constrained a process that was already running
154 arbitrary repository code, and under podman that code no longer runs in
155 the runner's process context. Under =-isolation none= there is no
156 container and the flag should be on.
151157
152158Under =-isolation none=, anything a step can do as the runner's user a
153159pushed =ci.yml= can do. Under podman a step is confined to its
deploy/gitbay-runner.override.conf +18 −1
@@ -30,7 +30,24 @@
3030Nice=10
3131CPUWeight=30
3232IOWeight=30
33NoNewPrivileges=yes
33# NoNewPrivileges is off, and that is a deliberate trade (#144).
34#
35# Rootless podman sets up its user namespace with newuidmap, a setuid
36# helper; NoNewPrivileges=yes blocks it and podman fails with
37# "newuidmap: write to uid_map failed: Operation not permitted", so the
38# runner refuses to start. The choice is between this flag and running
39# builds in containers at all.
40#
41# Containers are the stronger boundary by a wide margin. NoNewPrivileges
42# constrained a process that was already executing arbitrary repository
43# code as this user; a container confines that code to an image and a
44# bind-mounted workspace. What is lost is one hardening layer on the
45# runner process itself, which is ours rather than a build's — a build no
46# longer runs in this process's context at all.
47#
48# Under -isolation none there is no container, and this flag should be
49# yes. Set it back if you run that way.
50NoNewPrivileges=no
3451ProtectSystem=full
3552ProtectKernelTunables=yes
3653ProtectControlGroups=yes