From 510cc2f7fca91b42cf3ed4813631233e478b566a Mon Sep 17 00:00:00 2001 From: Lucas Manning Date: Thu, 24 Feb 2022 15:55:07 -0800 Subject: [PATCH] Fix pivot_root lock inversion. PivotRoot takes vfs.mountMu then calls PrependPath which calls fs.mu. RmdirAt() takes fs.mu and then calls PrepareDeleteDentry which takes vfs.mountMu. PiperOrigin-RevId: 430813050 --- pkg/sentry/vfs/mount.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/sentry/vfs/mount.go b/pkg/sentry/vfs/mount.go index 5fccbead9..ff64d494b 100644 --- a/pkg/sentry/vfs/mount.go +++ b/pkg/sentry/vfs/mount.go @@ -727,9 +727,8 @@ func (vfs *VirtualFilesystem) PivotRoot(ctx context.Context, creds *auth.Credent rootVd := RootFromContext(ctx) defer rootVd.DecRef(ctx) - vfs.mountMu.Lock() - defer vfs.mountMu.Unlock() - +retry: + epoch := vfs.mounts.seq.BeginRead() // Neither new_root nor put_old can be on the same mount as the current //root mount. if newRootVd.mount == rootVd.mount || putOldVd.mount == rootVd.mount { @@ -763,7 +762,13 @@ func (vfs *VirtualFilesystem) PivotRoot(ctx context.Context, creds *auth.Credent // pivot_root-ing new_root/put_old mounts with MS_SHARED propagation once it // is implemented in gVisor. - vfs.mounts.seq.BeginWrite() + vfs.mountMu.Lock() + if !vfs.mounts.seq.BeginWriteOk(epoch) { + // Checks above raced with a mount change. + vfs.mountMu.Unlock() + goto retry + } + defer vfs.mountMu.Unlock() mp := vfs.disconnectLocked(newRootVd.mount) mp.DecRef(ctx) rootMp := vfs.disconnectLocked(rootVd.mount)