Skip to content

Commit 7c678b8

Browse files
Eric DumazetSomasundaram Krishnasamy
authored andcommitted
tcp: add sanity tests in tcp_add_backlog()
Richard and Bruno both reported that my commit added a bug, and Bruno was able to determine the problem came when a segment wih a FIN packet was coalesced to a prior one in tcp backlog queue. It turns out the header prediction in tcp_rcv_established() looks back to TCP headers in the packet, not in the metadata (aka TCP_SKB_CB(skb)->tcp_flags) The fast path in tcp_rcv_established() is not supposed to handle a FIN flag (it does not call tcp_fin()) Therefore we need to make sure to propagate the FIN flag, so that the coalesced packet does not go through the fast path, the same than a GRO packet carrying a FIN flag. While we are at it, make sure we do not coalesce packets with RST or SYN, or if they do not have ACK set. Many thanks to Richard and Bruno for pinpointing the bad commit, and to Richard for providing a first version of the fix. Fixes: 4f693b5 ("tcp: implement coalescing on backlog queue") Signed-off-by: Eric Dumazet <[email protected]> Reported-by: Richard Purdie <[email protected]> Reported-by: Bruno Prémont <[email protected]> Signed-off-by: David S. Miller <[email protected]> (cherry picked from commit ca2fe29) Orabug: 31786543 Signed-off-by: Somasundaram Krishnasamy <[email protected]> Reviewed-by: Jack Vogel <[email protected]>
1 parent 6eab869 commit 7c678b8

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

net/ipv4/tcp_ipv4.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1690,7 +1690,9 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
16901690
if (TCP_SKB_CB(tail)->end_seq != TCP_SKB_CB(skb)->seq ||
16911691
TCP_SKB_CB(tail)->ip_dsfield != TCP_SKB_CB(skb)->ip_dsfield ||
16921692
((TCP_SKB_CB(tail)->tcp_flags |
1693-
TCP_SKB_CB(skb)->tcp_flags) & TCPHDR_URG) ||
1693+
TCP_SKB_CB(skb)->tcp_flags) & (TCPHDR_SYN | TCPHDR_RST | TCPHDR_URG)) ||
1694+
!((TCP_SKB_CB(tail)->tcp_flags &
1695+
TCP_SKB_CB(skb)->tcp_flags) & TCPHDR_ACK) ||
16941696
((TCP_SKB_CB(tail)->tcp_flags ^
16951697
TCP_SKB_CB(skb)->tcp_flags) & (TCPHDR_ECE | TCPHDR_CWR)) ||
16961698
#ifdef CONFIG_TLS_DEVICE
@@ -1709,6 +1711,15 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
17091711
if (after(TCP_SKB_CB(skb)->ack_seq, TCP_SKB_CB(tail)->ack_seq))
17101712
TCP_SKB_CB(tail)->ack_seq = TCP_SKB_CB(skb)->ack_seq;
17111713

1714+
/* We have to update both TCP_SKB_CB(tail)->tcp_flags and
1715+
* thtail->fin, so that the fast path in tcp_rcv_established()
1716+
* is not entered if we append a packet with a FIN.
1717+
* SYN, RST, URG are not present.
1718+
* ACK is set on both packets.
1719+
* PSH : we do not really care in TCP stack,
1720+
* at least for 'GRO' packets.
1721+
*/
1722+
thtail->fin |= th->fin;
17121723
TCP_SKB_CB(tail)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags;
17131724

17141725
if (TCP_SKB_CB(skb)->has_rxtstamp) {

0 commit comments

Comments
 (0)