71 lines
2.4 KiB
Diff
71 lines
2.4 KiB
Diff
From: Eric Dumazet <edumazet@google.com>
|
|
Date: Mon, 17 Jun 2019 10:03:52 -0700
|
|
Subject: [PATCH net 2/4] tcp: tcp_fragment() should apply sane memory limits
|
|
Origin: https://patchwork.ozlabs.org/patch/1117156/
|
|
|
|
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.
|
|
|
|
Note that this counter might increase in the case applications
|
|
use SO_SNDBUF socket option to lower sk_sndbuf.
|
|
|
|
CVE-2019-11478 : tcp_fragment, prevent fragmenting a packet when the
|
|
socket is already using more than half the allowed space
|
|
|
|
Signed-off-by: Eric Dumazet <edumazet@google.com>
|
|
Reported-by: Jonathan Looney <jtl@netflix.com>
|
|
Acked-by: Neal Cardwell <ncardwell@google.com>
|
|
Acked-by: Yuchung Cheng <ycheng@google.com>
|
|
Reviewed-by: Tyler Hicks <tyhicks@canonical.com>
|
|
Cc: Bruce Curtis <brucec@netflix.com>
|
|
Cc: Jonathan Lemon <jonathan.lemon@gmail.com>
|
|
Acked-by: Jonathan Lemon <jonathan.lemon@gmail.com>
|
|
---
|
|
include/uapi/linux/snmp.h | 1 +
|
|
net/ipv4/proc.c | 1 +
|
|
net/ipv4/tcp_output.c | 5 +++++
|
|
3 files changed, 7 insertions(+)
|
|
|
|
--- a/include/uapi/linux/snmp.h
|
|
+++ b/include/uapi/linux/snmp.h
|
|
@@ -282,6 +282,7 @@ enum
|
|
LINUX_MIB_TCPACKCOMPRESSED, /* TCPAckCompressed */
|
|
LINUX_MIB_TCPZEROWINDOWDROP, /* TCPZeroWindowDrop */
|
|
LINUX_MIB_TCPRCVQDROP, /* TCPRcvQDrop */
|
|
+ LINUX_MIB_TCPWQUEUETOOBIG, /* TCPWqueueTooBig */
|
|
__LINUX_MIB_MAX
|
|
};
|
|
|
|
--- a/net/ipv4/proc.c
|
|
+++ b/net/ipv4/proc.c
|
|
@@ -290,6 +290,7 @@ static const struct snmp_mib snmp4_net_l
|
|
SNMP_MIB_ITEM("TCPAckCompressed", LINUX_MIB_TCPACKCOMPRESSED),
|
|
SNMP_MIB_ITEM("TCPZeroWindowDrop", LINUX_MIB_TCPZEROWINDOWDROP),
|
|
SNMP_MIB_ITEM("TCPRcvQDrop", LINUX_MIB_TCPRCVQDROP),
|
|
+ SNMP_MIB_ITEM("TCPWqueueTooBig", LINUX_MIB_TCPWQUEUETOOBIG),
|
|
SNMP_MIB_SENTINEL
|
|
};
|
|
|
|
--- a/net/ipv4/tcp_output.c
|
|
+++ b/net/ipv4/tcp_output.c
|
|
@@ -1299,6 +1299,11 @@ int tcp_fragment(struct sock *sk, enum t
|
|
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;
|
|
|