diff options
author | Sishuai Gong <sishuai.system@gmail.com> | 2023-08-08 12:44:31 -0400 |
---|---|---|
committer | Dominique Martinet <asmadeus@codewreck.org> | 2023-10-24 13:52:37 +0900 |
commit | 58e3ce767307130e911408c75f054d6a6673c8a3 (patch) | |
tree | 62025555aaeea9eb2b9e2725a5e7f08e9d2198d5 /net/9p | |
parent | 05d3ef8bba77c1b5f98d941d8b2d4aeab8118ef1 (diff) |
9p/trans_fd: avoid sending req to a cancelled conn
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>
Diffstat (limited to 'net/9p')
-rw-r--r-- | net/9p/trans_fd.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index c4015f30f9fa..f226953577b2 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -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); |