aboutgitcodebugslistschat
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2025-10-02 00:41:54 +0200
committerStefano Brivio <sbrivio@redhat.com>2025-10-07 22:22:39 +0200
commitb145441913eef6f8885b6b84531e944ff593790c (patch)
tree4434c7e4b8877eaa584496a51f6f7b0ee4155096
parent8efa80b51f9f52082954aa26719b36a9ec367567 (diff)
downloadpasst-b145441913eef6f8885b6b84531e944ff593790c.tar
passt-b145441913eef6f8885b6b84531e944ff593790c.tar.gz
passt-b145441913eef6f8885b6b84531e944ff593790c.tar.bz2
passt-b145441913eef6f8885b6b84531e944ff593790c.tar.lz
passt-b145441913eef6f8885b6b84531e944ff593790c.tar.xz
passt-b145441913eef6f8885b6b84531e944ff593790c.tar.zst
passt-b145441913eef6f8885b6b84531e944ff593790c.zip
tcp: Don't consider FIN flags with mismatching sequence
If a guest or container sends us a FIN segment but its sequence number doesn't match the highest sequence of data we *accepted* (not necessarily the highest sequence we received), that is, conn->seq_from_tap, plus any data we're accepting in the current batch, we should discard the flag (not necessarily the segment), because there's still data we need to receive (again) before the end of the stream. If we consider those FIN flags as such, we'll end up in the situation described below. Here, 192.168.10.102 is a HTTP server in a Podman container, and 192.168.10.44 is a client fetching approximately 121 KB of data from it: 82 2.026811 192.168.10.102 → 192.168.10.44 54 TCP 55414 → 44992 [FIN, ACK] Seq=121441 Ack=143 Win=65536 Len=0 the server is done sending 83 2.026898 192.168.10.44 → 192.168.10.102 54 TCP 44992 → 55414 [ACK] Seq=143 Ack=114394 Win=216192 Len=0 pasta (client) acknowledges a previous sequence, because of a short sendmsg() 84 2.027324 192.168.10.44 → 192.168.10.102 54 TCP 44992 → 55414 [FIN, ACK] Seq=143 Ack=114394 Win=216192 Len=0 pasta (client) sends FIN, ACK as the client has no more data to send (a single GET request), while still acknowledging a previous sequence, because the retransmission didn't happen yet 85 2.027349 192.168.10.102 → 192.168.10.44 54 TCP 55414 → 44992 [ACK] Seq=121442 Ack=144 Win=65536 Len=0 the server acknowledges the FIN, ACK 86 2.224125 192.168.10.102 → 192.168.10.44 4150 TCP [TCP Retransmission] 55414 → 44992 [ACK] Seq=114394 Ack=144 Win=65536 Len=4096 [TCP segment of a reassembled PDU] and finally a retransmission comes, but as we wrongly switched to the CLOSE-WAIT state, 87 2.224202 192.168.10.44 → 192.168.10.102 54 TCP 44992 → 55414 [RST] Seq=144 Win=0 Len=0 we consider frame #86 as an acknowledgement for the FIN segment we sent, and close the connection, while we still had to re-receive (and finally send) the missing data segment, instead. Link: https://github.com/containers/podman/issues/27179 Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r--tcp.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/tcp.c b/tcp.c
index a648174..0cca3de 100644
--- a/tcp.c
+++ b/tcp.c
@@ -1774,7 +1774,7 @@ static int tcp_data_from_tap(const struct ctx *c, struct tcp_tap_conn *conn,
}
}
- if (th->fin)
+ if (th->fin && seq == seq_from_tap)
fin = 1;
if (!len)