From ef9d6889ab30e525f8ef874bfca0ccc013f4a271 Mon Sep 17 00:00:00 2001 From: Hongbo Li Date: Wed, 23 Oct 2019 17:28:36 +0800 Subject: [PATCH] net: fix memory limit bug in tcp_fragment upstream: b6653b3629e5 ("tcp: refine memory limit test in tcp_fragment") b617158dc096 ("tcp: be more careful in tcp_fragment") tcp_fragment() might be called for skbs in the write queue. Memory limits might have been exceeded because tcp_sendmsg() only checks limits at full skb (64KB) boundaries. Therefore, we need to make sure tcp_fragment() wont punish applications that might have setup very low SO_SNDBUF values. 75c119afe14f ("tcp: implement rb-tree based retransmit queue") separate transmit queue to transmit queue and retransmit queue. b6653b36 adds some check to the transmit queue, b617158dc adds some check on the rtx queue. So we only backport the b6653b36 patch. use tcp_send_head(sk) instead of TCP_FRAG_IN_WRITE_QUEUE. Signed-off-by: Hongbo Li --- net/ipv4/tcp_output.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 34c349025..f14be2ba7 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1270,7 +1270,8 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, if (nsize < 0) nsize = 0; - if (unlikely((sk->sk_wmem_queued >> 1) > sk->sk_sndbuf)) { + if (unlikely((sk->sk_wmem_queued >> 1) > sk->sk_sndbuf && + skb != tcp_send_head(sk))) { NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPWQUEUETOOBIG); return -ENOMEM; }