From d000539ca2ea40ca734a2ea41503223e4ef88e29 Mon Sep 17 00:00:00 2001 From: Eric Zhang Date: Thu, 10 Jul 2025 11:27:38 -0700 Subject: [PATCH] Follow symlinks in MkdirAllAt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See #11910 for details — this potentially fixes a divergence between gVisor and runc behavior where having the `cwd` of the OCI container spec set to a symlink to a folder causes gVisor to exit with this error: ``` running container: starting container: starting root container: starting sandbox: failed to create process working directory "/cwd-folder-name-here": not a directory ``` FUTURE_COPYBARA_INTEGRATE_REVIEW=https://github.com/google/gvisor/pull/11911 from ekzhang:patch-1 3f7bca1ae53c122fd560384fa49a70f4441bd4e4 PiperOrigin-RevId: 781612832 --- pkg/sentry/vfs/vfs.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/sentry/vfs/vfs.go b/pkg/sentry/vfs/vfs.go index 0727c46f9e..f2274183c0 100644 --- a/pkg/sentry/vfs/vfs.go +++ b/pkg/sentry/vfs/vfs.go @@ -878,7 +878,16 @@ func (vfs *VirtualFilesystem) MkdirAllAt(ctx context.Context, currentPath string Start: root, Path: fspath.Parse(currentPath), } + + // For the StatAt() operation, we follow final symlinks so that we don't + // produce errors when the final component is a symlink to a directory. + // + // However, keep the old pop unchanged when passing to MkdirAt() below + // because MkdirAt() must not follow the final symlink. This is enforced + // by preconditions of FilesystemImpl.MkdirAt(). + pop.FollowFinalSymlink = true stat, err := vfs.StatAt(ctx, creds, pop, &StatOptions{Mask: linux.STATX_TYPE}) + pop.FollowFinalSymlink = false switch { case err == nil: if mustBeDir && (stat.Mask&linux.STATX_TYPE == 0 || stat.Mode&linux.FileTypeMask != linux.ModeDirectory) {