[PATCH net-next] sctp: fix use-after-free in timeout event handling

luoqing <[email protected]>
Newsgroups org.kernel.vger.linux-sctp,org.kernel.vger.linux-kernel,org.kernel.vger.netdev
Message-ID <[email protected]>
From: Qing Luo <[email protected]>

sctp_do_sm() in sctp_generate_timeout_event() may process an
SCTP_CMD_ASSOC_FAILED command, which calls sctp_association_free() and
drops the last reference, freeing the association and its socket while
the timer callback is still running. The callback then dereferences the
freed sk and asoc, a use-after-free.

Hold an extra reference on the association at the start of the callback
so both it and its socket stay alive until we are done, and release it
at out_unlock along with the timer's reference. Also only set sk->sk_err
while the association is still alive.

Assisted-by: LLM
Signed-off-by: Qing Luo <[email protected]>
---
 net/sctp/sm_sideeffect.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 424f10a6fdba..f384c2faf1c4 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -275,6 +275,12 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc,
 	int error = 0;
 
 	bh_lock_sock(sk);
+
+	/* Take an extra ref to keep asoc alive through sctp_do_sm().
+	 * The timer already holds one ref; we'll release both at out_unlock.
+	 */
+	sctp_association_hold(asoc);
+
 	if (sock_owned_by_user(sk)) {
 		pr_debug("%s: sock is busy: timer %d\n", __func__,
 			 timeout_type);
@@ -296,13 +302,13 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc,
 			   SCTP_ST_TIMEOUT(timeout_type),
 			   asoc->state, asoc->ep, asoc,
 			   (void *)timeout_type, GFP_ATOMIC);
-
-	if (error)
+	if (!asoc->base.dead && error)
 		sk->sk_err = -error;
 
 out_unlock:
 	bh_unlock_sock(sk);
-	sctp_association_put(asoc);
+	sctp_association_put(asoc); 	/* release timer's ref */
+	sctp_association_put(asoc);	/* release our extra ref */
 }
 
 static void sctp_generate_t1_cookie_event(struct timer_list *t)
-- 
2.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.