| From 2527557a08f9d60e9fd38737b5a029b480af50bd Mon Sep 17 00:00:00 2001 |
| From: Thomas Graf <tgraf@suug.ch> |
| Date: Thu, 11 Apr 2013 10:57:18 +0000 |
| Subject: tcp: Reallocate headroom if it would overflow csum_start |
| |
| |
| From: Thomas Graf <tgraf@suug.ch> |
| |
| [ Upstream commit 50bceae9bd3569d56744882f3012734d48a1d413 ] |
| |
| If a TCP retransmission gets partially ACKed and collapsed multiple |
| times it is possible for the headroom to grow beyond 64K which will |
| overflow the 16bit skb->csum_start which is based on the start of |
| the headroom. It has been observed rarely in the wild with IPoIB due |
| to the 64K MTU. |
| |
| Verify if the acking and collapsing resulted in a headroom exceeding |
| what csum_start can cover and reallocate the headroom if so. |
| |
| A big thank you to Jim Foraker <foraker1@llnl.gov> and the team at |
| LLNL for helping out with the investigation and testing. |
| |
| Reported-by: Jim Foraker <foraker1@llnl.gov> |
| Signed-off-by: Thomas Graf <tgraf@suug.ch> |
| Acked-by: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv4/tcp_output.c | 8 ++++++-- |
| 1 file changed, 6 insertions(+), 2 deletions(-) |
| |
| --- a/net/ipv4/tcp_output.c |
| +++ b/net/ipv4/tcp_output.c |
| @@ -2154,8 +2154,12 @@ int tcp_retransmit_skb(struct sock *sk, |
| */ |
| TCP_SKB_CB(skb)->when = tcp_time_stamp; |
| |
| - /* make sure skb->data is aligned on arches that require it */ |
| - if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) { |
| + /* make sure skb->data is aligned on arches that require it |
| + * and check if ack-trimming & collapsing extended the headroom |
| + * beyond what csum_start can cover. |
| + */ |
| + if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) || |
| + skb_headroom(skb) >= 0xFFFF)) { |
| struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, |
| GFP_ATOMIC); |
| err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : |