From 340e05cb280aa7fb187b736f97175cc8947a8f3b Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Tue, 14 Apr 2026 17:17:36 +0200 Subject: [PATCH] fix failure to start container with networking enabled Signed-off-by: Nicolas De Loof --- docs/vm-configuration.md | 2 +- internal/shim/task/ctrnetworking.go | 5 ++++- internal/shim/task/mount.go | 14 +++++++++++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/vm-configuration.md b/docs/vm-configuration.md index ae30060..ef5343c 100644 --- a/docs/vm-configuration.md +++ b/docs/vm-configuration.md @@ -74,7 +74,7 @@ You must build it from source following the instructions set in that repository. ``` (terminal 1) $ bin/gvproxy -debug -listen unix:///tmp/network.sock -listen-vfkit unixgram:///tmp/gvisor.sock (terminal 2) $ ctr run -t --net-host --cap-add CAP_NET_ADMIN --rm --snapshotter erofs --runtime io.containerd.nerdbox.v1 \ - --annotation io.containerd.nerdbox.network.0=socket=/tmp/gvisor.sock,mode=unixgram,mac=fa:43:25:5d:6f:b4,addr=192.168.127.2 \ + --annotation io.containerd.nerdbox.network.0=socket=/tmp/gvisor.sock,mode=unixgram,mac=fa:43:25:5d:6f:b4,addr=192.168.127.2/16 \ docker.io/nicolaka/netshoot:latest test ``` diff --git a/internal/shim/task/ctrnetworking.go b/internal/shim/task/ctrnetworking.go index 827684b..5f391b0 100644 --- a/internal/shim/task/ctrnetworking.go +++ b/internal/shim/task/ctrnetworking.go @@ -187,8 +187,11 @@ func addResolvConf(ctx context.Context, b *bundle.Bundle, fallbackToHostRC bool) _, _ = rcBuf.WriteRune('\n') } rcBytes = rcBuf.Bytes() - } else if fallbackToHostRC { + } else { // Try giving the VM a copy of the host's resolv.conf. + // This is always attempted (not only as a fallback) because on some + // platforms (e.g., macOS) the host path /etc/resolv.conf may contain + // symlinks that prevent it from being shared via virtiofs. if c, err := os.ReadFile("/etc/resolv.conf"); err == nil { rcBytes = c } diff --git a/internal/shim/task/mount.go b/internal/shim/task/mount.go index 16bf42a..85019dc 100644 --- a/internal/shim/task/mount.go +++ b/internal/shim/task/mount.go @@ -230,16 +230,24 @@ func (bm *bindMounter) FromBundle(ctx context.Context, b *bundle.Bundle) error { tag := fmt.Sprintf("bind-%x", hash[:8]) vmTarget := "/mnt/" + tag + // Resolve symlinks in the source path because libkrun opens shared + // directories with O_NOFOLLOW, which rejects symlinks + // (e.g., /etc -> /private/etc and /etc/resolv.conf -> ../var/run/resolv.conf on macOS). + resolvedSource, err := filepath.EvalSymlinks(m.Source) + if err != nil { + return fmt.Errorf("failed to resolve symlinks for bind mount source %s: %w", m.Source, err) + } + // For files, share the parent directory via virtiofs since virtiofs // operates on directories. The spec source points to the file within // the mounted directory. - hostSrc := m.Source + hostSrc := resolvedSource specSrc := vmTarget if !fi.IsDir() { - hostSrc = filepath.Dir(m.Source) + hostSrc = filepath.Dir(resolvedSource) // Use path.Join (not filepath.Join) because this path is used // inside the Linux VM where forward slashes are required. - specSrc = path.Join(vmTarget, filepath.Base(m.Source)) + specSrc = path.Join(vmTarget, filepath.Base(resolvedSource)) } transformed := bindMount{