Fuse: DeviceFD.Read: Lock DeviceFD ahead of other locks.

Syzkaller reports a "unlocking an unlocked mutex" here:
https://github.com/google/gvisor/blob/a5ce865145c718f26c7a8f305f6c8262e992051c/pkg/sentry/fsimpl/fuse/dev.go#L154
... which can only happen if `fd.fs` changes in the middle. By locking
`DeviceFD` earlier, we follow the lock ordering specified in
https://github.com/google/gvisor/blob/a5ce865145c718f26c7a8f305f6c8262e992051c/pkg/sentry/fsimpl/fuse/connection.go#L42
hopefully fixing the issue.

Reported-by: syzbot+f211c42d52f93416457d@syzkaller.appspotmail.com
PiperOrigin-RevId: 426288804
This commit is contained in:
Etienne Perot
2022-02-03 18:51:20 -08:00
committed by gVisor bot
parent 350f05d6cd
commit 10d1a49c5b
+3 -3
View File
@@ -149,6 +149,9 @@ func (fd *DeviceFD) Read(ctx context.Context, dst usermem.IOSequence, opts vfs.R
minBuffSize := linux.FUSE_MIN_READ_BUFFER
inHdrLen := uint32((*linux.FUSEHeaderIn)(nil).SizeBytes())
writeHdrLen := uint32((*linux.FUSEWriteIn)(nil).SizeBytes())
fd.mu.Lock()
defer fd.mu.Unlock()
fd.fs.conn.mu.Lock()
negotiatedMinBuffSize := inHdrLen + writeHdrLen + fd.fs.conn.maxWrite
fd.fs.conn.mu.Unlock()
@@ -160,9 +163,6 @@ func (fd *DeviceFD) Read(ctx context.Context, dst usermem.IOSequence, opts vfs.R
if dst.NumBytes() < int64(minBuffSize) {
return 0, linuxerr.EINVAL
}
fd.mu.Lock()
defer fd.mu.Unlock()
return fd.readLocked(ctx, dst, opts)
}