diff options
| author | Michael Bommarito <michael.bommarito@gmail.com> | 2026-06-10 08:40:02 -0400 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-06-11 16:01:16 -0700 |
| commit | ab3e10b44ba5411779aac7afd2477917dd77750f (patch) | |
| tree | 517e112e86ba8c90bc8fe5e25f1e7b45f40b0d9c /net/tipc | |
| parent | 86b0c540e2ea397cde021eecd24145f7c16a3d4e (diff) | |
| download | linux-next-ab3e10b44ba5411779aac7afd2477917dd77750f.tar.gz linux-next-ab3e10b44ba5411779aac7afd2477917dd77750f.zip | |
tipc: prevent snt_unacked underflow on CONN_ACK
tipc_sk_conn_proto_rcv() subtracts the peer-supplied connection ack count
from the unsigned 16-bit send counter snt_unacked without checking that it
does not exceed the number of messages actually outstanding:
tsk->snt_unacked -= msg_conn_ack(hdr);
msg_conn_ack() is read straight from a received CONN_MANAGER/CONN_ACK
message. If the ack count is larger than snt_unacked, the subtraction
wraps to a near-maximum value, leaving tsk_conn_cong() permanently true
and starving the connection of further transmits.
Validate the ACK count at the start of the CONN_ACK block and drop the
message if it acknowledges more messages than are outstanding. A peer (or,
for a local connection, the connected peer socket) can otherwise wedge a
TIPC connection's send side by sending an oversized connection ack.
Fixes: 10724cc7bb78 ("tipc: redesign connection-level flow control")
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech>
Link: https://patch.msgid.link/20260610124003.3831170-3-michael.bommarito@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/socket.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 9329919fb07f..f64f7a35b5c9 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1362,6 +1362,9 @@ static void tipc_sk_conn_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb, __skb_queue_tail(xmitq, skb); return; } else if (mtyp == CONN_ACK) { + if (tsk->snt_unacked < msg_conn_ack(hdr)) + goto exit; + was_cong = tsk_conn_cong(tsk); tipc_sk_push_backlog(tsk, msg_nagle_ack(hdr)); tsk->snt_unacked -= msg_conn_ack(hdr); |
