diff options
author | Christopher Koch <chrisko@google.com> | 2018-05-03 09:59:32 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-05-03 10:00:24 -0700 |
commit | 9739b8c21cd1716c4c1c81a27121c50e63fcf906 (patch) | |
tree | 8ca7fa9a2294860de43cb03bf45b08b9b7108d03 /pkg | |
parent | 9c665c4c2496f71231f4c60454592854182c0e65 (diff) |
Don't prematurely remove MountSource from parent's children.
Otherwise, mounts that fail to be unmounted (EBUSY) will be removed
from the children list anyway.
At this point, this just affects /proc/pid/mounts and /proc/pid/mountinfo.
PiperOrigin-RevId: 195267588
Change-Id: I79114483d73b90f9a7d764a7d513b5b2f251182e
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/sentry/fs/mounts.go | 46 |
1 files changed, 22 insertions, 24 deletions
diff --git a/pkg/sentry/fs/mounts.go b/pkg/sentry/fs/mounts.go index 1e6b5b70e..87da4ee0e 100644 --- a/pkg/sentry/fs/mounts.go +++ b/pkg/sentry/fs/mounts.go @@ -272,31 +272,8 @@ func (mns *MountNamespace) Unmount(ctx context.Context, node *Dirent, detachOnly panic("cannot unmount initial dirent") } + m := node.Inode.MountSource if !detachOnly { - m := node.Inode.MountSource - - // Lock the parent MountSource first, if it exists. We are - // holding mns.Lock, so the parent can not change out - // from under us. - parent := m.Parent() - if parent != nil { - parent.mu.Lock() - defer parent.mu.Unlock() - } - - // Lock the mount that is being unmounted. - m.mu.Lock() - defer m.mu.Unlock() - - if m.parent != nil { - // Sanity check. - if _, ok := m.parent.children[m]; !ok { - panic(fmt.Sprintf("mount %+v is not a child of parent %+v", m, m.parent)) - } - delete(m.parent.children, m) - m.parent = nil - } - // Flush all references on the mounted node. m.FlushDirentRefs() @@ -315,6 +292,27 @@ func (mns *MountNamespace) Unmount(ctx context.Context, node *Dirent, detachOnly } } + // Lock the parent MountSource first, if it exists. We are + // holding mns.Lock, so the parent can not change out + // from under us. + parent := m.Parent() + if parent != nil { + parent.mu.Lock() + defer parent.mu.Unlock() + } + + // Lock the mount that is being unmounted. + m.mu.Lock() + defer m.mu.Unlock() + + if m.parent != nil { + // Sanity check. + if _, ok := m.parent.children[m]; !ok { + panic(fmt.Sprintf("mount %+v is not a child of parent %+v", m, m.parent)) + } + delete(m.parent.children, m) + } + original := origs[len(origs)-1] if err := node.unmount(ctx, original); err != nil { return err |