git: cda6bdbaa15e - main - tcp: Don't try to disconnect a socket multiple times.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 17 Feb 2023 17:14:34 UTC
The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=cda6bdbaa15e04857e2c0ae7ac06e9dbabac9835 commit cda6bdbaa15e04857e2c0ae7ac06e9dbabac9835 Author: John Baldwin <jhb@FreeBSD.org> AuthorDate: 2023-02-17 17:13:53 +0000 Commit: John Baldwin <jhb@FreeBSD.org> CommitDate: 2023-02-17 17:13:53 +0000 tcp: Don't try to disconnect a socket multiple times. When the checks for INP_TIMEWAIT were removed, tcp_usr_close() and tcp_usr_disconnect() were no longer prevented from calling tcp_disconnect() on a socket that was already disconnected. This triggered a panic in cxgbe(4) for TOE where the tcp_disconnect() on an already-disconnected socket invoked tcp_output() on a socket that was already in time-wait. Reviewed by: rrs, np Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D37112 --- sys/netinet/tcp_usrreq.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 1dbf4659ad00..0c36e4281010 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -654,6 +654,8 @@ tcp_usr_disconnect(struct socket *so) goto out; } tp = intotcpcb(inp); + if (tp->t_state == TCPS_TIME_WAIT) + goto out; tcp_disconnect(tp); out: TCP_PROBE2(debug__user, tp, PRU_DISCONNECT); @@ -1248,14 +1250,16 @@ tcp_usr_close(struct socket *so) ("tcp_usr_close: inp_socket == NULL")); /* - * If we still have full TCP state, and we're not dropped, initiate + * If we are still connected and we're not dropped, initiate * a disconnect. */ if (!(inp->inp_flags & INP_DROPPED)) { tp = intotcpcb(inp); - tp->t_flags |= TF_CLOSED; - tcp_disconnect(tp); - TCP_PROBE2(debug__user, tp, PRU_CLOSE); + if (tp->t_state != TCPS_TIME_WAIT) { + tp->t_flags |= TF_CLOSED; + tcp_disconnect(tp); + TCP_PROBE2(debug__user, tp, PRU_CLOSE); + } } if (!(inp->inp_flags & INP_DROPPED)) { soref(so);