9p/trans_fd: avoid sending req to a cancelled conn
authorSishuai Gong <sishuai.system@gmail.com>
Tue, 8 Aug 2023 16:44:31 +0000 (12:44 -0400)
committerDominique Martinet <asmadeus@codewreck.org>
Tue, 24 Oct 2023 04:52:37 +0000 (13:52 +0900)
When a connection is cancelled by p9_conn_cancel(), all requests on it
should be cancelled---mark req->status as REQ_STATUS_ERROR. However,
because a race over m->err between p9_conn_cancel() and p9_fd_request(),
p9_fd_request might see the old value of m->err, think that the connection
is NOT cancelled, and then add new requests to this cancelled connection.

Fixing this issue by lock-protecting the check on m->err.

Signed-off-by: Sishuai Gong <sishuai.system@gmail.com>
Message-ID: <AA2DB53B-DFC7-4B88-9515-E4C9AFA6435D@gmail.com>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
Reviewed-by: Christian Schoenebeck <linux_oss@crudebyte.com>
net/9p/trans_fd.c

index c4015f30f9fa79a4a968f9a0a9aab243f0d460a0..f226953577b26fce63d0f241748005aa2c874be3 100644 (file)
@@ -671,10 +671,14 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
 
        p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n",
                 m, current, &req->tc, req->tc.id);
-       if (m->err < 0)
-               return m->err;
 
        spin_lock(&m->req_lock);
+
+       if (m->err < 0) {
+               spin_unlock(&m->req_lock);
+               return m->err;
+       }
+
        WRITE_ONCE(req->status, REQ_STATUS_UNSENT);
        list_add_tail(&req->req_list, &m->unsent_req_list);
        spin_unlock(&m->req_lock);