Commit 9094a474 authored by Eric Dumazet's avatar Eric Dumazet Committed by Stefan Bader

UBUNTU: SAUCE: tcp: tcp_fragment() should apply sane memory limits

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: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarJonathan 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 (Remote denial of service (resource exhaustion) caused by TCP SACK scoreboard manipulation (LP: #1831638))

[tyhicks: Adjust context of SNMP enums]
Signed-off-by: default avatarTyler Hicks <tyhicks@canonical.com>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
parent db455250
...@@ -281,6 +281,7 @@ enum ...@@ -281,6 +281,7 @@ enum
LINUX_MIB_TCPKEEPALIVE, /* TCPKeepAlive */ LINUX_MIB_TCPKEEPALIVE, /* TCPKeepAlive */
LINUX_MIB_TCPMTUPFAIL, /* TCPMTUPFail */ LINUX_MIB_TCPMTUPFAIL, /* TCPMTUPFail */
LINUX_MIB_TCPMTUPSUCCESS, /* TCPMTUPSuccess */ LINUX_MIB_TCPMTUPSUCCESS, /* TCPMTUPSuccess */
LINUX_MIB_TCPWQUEUETOOBIG, /* TCPWqueueTooBig */
__LINUX_MIB_MAX __LINUX_MIB_MAX
}; };
......
...@@ -303,6 +303,7 @@ static const struct snmp_mib snmp4_net_list[] = { ...@@ -303,6 +303,7 @@ static const struct snmp_mib snmp4_net_list[] = {
SNMP_MIB_ITEM("TCPKeepAlive", LINUX_MIB_TCPKEEPALIVE), SNMP_MIB_ITEM("TCPKeepAlive", LINUX_MIB_TCPKEEPALIVE),
SNMP_MIB_ITEM("TCPMTUPFail", LINUX_MIB_TCPMTUPFAIL), SNMP_MIB_ITEM("TCPMTUPFail", LINUX_MIB_TCPMTUPFAIL),
SNMP_MIB_ITEM("TCPMTUPSuccess", LINUX_MIB_TCPMTUPSUCCESS), SNMP_MIB_ITEM("TCPMTUPSuccess", LINUX_MIB_TCPMTUPSUCCESS),
SNMP_MIB_ITEM("TCPWqueueTooBig", LINUX_MIB_TCPWQUEUETOOBIG),
SNMP_MIB_SENTINEL SNMP_MIB_SENTINEL
}; };
......
...@@ -1163,6 +1163,11 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, ...@@ -1163,6 +1163,11 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len,
if (nsize < 0) if (nsize < 0)
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)) if (skb_unclone(skb, gfp))
return -ENOMEM; return -ENOMEM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment