lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20181123072258epcms1p8c41425598751be28f8cc05b91c7ac4b5@epcms1p8>
Date:   Fri, 23 Nov 2018 16:22:58 +0900
From:   배석진 <soukjin.bae@...sung.com>
To:     "netdev@...r.kernel.org" <netdev@...r.kernel.org>,
        "lorenzo@...gle.com" <lorenzo@...gle.com>
CC:     유금환 <geumhwan.yu@...sung.com>
Subject: Suggesting patch for tcp_close

Dear all,


This is Soukin Bae working on Samsung Elec. Mobile Division.
we have a problem with tcp closing.

in shortly, 
1. on 4-way handshking to close session
2. if ack pkt is not arrived from opposite side
3. then session can't be closed forever


in mobile device, condition 2 can be happend in various case.
like as turn off wifi or mobile data. or bad condition of air network, etc..

this could be occur in both side of connection.
when issue happened during active closing, the session remained with FIN_WAIT1 state.
and at passive closing, remained with LAST_ACK state.

---------------------------------------------------------------------------------------------
below is test result after wifi on/off repetition (without mobile data).
maybe 'Foreign Address' sent the fin-ack when wifi-off state.
so device coun't recieve ack pkt further, and the session is remained permanently.
and their count is growing up. this is resource leak.

### turn on wifi
D:\Test>adb shell netstat -npWae
Proto Recv-Q Send-Q Local Address                                 Foreign Address               State       User       Inode       PID/Program Name
tcp        0      0 127.0.0.1:5037                                0.0.0.0:*                     LISTEN      0          36357       6907/adbd
tcp6       0      0 2001:2d8:ed1c:de1c:bd94:fe5:2d9a:d8e4:58660   2404:6800:4008:c00::bc:5228   ESTABLISHED 10041      74347       6523/com.google.android.gms.persistent
tcp6       0      0 2001:2d8:ed1c:de1c:bd94:fe5:2d9a:d8e4:35148   2404:6800:4004:800::2003:80   LAST_ACK    0          0           -
tcp6       0      0 2001:2d8:ed1c:de1c:bd94:fe5:2d9a:d8e4:37512   64:ff9b::3444:f3dc:443        ESTABLISHED 10137      77447       9522/com.samsung.android.game.gos
tcp6       0      0 2001:2d8:ed1c:de1c:bd94:fe5:2d9a:d8e4:49294   2404:6800:4005:80c::2004:443  LAST_ACK    0          0           -
tcp6       1      0 2001:2d8:ed1c:de1c:bd94:fe5:2d9a:d8e4:35260   64:ff9b::34d0:9421:80         LAST_ACK    0          0           -

### turn off wifi
D:\Test>adb shell netstat -npWae
Proto Recv-Q Send-Q Local Address                                 Foreign Address               State       User       Inode       PID/Program Name
tcp        0      0 127.0.0.1:5037                                0.0.0.0:*                     LISTEN      0          36357       6907/adbd
tcp6       0      0 2001:2d8:ed1c:de1c:bd94:fe5:2d9a:d8e4:35148   2404:6800:4004:800::2003:80   LAST_ACK    0          0           -
tcp6       0      0 2001:2d8:ed1c:de1c:bd94:fe5:2d9a:d8e4:49294   2404:6800:4005:80c::2004:443  LAST_ACK    0          0           -
tcp6       1      0 2001:2d8:ed1c:de1c:bd94:fe5:2d9a:d8e4:35260   64:ff9b::34d0:9421:80         LAST_ACK    0          0           -


---------------------------------------------------------------------------------------------
this is our analysis
when app finished using the socket(tcp session), it calls sock_close.
then tcp_close() makes sk->sk_state to LAST_ACK, and sock to SOCK_DEAD by excute sock_orphan().

