tcp: diag: add support for TIME_WAIT sockets to tcp_abort()
authorEric Dumazet <edumazet@google.com>
Mon, 27 Jun 2022 12:10:38 +0000 (12:10 +0000)
committerJakub Kicinski <kuba@kernel.org>
Wed, 29 Jun 2022 04:26:56 +0000 (21:26 -0700)
Currently, "ss -K -ta ..." does not support TIME_WAIT sockets.

Issue has been raised at least two times in the past [1] [2]
it is time to fix it.

[1] https://lore.kernel.org/netdev/ba65f579-4e69-ae0d-4770-bc6234beb428@gmail.com/
[2] https://lore.kernel.org/netdev/CANn89i+R9RgmD=AQ4vX1Vb_SQAj4c3fi7-ZtQz-inYY4Sq4CMQ@mail.gmail.com/T/

While we are at it, use inet_sk_state_load() while tcp_abort()
does not hold a lock on the socket.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Tested-by: Muhammad Usama Anjum <usama.anjum@collabora.com>
Link: https://lore.kernel.org/r/20220627121038.226500-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/tcp.c

index f730945..d2ca56a 100644 (file)
@@ -4531,16 +4531,24 @@ EXPORT_SYMBOL_GPL(tcp_done);
 
 int tcp_abort(struct sock *sk, int err)
 {
-       if (!sk_fullsock(sk)) {
-               if (sk->sk_state == TCP_NEW_SYN_RECV) {
-                       struct request_sock *req = inet_reqsk(sk);
+       int state = inet_sk_state_load(sk);
 
-                       local_bh_disable();
-                       inet_csk_reqsk_queue_drop(req->rsk_listener, req);
-                       local_bh_enable();
-                       return 0;
-               }
-               return -EOPNOTSUPP;
+       if (state == TCP_NEW_SYN_RECV) {
+               struct request_sock *req = inet_reqsk(sk);
+
+               local_bh_disable();
+               inet_csk_reqsk_queue_drop(req->rsk_listener, req);
+               local_bh_enable();
+               return 0;
+       }
+       if (state == TCP_TIME_WAIT) {
+               struct inet_timewait_sock *tw = inet_twsk(sk);
+
+               refcount_inc(&tw->tw_refcnt);
+               local_bh_disable();
+               inet_twsk_deschedule_put(tw);
+               local_bh_enable();
+               return 0;
        }
 
        /* Don't race with userspace socket closes such as tcp_close. */