From 9739b8c21cd1716c4c1c81a27121c50e63fcf906 Mon Sep 17 00:00:00 2001 From: Christopher Koch Date: Thu, 3 May 2018 09:59:32 -0700 Subject: 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 --- pkg/sentry/fs/mounts.go | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'pkg/sentry/fs') 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 -- cgit v1.2.3