summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdin Scannell <ascannell@google.com>2018-08-13 13:29:54 -0700
committerShentubot <shentubot@google.com>2018-08-13 13:31:18 -0700
commitdde836a91858ceee25dbe023263752b39ae21274 (patch)
tree1b919c0a20019e7bb108cf6508b850db82f9cc2a
parent85235ac212713942cb4c0ab2947964711a342a64 (diff)
Prevent renames across walk fast path.
PiperOrigin-RevId: 208533436 Change-Id: Ifc1a4e2d6438a424650bee831c301b1ac0d670a3
-rw-r--r--pkg/sentry/fs/dirent.go34
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.