aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_ipv4.c
diff options
context:
space:
mode:
authorEric Dumazet <[email protected]>2017-08-15 00:44:43 +0000
committerDavid S. Miller <[email protected]>2017-08-15 05:31:27 +0000
commitd624d276d1ddacbcb12ad96832ce0c7b82cd25db (patch)
treeb78aa1f2060bf2aa70b13af5d58a7bca994af306 /net/ipv4/tcp_ipv4.c
parentdccp: purge write queue in dccp_destroy_sock() (diff)
downloadkernel-d624d276d1ddacbcb12ad96832ce0c7b82cd25db.tar.gz
kernel-d624d276d1ddacbcb12ad96832ce0c7b82cd25db.zip
tcp: fix possible deadlock in TCP stack vs BPF filter
Filtering the ACK packet was not put at the right place. At this place, we already allocated a child and put it into accept queue. We absolutely need to call tcp_child_process() to release its spinlock, or we will deadlock at accept() or close() time. Found by syzkaller team (Thanks a lot !) Fixes: 8fac365f63c8 ("tcp: Add a tcp_filter hook before handle ack packet") Signed-off-by: Eric Dumazet <[email protected]> Reported-by: Dmitry Vyukov <[email protected]> Cc: Chenbo Feng <[email protected]> Signed-off-by: David S. Miller <[email protected]>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r--net/ipv4/tcp_ipv4.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index a20e7f03d5f7..e9252c7df809 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1722,6 +1722,8 @@ process:
*/
sock_hold(sk);
refcounted = true;
+ if (tcp_filter(sk, skb))
+ goto discard_and_relse;
nsk = tcp_check_req(sk, skb, req, false);
if (!nsk) {
reqsk_put(req);
@@ -1729,8 +1731,6 @@ process:
}
if (nsk == sk) {
reqsk_put(req);
- } else if (tcp_filter(sk, skb)) {
- goto discard_and_relse;
} else if (tcp_child_process(sk, nsk, skb)) {
tcp_v4_send_reset(nsk, skb);
goto discard_and_relse;