From: sashiko-bot@kernel.org
To: "Jaeyeong Lee" <lee@jaeyeong.cc>
Cc: linux-rdma@vger.kernel.org
Subject: Re: [PATCH v2] RDMA/siw: Fix early peer close handling on listeners
Date: Wed, 04 Nov 2026 10:44:52 +0000 [thread overview]
Message-ID: <sashiko-outbox-197117@kernel.org> (raw)
In-Reply-To: <20261104100953.125140-1-lee@jaeyeong.cc>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] RDMA/siw: siw_accept_newconn() drops connections in post-listen IDLE window
--
commit fd783e525f31231ba5b3c0e855c9ecc089f5379f
Author: Jaeyeong Lee <lee@jaeyeong.cc>
RDMA/siw: Fix early peer close handling on listeners
This commit prevents a use-after-free in siw_destroy_listen() when a TCP
child socket closes before kernel_accept() associates it with a new
connection endpoint. It ignores close notifications on listening and
unaccepted post-listen IDLE endpoints, and serializes the accepted-socket
handoff in siw_accept_newconn() while rejecting child sockets that have
already reached TCP_CLOSE or TCP_CLOSE_WAIT.
> diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c
> index ed49818793dde..92fcbcabb5984 100644
> --- a/drivers/infiniband/sw/siw/siw_cm.c
> +++ b/drivers/infiniband/sw/siw/siw_cm.c
> @@ -973,6 +973,7 @@ static void siw_accept_newconn(struct siw_cep *cep)
> struct socket *s = cep->sock;
> struct socket *new_s = NULL;
> struct siw_cep *new_cep = NULL;
> + bool peer_closed;
> int rv = 0; /* debug only. should disappear */
>
> if (cep->state != SIW_EPSTATE_LISTENING)
> @@ -1009,11 +1010,23 @@ static void siw_accept_newconn(struct siw_cep *cep)
> }
> new_cep->sock = new_s;
> siw_cep_get(new_cep);
> - new_s->sk->sk_user_data = new_cep;
>
> if (siw_tcp_nagle == false)
> tcp_sock_set_nodelay(new_s->sk);
> +
> + lock_sock(new_s->sk);
> + write_lock_bh(&new_s->sk->sk_callback_lock);
> new_cep->state = SIW_EPSTATE_AWAIT_MPAREQ;
> + new_s->sk->sk_user_data = new_cep;
> + peer_closed = new_s->sk->sk_state == TCP_CLOSE ||
> + new_s->sk->sk_state == TCP_CLOSE_WAIT;
> + write_unlock_bh(&new_s->sk->sk_callback_lock);
> + release_sock(new_s->sk);
> +
> + if (peer_closed) {
> + rv = -ECONNRESET;
> + goto error;
> + }
>
> rv = siw_cm_queue_work(new_cep, SIW_CM_WORK_MPATIMEOUT);
> if (rv)
> @@ -1361,6 +1374,10 @@ static void siw_cm_llp_state_change(struct sock *sk)
>
> case TCP_CLOSE:
> case TCP_CLOSE_WAIT:
> + if (cep->state == SIW_EPSTATE_LISTENING ||
> + (cep->state == SIW_EPSTATE_IDLE &&
> + !READ_ONCE(sk->sk_socket)))
> + break;
[Severity: High]
When a connection arrives during the post-listen SIW_EPSTATE_IDLE window
in siw_create_listen(), can the SIW_CM_WORK_ACCEPT work item run before
cep->state transitions to SIW_EPSTATE_LISTENING and strand the child
socket in the TCP accept queue?
In siw_create_listen(), s->ops->listen() is called while cep->state is
still SIW_EPSTATE_IDLE and cep->in_use is not held:
drivers/infiniband/sw/siw/siw_cm.c:siw_create_listen() {
...
rv = s->ops->listen(s, backlog);
if (rv) {
siw_dbg(id->device, "listen error %d\n", rv);
goto error;
}
cep->cm_id = id;
id->add_ref(id);
...
if (!id->provider_data) {
id->provider_data =
kmalloc_obj(struct list_head);
...
}
list_add_tail(&cep->listenq, (struct list_head *)id->provider_data);
cep->state = SIW_EPSTATE_LISTENING;
}
If a peer completes a TCP handshake during this window,
siw_cm_llp_state_change() queues SIW_CM_WORK_ACCEPT with delay 0, and if
the peer also closes, the new check ignores TCP_CLOSE / TCP_CLOSE_WAIT
because cep->state is SIW_EPSTATE_IDLE and sk->sk_socket is NULL.
However, if siw_cm_work_handler() runs siw_accept_newconn(cep) before
siw_create_listen() sets cep->state = SIW_EPSTATE_LISTENING,
siw_accept_newconn() bails out without calling kernel_accept():
drivers/infiniband/sw/siw/siw_cm.c:siw_accept_newconn() {
...
if (cep->state != SIW_EPSTATE_LISTENING)
goto error;
}
Because the SIW_CM_WORK_ACCEPT work item is consumed and never re-queued
when cep->state becomes SIW_EPSTATE_LISTENING, the unaccepted child socket
is left at the head of icsk_accept_queue. A live connection will hang
unaccepted, or if the peer closed it during the IDLE window, the dead
child socket will be dequeued by the next connection's SIW_CM_WORK_ACCEPT
and trigger the new peer_closed abort, stranding the subsequent valid
connection.
Would holding siw_cep_set_inuse(cep) or setting cep->state =
SIW_EPSTATE_LISTENING before calling s->ops->listen() in
siw_create_listen() avoid this post-listen IDLE window altogether?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261104100953.125140-1-lee@jaeyeong.cc?part=1
prev parent reply other threads:[~2026-11-04 10:44 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 10:10 [PATCH v2] RDMA/siw: Fix early peer close handling on listeners Jaeyeong Lee
2026-11-04 10:44 ` sashiko-bot [this message]
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=sashiko-outbox-197117@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=lee@jaeyeong.cc \
--cc=linux-rdma@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox