From: Miklos Szeredi mszeredi@redhat.com
stable inclusion from stable-5.10.50 commit bb7ee90ea5247941c13b3574667dcbe42261348a bugzilla: 174522 https://gitee.com/openeuler/kernel/issues/I4DNFY
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 80ef08670d4c28a06a3de954bd350368780bcfef upstream.
A request could end up on the fpq->io list after fuse_abort_conn() has reset fpq->connected and aborted requests on that list:
Thread-1 Thread-2
======== ======== ->fuse_simple_request() ->shutdown ->__fuse_request_send() ->queue_request() ->fuse_abort_conn() ->fuse_dev_do_read() ->acquire(fpq->lock) ->wait_for(fpq->lock) ->set err to all req's in fpq->io ->release(fpq->lock) ->acquire(fpq->lock) ->add req to fpq->io
After the userspace copy is done the request will be ended, but req->out.h.error will remain uninitialized. Also the copy might block despite being already aborted.
Fix both issues by not allowing the request to be queued on the fpq->io list after fuse_abort_conn() has processed this list.
Reported-by: Pradeep P V K pragalla@codeaurora.org Fixes: fd22d62ed0c3 ("fuse: no fc->lock for iqueue parts") Cc: stable@vger.kernel.org # v4.2 Signed-off-by: Miklos Szeredi mszeredi@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Chen Jun chenjun102@huawei.com Acked-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Chen Jun chenjun102@huawei.com --- fs/fuse/dev.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 5ecd7d38a85a..c1f649c41f24 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1276,6 +1276,15 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, goto restart; } spin_lock(&fpq->lock); + /* + * Must not put request on fpq->io queue after having been shut down by + * fuse_abort_conn() + */ + if (!fpq->connected) { + req->out.h.error = err = -ECONNABORTED; + goto out_end; + + } list_add(&req->list, &fpq->io); spin_unlock(&fpq->lock); cs->req = req;