mirror of
https://github.com/torvalds/linux.git
synced 2026-10-13 22:01:02 +02:00
sctp: avoid livelock while updating retransmit path
sctp_assoc_update_retran_path() can loop forever when every remaining
transport, including retran_path, is SCTP_UNCONFIRMED: the state check
runs before the wraparound test, so the loop cannot observe that it has
completed a full pass.
Fix this by considering a transport only when it is not UNCONFIRMED,
then checking whether the walk has returned to retran_path. This makes
the full-pass termination independent of the transport state while
preserving the existing fallback selection semantics.
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: 4c47af4d5e ("net: sctp: rework multihoming retransmission path selection to rfc4960")
Signed-off-by: Yiqi Sun <sunyiqixm@gmail.com>
Acked-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/20260915095017.942213-1-sunyiqixm@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
6c01564da3
commit
d2c31b8374
|
|
@ -1289,18 +1289,19 @@ 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;
|
||||
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)
|
||||
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user