Skip to content

Fix/bind mounts type none - #1150

Open
cmainas wants to merge 3 commits into
mainfrom
fix/bind_mounts_type_none
Open

cmainas wants to merge 3 commits into
mainfrom
fix/bind_mounts_type_none

Conversation

@cmainas

@cmainas cmainas commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Description

containerd and nerdctl spell volumes as {"type": "none", "options": ["rbind", ...]}.urunc only accepted type: "bind", so such volumes never reached the guest.

  • Recognise bind mounts by their options. isBindMount now follows the OCI runtime spec and runc: a mount is a bind mount if its options include bind or rbind,regardless of its type. A mount with type: "bind" but no such option is dropped, so the e2e ctr helper now passes options=rbind.
  • Keep host kernel filesystems out of the mounted paths: Rootless runtimes replace the sysfs mount with an rbind of the host's /sys, which would otherwise end up in the virtiofs/9p share. onlyBindMounts skips, with a warning, bind mounts whose source is on sysfs, procfs, cgroupfs or another kernel filesystem, for every rootfs type.
  • Copy only regular files into a block rootfs. Sockets, FIFOs and device nodes used to break container creation and are now skipped, as directories already were.

At last, a bind mount whose source does not exist now fails container creation for every rootfs type.

Related issues

How was this tested?

With e2e tests

LLM usage

Opus 5.5

Checklist

  • I have read the contribution guide.
  • The linter passes locally (make lint).
  • The e2e tests of at least one tool pass locally (make test_ctr, make test_nerdctl, make test_docker, make test_crictl).
  • If LLMs were used: I have read the llm policy.

An OCI mount is a bind mount when its options include "bind" or
"rbind"; its Type is then a dummy that runtimes such as runc ignore.
Docker sets it to "bind", but containerd and nerdctl emit volumes
(`nerdctl run -v host:/data`) with Type "none". urunc only checked for
Type "bind", so such volumes were dropped everywhere bind mounts are
filtered: they never reached the shared rootfs of a virtiofs/9p guest,
were not copied into a block rootfs or an initrd, and were not
remounted with their VFS flags.

Add isBindMount, which follows the runtime spec and looks only at the
options, and use it in every such check (mount application, shared-fs
and block filtering). The initrd package no longer filters mounts
itself; its caller passes it only the bind mounts.

Also a mount spelled only by its Type, e.g. Type "bind" without a bind
option, is not a bind mount and is dropped like other unsupported
mounts, so make the e2e ctr helper pass the rbind option that `ctr
--mount type=bind` omits.

Signed-off-by: Charalampos Mainas <charalampos.mainas@gmail.com>
Rootless runtimes replace the container's sysfs mount with an rbind of
the host's /sys, e.g. with --net=host, since they cannot mount a fresh
sysfs. Now that such Type "none" binds are recognised, this mount would
end up in the rootfs shared with a virtiofs/9p guest, exposing the
host's sysfs to it and, through the file server, letting the guest
write host kernel knobs. On the block and initrd paths, single-file
binds from /proc or /sys would also copy host state into the guest.

Add onlyBindMounts as the single place that selects the spec mounts
passed to the guest: the bind mounts, minus those whose source resides
on a host kernel filesystem (sysfs, procfs, cgroupfs, securityfs,
debugfs, tracefs, bpffs, efivarfs, pstore, binfmt_misc and nsfs),
detected through statfs. Skipped mounts are logged. Use it for the
shared-fs, initrd and block (file copies and volumes) paths. The guest
has its own kernel and its own instances of these filesystems.

A bind mount whose source cannot be statfs'd, e.g. because it does not
exist, now fails container creation on every path.

Signed-off-by: Charalampos Mainas <charalampos.mainas@gmail.com>
For a block rootfs, copyMountfiles copies the source of each bind mount
into the rootfs with fileFromHost, which only refused directories. Any
other special file broke container creation: opening a socket fails,
opening a FIFO blocks forever and reading a device such as /dev/urandom
never ends, filling the rootfs.

Replace ErrCopyDir with ErrNotRegularFile, which fileFromHost returns
for anything that is not a regular file, before opening it, and skip
such mounts in copyMountfiles as directories already were. This matches
the initrd path, which already copies only regular files.

Signed-off-by: Charalampos Mainas <charalampos.mainas@gmail.com>
@netlify

netlify Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for urunc ready!

Name Link
🔨 Latest commit d3251f1
🔍 Latest deploy log https://app.netlify.com/projects/urunc/deploys/6adfbe35899ec40e19d414c8
😎 Deploy Preview https://deploy-preview-1150--urunc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@cmainas
cmainas force-pushed the fix/bind_mounts_type_none branch 3 times, most recently from d139be7 to d3251f1 Compare October 26, 2026 20:55
@cmainas
cmainas marked this pull request as ready for review October 27, 2026 12:55
@cmainas
cmainas requested a review from ananos October 27, 2026 12:55

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bind mounts with type: none are ignored

1 participant