From 254fedb1d69c02162b19c65219243098eeac0b1b Mon Sep 17 00:00:00 2001 From: Rahat Mahmood Date: Wed, 2 Nov 2022 09:41:49 -0700 Subject: [PATCH] tmpfs: Handle symlink resolution at root Previously we weren't resolving any links when walking a single component path (i.e. the root of the FS was a symlink). PiperOrigin-RevId: 485618692 --- pkg/sentry/fsimpl/tmpfs/filesystem.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/pkg/sentry/fsimpl/tmpfs/filesystem.go b/pkg/sentry/fsimpl/tmpfs/filesystem.go index fc8c6efac..fb398f499 100644 --- a/pkg/sentry/fsimpl/tmpfs/filesystem.go +++ b/pkg/sentry/fsimpl/tmpfs/filesystem.go @@ -133,13 +133,27 @@ func walkParentDirLocked(ctx context.Context, rp *vfs.ResolvingPath, d *dentry) // Preconditions: filesystem.mu must be locked. func resolveLocked(ctx context.Context, rp *vfs.ResolvingPath) (*dentry, error) { d := rp.Start().Impl().(*dentry) - for !rp.Done() { - next, err := stepLocked(ctx, rp, d) - if err != nil { + + if symlink, ok := d.inode.impl.(*symlink); rp.Done() && ok && rp.ShouldFollowSymlink() { + // Path with a single component. We don't need to step to the next + // component, but still need to resolve any symlinks. + // + // Symlink traversal updates access time. + d.inode.touchAtime(rp.Mount()) + if err := rp.HandleSymlink(symlink.target); err != nil { return nil, err } - d = next + } else { + // Path with multiple components, walk and resolve as required. + for !rp.Done() { + next, err := stepLocked(ctx, rp, d) + if err != nil { + return nil, err + } + d = next + } } + if rp.MustBeDir() && !d.inode.isDir() { return nil, linuxerr.ENOTDIR }