]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
UBUNTU: SAUCE: tcp: tcp_fragment() should apply sane memory limits
authorEric Dumazet <edumazet@google.com>
Fri, 31 May 2019 20:59:30 +0000 (20:59 +0000)
committerMarcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tue, 4 Jun 2019 20:32:09 +0000 (17:32 -0300)
Jonathan Looney reported that a malicious peer can force a sender
to fragment its retransmit queue into tiny skbs, inflating memory
usage and/or overflow 32bit counters.

TCP allows an application to queue up to sk_sndbuf bytes,
so we need to give some allowance for non malicious splitting
of retransmit queue.

A new SNMP counter is added to monitor how many times TCP
did not allow to split an skb if the allowance was exceeded.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Jonathan Looney <jtl@netflix.com>
Cc: Bruce Curtis <brucec@netflix.com>
Cc: Neal Cardwell <ncardwell@google.com>
CC: Yuchung Cheng <ycheng@google.com>
BugLink: https://bugs.launchpad.net/bugs/1831638
[tyhicks: Adjust context of SNMP enums]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Signed-off-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
include/uapi/linux/snmp.h
net/ipv4/proc.c
net/ipv4/tcp_output.c

index 33a70ece462f00ee2be8c78c552b4471ddce9fcb..0b3c2d12761b9b986dd0683098cf41f9dae3e762 100644 (file)
@@ -276,6 +276,7 @@ enum
        LINUX_MIB_TCPKEEPALIVE,                 /* TCPKeepAlive */
        LINUX_MIB_TCPMTUPFAIL,                  /* TCPMTUPFail */
        LINUX_MIB_TCPMTUPSUCCESS,               /* TCPMTUPSuccess */
+       LINUX_MIB_TCPWQUEUETOOBIG,              /* TCPWqueueTooBig */
        __LINUX_MIB_MAX
 };
 
index 9f37c47278616e3752ccb94f2754f22ff62d0394..36921e65b281a230b45567e1ebe2caa2c89ee912 100644 (file)
@@ -297,6 +297,7 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPKeepAlive", LINUX_MIB_TCPKEEPALIVE),
        SNMP_MIB_ITEM("TCPMTUPFail", LINUX_MIB_TCPMTUPFAIL),
        SNMP_MIB_ITEM("TCPMTUPSuccess", LINUX_MIB_TCPMTUPSUCCESS),
+       SNMP_MIB_ITEM("TCPWqueueTooBig", LINUX_MIB_TCPWQUEUETOOBIG),
        SNMP_MIB_SENTINEL
 };
 
index 1ead7d0b59de0bc88e76ce2d4284f366aa3e3e08..57d2735db97b90c543e8d5d970424b2269b972c5 100644 (file)
@@ -1321,6 +1321,11 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
        if (nsize < 0)
                nsize = 0;
 
+       if (unlikely((sk->sk_wmem_queued >> 1) > sk->sk_sndbuf)) {
+               NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPWQUEUETOOBIG);
+               return -ENOMEM;
+       }
+
        if (skb_unclone(skb, gfp))
                return -ENOMEM;