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);