diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-07-29 12:29:24 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-07-29 12:29:24 -0700 |
commit | 21391520cbb597823050ac1bc343a0df3222ac90 (patch) | |
tree | 88da45922be57cf407dbf74b3b7c296cfe490922 | |
parent | c2f3850df7f95537e79c561f7be49df2e4ad8060 (diff) | |
parent | 74d6a5d5662975aed7f25952f62efbb6f6dadd29 (diff) |
Merge tag '9p-for-5.8-2' of git://github.com/martinetd/linux into master
Pull 9p fixes from Dominique Martinet:
"A couple of syzcaller fixes for 5.8
The first one in particular has been quite noisy ("broke" in -rc5) so
this would be worth landing even this late even if users likely won't
see a difference"
* tag '9p-for-5.8-2' of git://github.com/martinetd/linux:
9p/trans_fd: Fix concurrency del of req_list in p9_fd_cancelled/p9_read_work
net/9p: validate fds in p9_fd_open
-rw-r--r-- | net/9p/trans_fd.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 13cd683a658a..12ecacf0c55f 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -362,6 +362,10 @@ static void p9_read_work(struct work_struct *work) if (m->rreq->status == REQ_STATUS_SENT) { list_del(&m->rreq->req_list); p9_client_cb(m->client, m->rreq, REQ_STATUS_RCVD); + } else if (m->rreq->status == REQ_STATUS_FLSHD) { + /* Ignore replies associated with a cancelled request. */ + p9_debug(P9_DEBUG_TRANS, + "Ignore replies associated with a cancelled request\n"); } else { spin_unlock(&m->client->lock); p9_debug(P9_DEBUG_ERROR, @@ -703,11 +707,20 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) { p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req); + spin_lock(&client->lock); + /* Ignore cancelled request if message has been received + * before lock. + */ + if (req->status == REQ_STATUS_RCVD) { + spin_unlock(&client->lock); + return 0; + } + /* we haven't received a response for oldreq, * remove it from the list. */ - spin_lock(&client->lock); list_del(&req->req_list); + req->status = REQ_STATUS_FLSHD; spin_unlock(&client->lock); p9_req_put(req); @@ -803,20 +816,28 @@ static int p9_fd_open(struct p9_client *client, int rfd, int wfd) return -ENOMEM; ts->rd = fget(rfd); + if (!ts->rd) + goto out_free_ts; + if (!(ts->rd->f_mode & FMODE_READ)) + goto out_put_rd; ts->wr = fget(wfd); - if (!ts->rd || !ts->wr) { - if (ts->rd) - fput(ts->rd); - if (ts->wr) - fput(ts->wr); - kfree(ts); - return -EIO; - } + if (!ts->wr) + goto out_put_rd; + if (!(ts->wr->f_mode & FMODE_WRITE)) + goto out_put_wr; client->trans = ts; client->status = Connected; return 0; + +out_put_wr: + fput(ts->wr); +out_put_rd: + fput(ts->rd); +out_free_ts: + kfree(ts); + return -EIO; } static int p9_socket_open(struct p9_client *client, struct socket *csocket) |