rshared propagation (bind mount options and rootfsPropagation) silently results in private mounts; Kubernetes mountPropagation=Bidirectional inert (runc 1.4.2)
Description
With an OCI spec that requests rshared propagation — both as the option on bind mounts in spec.mounts and as linux.rootfsPropagation — the resulting container gets those mounts (and its rootfs) with no propagation peer groups at all: no shared: or master: optional fields in the container's /proc/self/mountinfo, i.e. fully private. Propagation is functionally dead in both directions for mounts created after container start: a filesystem mounted inside the container under an rshared bind never appears in the host's mount namespace.
The practical impact is that Kubernetes mountPropagation: Bidirectional (the CSI node-plugin pattern) silently does nothing: the kubelet and containerd both do their part (CRI reports PROPAGATION_BIDIRECTIONAL, the generated OCI spec carries rshared + rootfsPropagation: rshared), and the container still cannot expose a mount to the host. Nothing errors — the mounts are just private.
This looks like the rshared sibling of #5192 (fixed by #5200): same prepareRootfs make-private-then-restore area, but #5192/#5200 addressed the rslave/HostToContainer restore. In our capture on runc 1.4.2, the rshared case is broken too, and more broadly than the rootfs: the individual rshared bind mounts also come out private. I can't tell from #5200 whether its backports (labeled for release-1.4/1.5) also cover this path — if they do, treat this as a confirmation report with a reproducible environment.
Steps to reproduce
On a k3s v1.36.2+k3s1 node (containerd v2.3.2-k3s2, bundled runc 1.4.2), a privileged pod with:
volumeMounts:
- name: cache
mountPath: /srv/buildkit
mountPropagation: Bidirectional
volumes:
- name: cache
persistentVolumeClaim:
claimName: buildkit-cache # static PV, hostPath /srv/buildkit
securityContext:
privileged: truecrictl inspect <cid>— CRI level is correct:
"containerPath": "/srv/buildkit", "propagation": "PROPAGATION_BIDIRECTIONAL"- The generated OCI runtime spec is correct:
{
"destination": "/srv/buildkit",
"options": ["rbind", "rshared", "rw"],
"source": "/srv/buildkit",
"type": "bind"
}with "rootfsPropagation": "rshared" in linux.
- Inside the running container,
/proc/self/mountinfo:
202 200 0:106 / / rw,relatime - overlay overlay rw,lowerdir=...
375 202 8:1 /srv/buildkit /srv/buildkit rw,relatime - ext4 /dev/sda1 rwNo optional fields on either line — the rootfs and the bind are private, despite both rshared requests. (On the host, / is shared:1, systemd default; the source path is on the root fs.)
- Functional probe: inside the container,
mkdir /srv/buildkit/proptest && mount -t tmpfs proptest /srv/buildkit/proptest. The mount appears in the container's mountinfo and never appears in the host's mount namespace (findmnt /srv/buildkit/propteston the host: nothing).
Expected behavior
The bind mount at /srv/buildkit is a member of the host's peer group (shared:1 in the container's mountinfo), and the tmpfs mounted under it inside the container propagates to the host — Kubernetes Bidirectional semantics.
Environment
- runc 1.4.2 (
runc version 1.4.2, commit: v1.4.2-0-gc241c0b, spec: 1.3.0, libseccomp: 2.6.0), as bundled in k3s v1.36.2+k3s1 - containerd v2.3.2-k3s2, runtime
io.containerd.runc.v2 - k3s v1.36.2+k3s1 (kubelet + containerd in host namespaces; host
/isshared:1) - Ubuntu 24.04.4 LTS, kernel 6.8.0-136-generic, x86_64
- No user namespaces; container is privileged
Caveat stated plainly: this was captured through the containerd/CRI stack on k3s, not with standalone runc run; the spec excerpts above are containerd's generated config.json, so runc received the rshared requests. Happy to gather more state from this environment or test a patched runc.
Discovered while diagnosing why a buildkitd pod's mounts never reached the host shim (moby/buildkit#4787 territory); full investigation trail with the raw captures: https://github.com/beeekind/infrastructure/issues/478#issuecomment-5223318251
Source: opencontainers/runc