diff options
author | Adin Scannell <ascannell@google.com> | 2018-08-13 13:29:54 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-08-13 13:31:18 -0700 |
commit | dde836a91858ceee25dbe023263752b39ae21274 (patch) | |
tree | 1b919c0a20019e7bb108cf6508b850db82f9cc2a /pkg/sentry/fs/dirent.go | |
parent | 85235ac212713942cb4c0ab2947964711a342a64 (diff) |
Prevent renames across walk fast path.
PiperOrigin-RevId: 208533436
Change-Id: Ifc1a4e2d6438a424650bee831c301b1ac0d670a3
Diffstat (limited to 'pkg/sentry/fs/dirent.go')
-rw-r--r-- | pkg/sentry/fs/dirent.go | 34 |
1 files changed, 8 insertions, 26 deletions
diff --git a/pkg/sentry/fs/dirent.go b/pkg/sentry/fs/dirent.go index f81ad5792..4d3aeaf41 100644 --- a/pkg/sentry/fs/dirent.go +++ b/pkg/sentry/fs/dirent.go @@ -533,14 +533,18 @@ func (d *Dirent) walk(ctx context.Context, root *Dirent, name string, walkMayUnl return nil, syscall.ENOENT } - // Slow path: load the InodeOperations into memory. Since this is a hot path and the lookup may be expensive, - // if possible release the lock and re-acquire it. + // Slow path: load the InodeOperations into memory. Since this is a hot path and the lookup may be + // expensive, if possible release the lock and re-acquire it. if walkMayUnlock { + // While this dirent is unlocked, the lookup below is not allowed to proceed in tandem with a + // rename operation. The rename should be fully complete before we call Lookup on anything. d.mu.Unlock() + renameMu.RLock() } c, err := d.Inode.Lookup(ctx, name) if walkMayUnlock { d.mu.Lock() + renameMu.RUnlock() } // No dice. if err != nil { @@ -1047,34 +1051,12 @@ func (d *Dirent) flush() { } } -// Busy indicates whether this Dirent is a mount point or root dirent, or has -// active positive children. -// -// This is expensive, since it flushes the children cache. -// -// TODO: Fix this busy-ness check. +// Busy indicates whether this Dirent is a mount point or root dirent. func (d *Dirent) Busy() bool { d.mu.Lock() defer d.mu.Unlock() - if d.mounted || d.parent == nil { - return true - } - - // Flush any cached references to children that are doomed. - d.flush() - - // Count positive children. - var nonNegative int - for _, w := range d.children { - if child := w.Get(); child != nil { - if !child.(*Dirent).IsNegative() { - nonNegative++ - } - child.DecRef() - } - } - return nonNegative > 0 + return d.mounted || d.parent == nil } // mount mounts a new dirent with the given inode over d. |