11-23 11:40:55.676 [5:      Thread-44:11210] TCP: bsj: tcp_set_state: TCP sk=ffffffc8a789c640, in:80092, State Close Wait -> Last ACK, [2404:6800:4004:800::2003]
11-23 11:40:55.676 [5:      Thread-44:11210] Call trace:
11-23 11:40:55.676 [5:      Thread-44:11210] [<ffffff8008ffdda8>] tcp_set_state+0x1b8/0x1f0
11-23 11:40:55.676 [5:      Thread-44:11210] [<ffffff8008ffe3f8>] tcp_close+0x484/0x534
11-23 11:40:55.676 [5:      Thread-44:11210] [<ffffff800902f830>] inet_release+0x60/0x74
11-23 11:40:55.676 [5:      Thread-44:11210] [<ffffff8009074238>] inet6_release+0x30/0x48
11-23 11:40:55.676 [5:      Thread-44:11210] [<ffffff8008f35e4c>] __sock_release+0x40/0x104
11-23 11:40:55.676 [5:      Thread-44:11210] [<ffffff8008f3bab0>] sock_close+0x18/0x28
11-23 11:40:55.678 [5:      Thread-44:11210] TCP: bsj: sock_orphan: TCP sk=ffffffc8a789c640, in:80092, State Last ACK, [2404:6800:4004:800::2003]


at this point, if the FIN_ACK comes, there's no problem. all is well~
but without that and when turn off wifi,
netd trying to close all the session by calling tcp_abort, sock_diag_destory.

11-23 11:41:38.463 [4:           netd: 5323] TCP: bsj: tcp_abort: SOCK_DEAD!!! : TCP sk=ffffffc8a789c640, in:0, State Last ACK, caller: <sock_diag_destroy>, [2404:6800:4004:800::2003]
11-23 11:41:38.464 [4:           netd: 5323] TCP: bsj: tcp_abort: SOCK_DEAD!!! : TCP sk=ffffffc8a789b840, in:0, State Last ACK, caller: <sock_diag_destroy>, [2404:6800:4005:80c::2004]
11-23 11:41:38.464 [4:           netd: 5323] TCP: bsj: tcp_abort: SOCK_DEAD!!! : TCP sk=ffffffc8a7899c40, in:0, State Last ACK, caller: <sock_diag_destroy>, [64:ff9b::34d0:9421]

but because of this sock was already changed to SOCK_DEAT state by tcp_close(), tcp_done() can't be excuted.
so this session can't be closed.

int tcp_abort(struct sock *sk, int err)
{
	...
	if (!sock_flag(sk, SOCK_DEAD)) {	//// when SOCK_DEAD, tcp_done() be skip.
		...
		sk->sk_error_report(sk);
		if (tcp_need_reset(sk->sk_state))
			tcp_send_active_reset(sk, GFP_ATOMIC);
		tcp_done(sk);
	}
	...
	return 0;
}


---------------------------------------------------------------------------------------------
wh thought that just sk_error_report have to reside in that condition, SOCK_DEAD.
and send-reset and tcp_done should to be always.
we fixed it like as below, and confirmed that issue resolved.
please check this.

Best regards,



>From 30f8d02f9d2ca8820a527444260e6dcf4862db8a Mon Sep 17 00:00:00 2001
From: soukjin bae <soukjin.bae@...sung.com>
Date: Fri, 23 Nov 2018 15:56:53 +0900
Subject: [PATCH] net: close session always when tcp_abort

session before recieve the FIN_ACK couldn't be closed by tcp_abort
they will remained permanently. close them

Signed-off-by: soukjin bae <soukjin.bae@...sung.com>
Signed-off-by: geumhwan you <geumhwan.you@...sung.com>
---
 net/ipv4/tcp.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 9e6bc4d6daa7..faf4a8bbec8e 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3792,11 +3792,12 @@ int tcp_abort(struct sock *sk, int err)
 		/* This barrier is coupled with smp_rmb() in tcp_poll() */
 		smp_wmb();
 		sk->sk_error_report(sk);
-		if (tcp_need_reset(sk->sk_state))
-			tcp_send_active_reset(sk, GFP_ATOMIC);
-		tcp_done(sk);
 	}
 
+	if (tcp_need_reset(sk->sk_state))
+		tcp_send_active_reset(sk, GFP_ATOMIC);
+	tcp_done(sk);
+
 	bh_unlock_sock(sk);
 	local_bh_enable();
 	tcp_write_queue_purge(sk);
-- 
2.13.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