From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f171.google.com (mail-pf1-f171.google.com [209.85.210.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4AE15361950 for ; Thu, 27 Aug 2026 07:50:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.171 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787817053; cv=none; b=DvcabALcT38kHsBC2YJnGDdCSs59ZoeyuuJ5PQPOA0iyNUoFTj70gedIgKnM3pS4xnu7crQ9FbS+0Vc7CdoZYcMPKq5vEfyT1o4Cb2ptpq+Et2KRpDqlcir76MGrCwO/w7lxdDIvHtLULY8neAU/Xlynsuu+1g+WIBw9Uvy6F5k= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787817053; c=relaxed/simple; bh=ombfWduYmRzuQM+qSTOW1ygfQL83duLTVFuIzr1u56M=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=f+rCf3PkewRMHzvj/QvDx6T9cQ4ULYOP78U3RjWkeO8jTRb8iXn0U82GbALl2U1bDkFMyWRhc1mJzEya9VS36uJO/WOuKw0ZcSvtkjR05wov2Iz5eOJyg5l4kKO0ksKycBi/QnOuLxdj3+QACsLUx8O4vSmZHvRoA381CQIWcSs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=jWQVZIjG; arc=none smtp.client-ip=209.85.210.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jWQVZIjG" Received: by mail-pf1-f171.google.com with SMTP id d2e1a72fcca58-851d4de33a3so81755b3a.2 for ; Thu, 27 Aug 2026 00:50:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787817051; x=1788421851; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=QJxok4wgUB8E2b2EBexjp7DU43elN9IiB4VyNdbeBMI=; b=jWQVZIjGm1P24DRfClznD9+7yzaeXVPc0wzpMJbuAd/RNGPmN7gVHVYvo6Zc8OjUfg CKiJ7OW2aKP6+T0mhBxULF00v7cqfLQXZgwcbwkeN5dIto9u7cYw8n+Zj0PSYYkmXhsx l9IdtO+Dr8tCqbzJixZu/rzCfiDKn0cGzedji1xD2swihZIX3u4jL9cLMuDcmGbfCdzU OKU5gtW5b0+Rd2C2y915qsfdX0OGLeOii9uwNrFIfCe/ODxrthMqcjvmdnLplepyw0wL bG6j7t55kP7awbmZLX304OyhBrolPJf6QFHXqqZJcFHVi1TavE+3zO4ORvgNNk6NDBLZ WB2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787817051; x=1788421851; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=QJxok4wgUB8E2b2EBexjp7DU43elN9IiB4VyNdbeBMI=; b=VF6gy/SCL1q5vl8p2osOfwoAppfloLPfEODukssu1gGUFHC3f2gftLs31S77apFaDu wNjABKaiWsncIukRQBtJzZLMTCT2DNS9gOFA+0BIyYW38gyP6KqZj5sQTdWDKgyP15Kg mjO3vaFjIMnZJ0MSnf87YwNKo3k1vTzFbEjfs2hLy8k1gLTdyPPxvxEqUzOlpEtRFnho hxS3/UCrh9w4QRcsQOF6bgrzN7/55LD09Md6otdf3UXVtUph2Ri+bu4slrnd3gYf/yZB 8kRVnkREqf8TI36zYSA3R6dS1wc+jBya2k1QAWd1ps+odBVBgrcrMyAf93AIRYKjCKQo RADw== X-Forwarded-Encrypted: i=1; AHgh+Roo2+JVGphY6h1rkyJzI93lCT1XjC5UlgPPkW4l90cIfPLkHVn+0lZUKvMaEYqJTVVKpShMAsGYzd8iMZs=@vger.kernel.org X-Gm-Message-State: AFuF++kCcJJv2nJS5V97XohIEJ0pgfLruYrckpeJ2Uxs5DwEH/HE3Ekz 5gurdhrVXj/Vb5CnVHB93cDb0pxM98sWlTdYPcVdA7urs63W5dpdWLNA X-Gm-Gg: AR+sD12IZU2Ovfnp/eM5bHaJhetMqVNXlES17233+mVr6MQ2w5SVu2eyITH8nk/bBrn /rLCPP8EfcuEJtNIuET/awtVZ9o9lyYV2MwdDehYkYV+s5y6bi72FQQLB6o0AwmYGE5p8c3ky8i py8v3WB6zbRuY28JMT8w3/urf2JYy1gLa7O8vVFApLcDGKo1iDfLX2vtFgk8QdM0poFYjWIs6zt 8KPzhqLttIaXgkJTLA9wLdafgtOIdMUvecLGrWZb1D9baykZ8op2Z510SXig7CnBc6z8KA+wKGT tDqTCW4wBkVKyeNAP9u18pe+llChtcYU7qO0YkHAM8C3a2se0/+KpNUDwTwixjmXA87W60DIhMi pCJ3ah+XkPwXAEvFfhtV6p8zJFywN/yEKp1VF1nGGtXhnlVHEE8njIQlPMctsRPUNOnQlwPsQq6 zk2dxBzbo5iRiX8dg2oOLXRnGuEQtxe4whQDaZxtNv8dTJp3xB/rG9CNaml/PMnEt3DKXEka4bP +OQNM/zn0l1Wy47ukZMpBuKgzTX2Q== X-Received: by 2002:a05:6a21:c147:20b0:3d1:56e6:daad with SMTP id adf61e73a8af0-3d156e6db8emr2237492637.0.1787817050967; Thu, 27 Aug 2026 00:50:50 -0700 (PDT) Received: from localhost.localdomain ([189.1.242.96]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-cc1bec80fdesm1761524a12.24.2026.08.27.00.50.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Aug 2026 00:50:50 -0700 (PDT) From: Yiqi Sun To: marcelo.leitner@gmail.com, lucien.xin@gmail.com Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, linux-sctp@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Yiqi Sun Subject: [PATCH net] sctp: avoid livelock while updating retransmit path Date: Thu, 27 Aug 2026 15:50:06 +0800 Message-Id: <20260827075006.3979566-1-sunyiqixm@gmail.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit sctp_assoc_update_retran_path() walks the association transport list from the current retransmit path's successor and stops once it reaches the current retransmit path again. However, the loop skips transports in SCTP_UNCONFIRMED state before checking for the wraparound condition. This makes the loop non-terminating when the association contains only UNCONFIRMED transports at that point and asoc->peer.retran_path is also UNCONFIRMED. One way to reach that state is through ASCONF wildcard DEL-IP processing after an unconfirmed address is selected as the primary transport. sctp_assoc_del_nonprimary_peers() then removes the other transports one by one; when removing the current retran_path, sctp_assoc_rm_peer() calls sctp_assoc_update_retran_path() before unlinking it. If the remaining candidate and the current retran_path are both UNCONFIRMED, the loop repeatedly continues before it can observe that it has completed a full pass. The same reproducer that exercised the bug fixed by commit 9b2854f86f0b ("sctp: don't free the ASCONF's own transport in DEL-IP processing") can still trigger this CPU stall after that fix is applied. With the UAF prevented, the ASCONF processing no longer dereferences the freed transport, but it can still reach the retransmit-path update described above and spin in the all-UNCONFIRMED case. Fix this by remembering whether the current transport is the original retran_path, still considering it as a candidate when it is not UNCONFIRMED, and then breaking after the candidate logic. This preserves the existing fallback semantics while making the full-pass termination independent of the transport state. Also restore the NULL guard around the retran_path assignment. In the all-UNCONFIRMED case there is no eligible replacement transport, and installing NULL would leave later retransmit-path users and the debug print with a NULL path. Fixes: 4c47af4d5eb2 ("net: sctp: rework multihoming retransmission path selection to rfc4960") Signed-off-by: Yiqi Sun --- net/sctp/associola.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/net/sctp/associola.c b/net/sctp/associola.c index c0512c827d0f..6f19eb0b01e2 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1272,6 +1272,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) { struct sctp_transport *trans = asoc->peer.retran_path; struct sctp_transport *trans_next = NULL; + bool last = false; /* We're done as we only have the one and only path. */ if (asoc->peer.transport_count == 1) @@ -1289,18 +1290,20 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) /* Manually skip the head element. */ if (&trans->transports == &asoc->peer.transport_addr_list) continue; - if (trans->state == SCTP_UNCONFIRMED) - continue; - trans_next = sctp_trans_elect_best(trans, trans_next); - /* Active is good enough for immediate return. */ - if (trans_next->state == SCTP_ACTIVE) - break; + last = trans == asoc->peer.retran_path; + if (trans->state != SCTP_UNCONFIRMED) { + trans_next = sctp_trans_elect_best(trans, trans_next); + /* Active is good enough for immediate return. */ + if (trans_next->state == SCTP_ACTIVE) + break; + } /* We've reached the end, time to update path. */ - if (trans == asoc->peer.retran_path) + if (last) break; } - asoc->peer.retran_path = trans_next; + if (trans_next) + asoc->peer.retran_path = trans_next; pr_debug("%s: association:%p updated new path to addr:%pISpc\n", __func__, asoc, &asoc->peer.retran_path->ipaddr.sa); -- 2.34.1