From: Christian Schoenebeck <linux_oss@crudebyte.com>
To: v9fs-developer@lists.sourceforge.net,
Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>,
Dominique Martinet <asmadeus@codewreck.org>,
syzbot <syzbot+2f20b523930c32c160cc@syzkaller.appspotmail.com>
Cc: syzkaller-bugs@googlegroups.com, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] net/9p: use a dedicated spinlock for trans_fd
Date: Thu, 06 Oct 2022 15:16:40 +0200 [thread overview]
Message-ID: <2356596.7K3kzkM6Yp@silver> (raw)
In-Reply-To: <20220904112928.1308799-1-asmadeus@codewreck.org>
On Sonntag, 4. September 2022 13:29:28 CEST Dominique Martinet wrote:
> Shamelessly copying the explanation from Tetsuo Handa's suggested
> patch[1] (slightly reworded):
> syzbot is reporting inconsistent lock state in p9_req_put()[2],
> for p9_tag_remove() from p9_req_put() from IRQ context is using
> spin_lock_irqsave() on "struct p9_client"->lock but trans_fd
> (not from IRQ context) is using spin_lock().
>
> Since the locks actually protect different things in client.c and in
> trans_fd.c, just replace trans_fd.c's lock by a new one specific to the
> transport instead of using spin_lock_irq* variants everywhere
> (client.c's protect the idr for tag allocations, while
> trans_fd.c's protects its own req list and request status field
> that acts as the transport's state machine)
>
> Link:
> https://lkml.kernel.org/r/2470e028-9b05-2013-7198-1fdad071d999@I-love.SAKUR
> A.ne.jp [1] Link:
> https://syzkaller.appspot.com/bug?extid=2f20b523930c32c160cc [2]
> Reported-by: syzbot <syzbot+2f20b523930c32c160cc@syzkaller.appspotmail.com>
> Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> ---
> Tetsuo Handa-san, thank you very much!
> I'm sorry for not respecting your opinion but it's been a pleasure to
> have submissions from someone on JST :)
>
> Both this and your previous patch only impact trans_fd which I can't
> test super easily, so while I've sent the patch here I'll only queue it
> to -next hopefully next week after I've had time to setup a compatible
> server again...
>
> net/9p/trans_fd.c | 42 ++++++++++++++++++++++++++----------------
> 1 file changed, 26 insertions(+), 16 deletions(-)
>
Late on the party, sorry. Note that you already queued a slightly different
version than this patch here, anyway, one thing ...
> diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
> index ef5760971f1e..5b4807411281 100644
> --- a/net/9p/trans_fd.c
> +++ b/net/9p/trans_fd.c
> @@ -91,6 +91,7 @@ struct p9_poll_wait {
> * @mux_list: list link for mux to manage multiple connections (?)
> * @client: reference to client instance for this connection
> * @err: error state
> + * @req_lock: lock protecting req_list and requests statuses
> * @req_list: accounting for requests which have been sent
> * @unsent_req_list: accounting for requests that haven't been sent
> * @rreq: read request
> @@ -114,6 +115,7 @@ struct p9_conn {
> struct list_head mux_list;
> struct p9_client *client;
> int err;
> + spinlock_t req_lock;
> struct list_head req_list;
> struct list_head unsent_req_list;
> struct p9_req_t *rreq;
> @@ -189,10 +191,10 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
>
> p9_debug(P9_DEBUG_ERROR, "mux %p err %d\n", m, err);
>
> - spin_lock(&m->client->lock);
> + spin_lock(&m->req_lock);
>
> if (m->err) {
> - spin_unlock(&m->client->lock);
> + spin_unlock(&m->req_lock);
> return;
> }
>
> @@ -205,7 +207,7 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
> list_move(&req->req_list, &cancel_list);
> }
>
> - spin_unlock(&m->client->lock);
> + spin_unlock(&m->req_lock);
>
> list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
> p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req);
> @@ -360,7 +362,7 @@ static void p9_read_work(struct work_struct *work)
> if ((m->rreq) && (m->rc.offset == m->rc.capacity)) {
> p9_debug(P9_DEBUG_TRANS, "got new packet\n");
> m->rreq->rc.size = m->rc.offset;
> - spin_lock(&m->client->lock);
> + spin_lock(&m->req_lock);
> if (m->rreq->status == REQ_STATUS_SENT) {
> list_del(&m->rreq->req_list);
> p9_client_cb(m->client, m->rreq,
REQ_STATUS_RCVD);
> @@ -369,14 +371,14 @@ static void p9_read_work(struct work_struct *work)
> p9_debug(P9_DEBUG_TRANS,
> "Ignore replies associated with a
cancelled request\n");
> } else {
> - spin_unlock(&m->client->lock);
> + spin_unlock(&m->req_lock);
> p9_debug(P9_DEBUG_ERROR,
> "Request tag %d errored out while we
were reading the reply\n",
> m->rc.tag);
> err = -EIO;
> goto error;
> }
> - spin_unlock(&m->client->lock);
> + spin_unlock(&m->req_lock);
> m->rc.sdata = NULL;
> m->rc.offset = 0;
> m->rc.capacity = 0;
> @@ -454,10 +456,10 @@ static void p9_write_work(struct work_struct *work)
> }
>
> if (!m->wsize) {
> - spin_lock(&m->client->lock);
> + spin_lock(&m->req_lock);
> if (list_empty(&m->unsent_req_list)) {
> clear_bit(Wworksched, &m->wsched);
> - spin_unlock(&m->client->lock);
> + spin_unlock(&m->req_lock);
> return;
> }
>
> @@ -472,7 +474,7 @@ static void p9_write_work(struct work_struct *work)
> m->wpos = 0;
> p9_req_get(req);
> m->wreq = req;
> - spin_unlock(&m->client->lock);
> + spin_unlock(&m->req_lock);
> }
>
> p9_debug(P9_DEBUG_TRANS, "mux %p pos %d size %d\n",
> @@ -670,10 +672,10 @@ static int p9_fd_request(struct p9_client *client,
> struct p9_req_t *req) if (m->err < 0)
> return m->err;
>
> - spin_lock(&client->lock);
> + spin_lock(&m->req_lock);
> req->status = REQ_STATUS_UNSENT;
> list_add_tail(&req->req_list, &m->unsent_req_list);
> - spin_unlock(&client->lock);
> + spin_unlock(&m->req_lock);
>
> if (test_and_clear_bit(Wpending, &m->wsched))
> n = EPOLLOUT;
> @@ -688,11 +690,13 @@ static int p9_fd_request(struct p9_client *client,
> struct p9_req_t *req)
>
> static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
> {
> + struct p9_trans_fd *ts = client->trans;
> + struct p9_conn *m = &ts->conn;
> int ret = 1;
>
> p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
>
> - spin_lock(&client->lock);
> + spin_lock(&m->req_lock);
>
> if (req->status == REQ_STATUS_UNSENT) {
> list_del(&req->req_list);
> @@ -700,21 +704,24 @@ static int p9_fd_cancel(struct p9_client *client,
> struct p9_req_t *req) p9_req_put(client, req);
> ret = 0;
> }
> - spin_unlock(&client->lock);
> + spin_unlock(&m->req_lock);
>
> return ret;
> }
>
> static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
> {
> + struct p9_trans_fd *ts = client->trans;
> + struct p9_conn *m = &ts->conn;
> +
> p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
>
> - spin_lock(&client->lock);
> + spin_lock(&m->req_lock);
> /* Ignore cancelled request if message has been received
> * before lock.
> */
> if (req->status == REQ_STATUS_RCVD) {
> - spin_unlock(&client->lock);
> + spin_unlock(&m->req_lock);
> return 0;
> }
>
> @@ -723,7 +730,8 @@ static int p9_fd_cancelled(struct p9_client *client,
> struct p9_req_t *req) */
> list_del(&req->req_list);
> req->status = REQ_STATUS_FLSHD;
> - spin_unlock(&client->lock);
> + spin_unlock(&m->req_lock);
> +
> p9_req_put(client, req);
>
> return 0;
> @@ -832,6 +840,7 @@ static int p9_fd_open(struct p9_client *client, int rfd,
> int wfd)
>
> client->trans = ts;
> client->status = Connected;
> + spin_lock_init(&ts->conn.req_lock);
Are you sure this is the right place for spin_lock_init()? Not rather in
p9_conn_create()?
> return 0;
>
> @@ -866,6 +875,7 @@ static int p9_socket_open(struct p9_client *client,
> struct socket *csocket) p->wr = p->rd = file;
> client->trans = p;
> client->status = Connected;
> + spin_lock_init(&p->conn.req_lock);
Same here.
>
> p->rd->f_flags |= O_NONBLOCK;
The rest LGTM.
Best regards,
Christian Schoenebeck
next prev parent reply other threads:[~2022-10-06 13:17 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-15 22:24 [syzbot] inconsistent lock state in p9_req_put syzbot
2022-09-04 6:09 ` [PATCH] net/9p: use a dedicated spinlock for modifying IDR Tetsuo Handa
2022-09-04 6:36 ` Dominique Martinet
2022-09-04 7:06 ` [PATCH v2] " Tetsuo Handa
2022-09-04 7:55 ` Dominique Martinet
2022-09-04 10:02 ` Tetsuo Handa
2022-09-04 10:52 ` Dominique Martinet
2022-09-04 10:58 ` Tetsuo Handa
2022-09-04 7:17 ` [PATCH] " Tetsuo Handa
2022-09-04 11:29 ` [PATCH] net/9p: use a dedicated spinlock for trans_fd Dominique Martinet
2022-09-04 13:03 ` Tetsuo Handa
2022-10-06 13:16 ` Christian Schoenebeck [this message]
2022-10-07 1:05 ` Dominique Martinet
2022-10-07 9:29 ` Christian Schoenebeck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2356596.7K3kzkM6Yp@silver \
--to=linux_oss@crudebyte.com \
--cc=asmadeus@codewreck.org \
--cc=linux-kernel@vger.kernel.org \
--cc=penguin-kernel@i-love.sakura.ne.jp \
--cc=syzbot+2f20b523930c32c160cc@syzkaller.appspotmail.com \
--cc=syzkaller-bugs@googlegroups.com \
--cc=v9fs-developer@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.