From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-eopbgr690096.outbound.protection.outlook.com ([40.107.69.96]:35711 "EHLO NAM04-CO1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727480AbeH3WHI (ORCPT ); Thu, 30 Aug 2018 18:07:08 -0400 From: Sasha Levin To: "stable@vger.kernel.org" CC: Tomas Bortoli , Yiwen Jiang , "David S . Miller" , Dominique Martinet , Sasha Levin Subject: [PATCH AUTOSEL 4.18 061/113] net/9p/trans_fd.c: fix race by holding the lock Date: Thu, 30 Aug 2018 18:03:36 +0000 Message-ID: <20180830180050.35735-61-alexander.levin@microsoft.com> References: <20180830180050.35735-1-alexander.levin@microsoft.com> In-Reply-To: <20180830180050.35735-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Tomas Bortoli [ Upstream commit 9f476d7c540cb57556d3cc7e78704e6cd5100f5f ] It may be possible to run p9_fd_cancel() with a deleted req->req_list and incur in a double del. To fix hold the client->lock while changing the status, so the other threads will be synchronized. Link: http://lkml.kernel.org/r/20180723184253.6682-1-tomasbortoli@gmail.com Signed-off-by: Tomas Bortoli Reported-by: syzbot+735d926e9d1317c3310c@syzkaller.appspotmail.com To: Eric Van Hensbergen To: Ron Minnich To: Latchesar Ionkov Cc: Yiwen Jiang Cc: David S. Miller Signed-off-by: Dominique Martinet Signed-off-by: Sasha Levin --- net/9p/trans_fd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 588bf88c3305..f9f96d50d96d 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -197,15 +197,14 @@ static void p9_mux_poll_stop(struct p9_conn *m) static void p9_conn_cancel(struct p9_conn *m, int err) { struct p9_req_t *req, *rtmp; - unsigned long flags; LIST_HEAD(cancel_list); =20 p9_debug(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); =20 - spin_lock_irqsave(&m->client->lock, flags); + spin_lock(&m->client->lock); =20 if (m->err) { - spin_unlock_irqrestore(&m->client->lock, flags); + spin_unlock(&m->client->lock); return; } =20 @@ -217,7 +216,6 @@ static void p9_conn_cancel(struct p9_conn *m, int err) list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { list_move(&req->req_list, &cancel_list); } - spin_unlock_irqrestore(&m->client->lock, flags); =20 list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req); @@ -226,6 +224,7 @@ static void p9_conn_cancel(struct p9_conn *m, int err) req->t_err =3D err; p9_client_cb(m->client, req, REQ_STATUS_ERROR); } + spin_unlock(&m->client->lock); } =20 static __poll_t @@ -373,8 +372,9 @@ static void p9_read_work(struct work_struct *work) if (m->req->status !=3D REQ_STATUS_ERROR) status =3D REQ_STATUS_RCVD; list_del(&m->req->req_list); - spin_unlock(&m->client->lock); + /* update req->status while holding client->lock */ p9_client_cb(m->client, m->req, status); + spin_unlock(&m->client->lock); m->rc.sdata =3D NULL; m->rc.offset =3D 0; m->rc.capacity =3D 0; --=20 2.17.1