Commit 21391520 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents c2f3850d 74d6a5d5
Loading
Loading
Loading
Loading
+30 −9
Original line number Diff line number Diff line
@@ -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)