| From ccf7abb93af09ad0868ae9033d1ca8108bdaec82 Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Fri, 3 Feb 2017 14:59:38 -0800 |
| Subject: [PATCH] tcp: avoid infinite loop in tcp_splice_read() |
| |
| commit ccf7abb93af09ad0868ae9033d1ca8108bdaec82 upstream. |
| |
| Splicing from TCP socket is vulnerable when a packet with URG flag is |
| received and stored into receive queue. |
| |
| __tcp_splice_read() returns 0, and sk_wait_data() immediately |
| returns since there is the problematic skb in queue. |
| |
| This is a nice way to burn cpu (aka infinite loop) and trigger |
| soft lockups. |
| |
| Again, this gem was found by syzkaller tool. |
| |
| Fixes: 9c55e01c0cc8 ("[TCP]: Splice receive support.") |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Reported-by: Dmitry Vyukov <dvyukov@google.com> |
| Cc: Willy Tarreau <w@1wt.eu> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| |
| diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c |
| index 4a044964da66..0efb4c7f6704 100644 |
| --- a/net/ipv4/tcp.c |
| +++ b/net/ipv4/tcp.c |
| @@ -770,6 +770,12 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, |
| ret = -EAGAIN; |
| break; |
| } |
| + /* if __tcp_splice_read() got nothing while we have |
| + * an skb in receive queue, we do not want to loop. |
| + * This might happen with URG data. |
| + */ |
| + if (!skb_queue_empty(&sk->sk_receive_queue)) |
| + break; |
| sk_wait_data(sk, &timeo, NULL); |
| if (signal_pending(current)) { |
| ret = sock_intr_errno(timeo); |
| -- |
| 2.12.0 |
| |