diff options
author | Jamie Liu <jamieliu@google.com> | 2021-02-11 19:08:18 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-02-11 19:10:22 -0800 |
commit | 34614c39860a7316132a2bf572366618e7a78be9 (patch) | |
tree | 65d2a5d74acb316d0f5d60173e957643a6dd2562 | |
parent | 91cf7b3ca48b9388c9058962ffe798c37e951990 (diff) |
Unconditionally check for directory-ness in overlay.filesystem.UnlinkAt().
PiperOrigin-RevId: 357106080
-rw-r--r-- | pkg/sentry/fsimpl/overlay/filesystem.go | 64 |
1 files changed, 19 insertions, 45 deletions
diff --git a/pkg/sentry/fsimpl/overlay/filesystem.go b/pkg/sentry/fsimpl/overlay/filesystem.go index b36031291..890b01cdb 100644 --- a/pkg/sentry/fsimpl/overlay/filesystem.go +++ b/pkg/sentry/fsimpl/overlay/filesystem.go @@ -1308,8 +1308,8 @@ func (fs *filesystem) RmdirAt(ctx context.Context, rp *vfs.ResolvingPath) error return err } - // Unlike UnlinkAt, we need a dentry representing the child directory being - // removed in order to verify that it's empty. + // We need a dentry representing the child directory being removed in order + // to verify that it's empty. child, _, err := fs.getChildLocked(ctx, parent, name, &ds) if err != nil { return err @@ -1555,50 +1555,24 @@ func (fs *filesystem) UnlinkAt(ctx context.Context, rp *vfs.ResolvingPath) error return err } - parentMode := atomic.LoadUint32(&parent.mode) - child := parent.children[name] - var childLayer lookupLayer - if child == nil { - if parentMode&linux.S_ISVTX != 0 { - // If the parent's sticky bit is set, we need a child dentry to get - // its owner. - child, _, err = fs.getChildLocked(ctx, parent, name, &ds) - if err != nil { - return err - } - } else { - // Determine if the file being unlinked actually exists. Holding - // parent.dirMu prevents a dentry from being instantiated for the file, - // which in turn prevents it from being copied-up, so this result is - // stable. - childLayer, err = fs.lookupLayerLocked(ctx, parent, name) - if err != nil { - return err - } - if !childLayer.existsInOverlay() { - return syserror.ENOENT - } - } + // We need a dentry representing the child being removed in order to verify + // that it's not a directory. + child, childLayer, err := fs.getChildLocked(ctx, parent, name, &ds) + if err != nil { + return err } - if child != nil { - if child.isDir() { - return syserror.EISDIR - } - if err := parent.mayDelete(rp.Credentials(), child); err != nil { - return err - } - if err := vfsObj.PrepareDeleteDentry(mntns, &child.vfsd); err != nil { - return err - } - // Hold child.copyMu to prevent it from being copied-up during - // deletion. - child.copyMu.RLock() - defer child.copyMu.RUnlock() - if child.upperVD.Ok() { - childLayer = lookupLayerUpper - } else { - childLayer = lookupLayerLower - } + if child.isDir() { + return syserror.EISDIR + } + if err := parent.mayDelete(rp.Credentials(), child); err != nil { + return err + } + // Hold child.copyMu to prevent it from being copied-up during + // deletion. + child.copyMu.RLock() + defer child.copyMu.RUnlock() + if err := vfsObj.PrepareDeleteDentry(mntns, &child.vfsd); err != nil { + return err } pop := vfs.PathOperation{ |