]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
tcp: relookup sock for RST+ACK packets handled by obsolete req sock
authorAlexander Ovechkin <ovov@yandex-team.ru>
Mon, 15 Mar 2021 11:05:45 +0000 (14:05 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 Mar 2021 12:30:20 +0000 (14:30 +0200)
[ Upstream commit 7233da86697efef41288f8b713c10c2499cffe85 ]

Currently tcp_check_req can be called with obsolete req socket for which big
socket have been already created (because of CPU race or early demux
assigning req socket to multiple packets in gro batch).

Commit e0f9759f530bf789e984 ("tcp: try to keep packet if SYN_RCV race
is lost") added retry in case when tcp_check_req is called for PSH|ACK packet.
But if client sends RST+ACK immediatly after connection being
established (it is performing healthcheck, for example) retry does not
occur. In that case tcp_check_req tries to close req socket,
leaving big socket active.

Fixes: e0f9759f530 ("tcp: try to keep packet if SYN_RCV race is lost")
Signed-off-by: Alexander Ovechkin <ovov@yandex-team.ru>
Reported-by: Oleg Senin <olegsenin@yandex-team.ru>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/net/inet_connection_sock.h
net/ipv4/inet_connection_sock.c
net/ipv4/tcp_minisocks.c

index 111d7771b208150d4e6f445b2675648b4de0eb7d..aa92af3dd444d7fb30ecfccf9f77a5e309885bdd 100644 (file)
@@ -284,7 +284,7 @@ static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
        return inet_csk_reqsk_queue_len(sk) >= sk->sk_max_ack_backlog;
 }
 
-void inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req);
+bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req);
 void inet_csk_reqsk_queue_drop_and_put(struct sock *sk, struct request_sock *req);
 
 static inline void inet_csk_prepare_for_destroy_sock(struct sock *sk)
index 6bd7ca09af03dd5385096f749cf05afecb4b7795..fd472eae4f5ca65f8a9722f4b3d156bd44f3a142 100644 (file)
@@ -705,12 +705,15 @@ static bool reqsk_queue_unlink(struct request_sock *req)
        return found;
 }
 
-void inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req)
+bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req)
 {
-       if (reqsk_queue_unlink(req)) {
+       bool unlinked = reqsk_queue_unlink(req);
+
+       if (unlinked) {
                reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req);
                reqsk_put(req);
        }
+       return unlinked;
 }
 EXPORT_SYMBOL(inet_csk_reqsk_queue_drop);
 
index 0055ae0a3bf840c737f5f61fb1ef683208387e32..7513ba45553dba4de8fc9b85b2c18874f1ecbe22 100644 (file)
@@ -804,8 +804,11 @@ embryonic_reset:
                tcp_reset(sk, skb);
        }
        if (!fastopen) {
-               inet_csk_reqsk_queue_drop(sk, req);
-               __NET_INC_STATS(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
+               bool unlinked = inet_csk_reqsk_queue_drop(sk, req);
+
+               if (unlinked)
+                       __NET_INC_STATS(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
+               *req_stolen = !unlinked;
        }
        return NULL;
 }