tcp: Check for filled TCP option space before SACK
authorMat Martineau <mathew.j.martineau@linux.intel.com>
Thu, 9 Jan 2020 15:59:22 +0000 (07:59 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 10 Jan 2020 02:41:41 +0000 (18:41 -0800)
Update the SACK check to work with zero option space available, a case
that's possible with MPTCP but not MD5+TS. Maintained only one
conditional branch for insufficient SACK space.

v1 -> v2:
- Moves the check inside the SACK branch by taking recent SACK fix:

    9424e2e7ad93 (tcp: md5: fix potential overestimation of TCP option space)

  in to account, but modifies it to work in MPTCP scenarios beyond the
  MD5+TS corner case.

Co-developed-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/tcp_output.c

index 3ce7fe1c4076e27ed73a34f0a70101f3f5254ab4..05109d0c675b814e4975614d6eef8b074e6ed95a 100644 (file)
@@ -754,13 +754,17 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb
        eff_sacks = tp->rx_opt.num_sacks + tp->rx_opt.dsack;
        if (unlikely(eff_sacks)) {
                const unsigned int remaining = MAX_TCP_OPTION_SPACE - size;
+               if (unlikely(remaining < TCPOLEN_SACK_BASE_ALIGNED +
+                                        TCPOLEN_SACK_PERBLOCK))
+                       return size;
+
                opts->num_sack_blocks =
                        min_t(unsigned int, eff_sacks,
                              (remaining - TCPOLEN_SACK_BASE_ALIGNED) /
                              TCPOLEN_SACK_PERBLOCK);
-               if (likely(opts->num_sack_blocks))
-                       size += TCPOLEN_SACK_BASE_ALIGNED +
-                               opts->num_sack_blocks * TCPOLEN_SACK_PERBLOCK;
+
+               size += TCPOLEN_SACK_BASE_ALIGNED +
+                       opts->num_sack_blocks * TCPOLEN_SACK_PERBLOCK;
        }
 
        return size;