From 5a28bc6121c2cb076e24036386241e32a5745b40 Mon Sep 17 00:00:00 2001 From: Jinmou Li Date: Thu, 3 Sep 2020 19:22:24 +0000 Subject: Fix FUSE_RELEASE protocol reply processing This commit fixes the potential unexpected errors of original handling of FUSE_RELEASE responses while keep the same behavior (ignoring any reply). --- pkg/sentry/fsimpl/fuse/dev.go | 9 ++++++++- pkg/sentry/fsimpl/fuse/file.go | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'pkg/sentry/fsimpl/fuse') diff --git a/pkg/sentry/fsimpl/fuse/dev.go b/pkg/sentry/fsimpl/fuse/dev.go index e7296c189..6f0b896cb 100644 --- a/pkg/sentry/fsimpl/fuse/dev.go +++ b/pkg/sentry/fsimpl/fuse/dev.go @@ -204,8 +204,11 @@ func (fd *DeviceFD) readLocked(ctx context.Context, dst usermem.IOSequence, opts // Fully done with this req, remove it from the queue. fd.queue.Remove(req) - if req.hdr.Opcode == linux.FUSE_RELEASE { + + // Remove noReply ones from map of requests expecting a reply. + if req.noReply { fd.numActiveRequests -= 1 + delete(fd.completions, req.hdr.Unique) } return int64(n), nil @@ -296,6 +299,10 @@ func (fd *DeviceFD) writeLocked(ctx context.Context, src usermem.IOSequence, opt fut, ok := fd.completions[hdr.Unique] if !ok { + if fut.hdr.Unique == linux.FUSE_RELEASE { + // Currently we simply discard the reply for FUSE_RELEASE. + return n + src.NumBytes(), nil + } // Server sent us a response for a request we never sent? return 0, syserror.EINVAL } diff --git a/pkg/sentry/fsimpl/fuse/file.go b/pkg/sentry/fsimpl/fuse/file.go index 15c0e3f41..b98145ba2 100644 --- a/pkg/sentry/fsimpl/fuse/file.go +++ b/pkg/sentry/fsimpl/fuse/file.go @@ -84,7 +84,12 @@ func (fd *fileDescription) Release(ctx context.Context) { } kernelTask := kernel.TaskFromContext(ctx) // ignoring errors and FUSE server reply is analogous to Linux's behavior. - req, _ := conn.NewRequest(auth.CredentialsFromContext(ctx), uint32(kernelTask.ThreadID()), fd.inode().NodeID, opcode, &in) + req, err := conn.NewRequest(auth.CredentialsFromContext(ctx), uint32(kernelTask.ThreadID()), fd.inode().NodeID, opcode, &in) + if err != nil { + // No way to invoke Call() with an errored request. + return + } + req.noReply = true conn.CallAsync(kernelTask, req) } -- cgit v1.2.3