git: f71cb9f74808 - main - tcp: inp_socket is valid through the lifetime of a TCP inpcb

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Tue, 08 Nov 2022 18:24:56 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=f71cb9f74808facc9d3e6854f96da2afbed8a1e3

commit f71cb9f74808facc9d3e6854f96da2afbed8a1e3
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2022-11-08 18:24:39 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2022-11-08 18:24:39 +0000

    tcp: inp_socket is valid through the lifetime of a TCP inpcb
    
    The inp_socket is cleared only in in_pcbdetach(), which for TCP is
    always accompanied with inp_pcbfree().  An inpcb that went through
    in_pcbfree() shall never be returned by any kind of pcb lookup.
    
    Reviewed by:            tuexen
    Differential revision:  https://reviews.freebsd.org/D37062
---
 sys/netinet/tcp_input.c |   2 +-
 sys/netinet/tcp_subr.c  | 177 ++++++++++++++++++++++--------------------------
 sys/netinet/tcp_timer.c |   2 +
 3 files changed, 83 insertions(+), 98 deletions(-)

diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index eeed49681ec6..ad399b9042e2 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -940,7 +940,7 @@ findpcb:
 
 	if ((inp->inp_flowtype == M_HASHTYPE_NONE) &&
 	    (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) &&
-	    ((inp->inp_socket == NULL) || !SOLISTENING(inp->inp_socket))) {
+	    !SOLISTENING(inp->inp_socket)) {
 		inp->inp_flowid = m->m_pkthdr.flowid;
 		inp->inp_flowtype = M_HASHTYPE_GET(m);
 	}
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 999f52c9a339..e159bf81208b 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2730,8 +2730,6 @@ tcp_getcred(SYSCTL_HANDLER_ARGS)
 	    addrs[0].sin_addr, addrs[0].sin_port, INPLOOKUP_RLOCKPCB, NULL);
 	NET_EPOCH_EXIT(et);
 	if (inp != NULL) {
-		if (inp->inp_socket == NULL)
-			error = ENOENT;
 		if (error == 0)
 			error = cr_canseeinpcb(req->td->td_ucred, inp);
 		if (error == 0)
@@ -2798,8 +2796,6 @@ tcp6_getcred(SYSCTL_HANDLER_ARGS)
 			INPLOOKUP_RLOCKPCB, NULL);
 	NET_EPOCH_EXIT(et);
 	if (inp != NULL) {
-		if (inp->inp_socket == NULL)
-			error = ENOENT;
 		if (error == 0)
 			error = cr_canseeinpcb(req->td->td_ucred, inp);
 		if (error == 0)
@@ -2875,47 +2871,44 @@ tcp_ctlinput_with_port(struct icmp *icp, uint16_t port)
 	inp = in_pcblookup(&V_tcbinfo, ip->ip_dst, th->th_dport, ip->ip_src,
 	    th->th_sport, INPLOOKUP_WLOCKPCB, NULL);
 	if (inp != NULL)  {
-		if (inp->inp_socket != NULL) {
-			tp = intotcpcb(inp);
+		tp = intotcpcb(inp);
 #ifdef TCP_OFFLOAD
-			if (tp->t_flags & TF_TOE && errno == EMSGSIZE) {
+		if (tp->t_flags & TF_TOE && errno == EMSGSIZE) {
+			/*
+			 * MTU discovery for offloaded connections.  Let
+			 * the TOE driver verify seq# and process it.
+			 */
+			mtu = tcp_next_pmtu(icp, ip);
+			tcp_offload_pmtu_update(tp, icmp_tcp_seq, mtu);
+			goto out;
+		}
+#endif
+		if (tp->t_port != port)
+			goto out;
+		if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) &&
+		    SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) {
+			if (errno == EMSGSIZE) {
 				/*
-				 * MTU discovery for offloaded connections.  Let
-				 * the TOE driver verify seq# and process it.
+				 * MTU discovery: we got a needfrag and
+				 * will potentially try a lower MTU.
 				 */
 				mtu = tcp_next_pmtu(icp, ip);
-				tcp_offload_pmtu_update(tp, icmp_tcp_seq, mtu);
-				goto out;
-			}
-#endif
-			if (tp->t_port != port) {
-				goto out;
-			}
-			if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) &&
-			    SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) {
-				if (errno == EMSGSIZE) {
-					/*
-					 * MTU discovery: we got a needfrag and
-					 * will potentially try a lower MTU.
-					 */
-					mtu = tcp_next_pmtu(icp, ip);
-
-					/*
-					 * Only process the offered MTU if it
-					 * is smaller than the current one.
-					 */
-					if (mtu < tp->t_maxseg +
-					    sizeof(struct tcpiphdr)) {
-						bzero(&inc, sizeof(inc));
-						inc.inc_faddr = ip->ip_dst;
-						inc.inc_fibnum =
-						    inp->inp_inc.inc_fibnum;
-						tcp_hc_updatemtu(&inc, mtu);
-						inp = tcp_mtudisc(inp, mtu);
-					}
-				} else
-					inp = (*notify)(inp, errno);
-			}
+
+				/*
+				 * Only process the offered MTU if it
+				 * is smaller than the current one.
+				 */
+				if (mtu < tp->t_maxseg +
+				    sizeof(struct tcpiphdr)) {
+					bzero(&inc, sizeof(inc));
+					inc.inc_faddr = ip->ip_dst;
+					inc.inc_fibnum =
+					    inp->inp_inc.inc_fibnum;
+					tcp_hc_updatemtu(&inc, mtu);
+					inp = tcp_mtudisc(inp, mtu);
+				}
+			} else
+				inp = (*notify)(inp, errno);
 		}
 	} else {
 		bzero(&inc, sizeof(inc));
@@ -3067,51 +3060,48 @@ tcp6_ctlinput_with_port(struct ip6ctlparam *ip6cp, uint16_t port)
 	}
 	m_copydata(m, off, sizeof(tcp_seq), (caddr_t)&icmp_tcp_seq);
 	if (inp != NULL)  {
-		if (inp->inp_socket != NULL) {
-			tp = intotcpcb(inp);
+		tp = intotcpcb(inp);
 #ifdef TCP_OFFLOAD
-			if (tp->t_flags & TF_TOE && errno == EMSGSIZE) {
-				/* MTU discovery for offloaded connections. */
-				mtu = tcp6_next_pmtu(icmp6);
-				tcp_offload_pmtu_update(tp, icmp_tcp_seq, mtu);
-				goto out;
-			}
+		if (tp->t_flags & TF_TOE && errno == EMSGSIZE) {
+			/* MTU discovery for offloaded connections. */
+			mtu = tcp6_next_pmtu(icmp6);
+			tcp_offload_pmtu_update(tp, icmp_tcp_seq, mtu);
+			goto out;
+		}
 #endif
-			if (tp->t_port != port) {
-				goto out;
-			}
-			if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) &&
-			    SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) {
-				if (errno == EMSGSIZE) {
-					/*
-					 * MTU discovery:
-					 * If we got a needfrag set the MTU
-					 * in the route to the suggested new
-					 * value (if given) and then notify.
-					 */
-					mtu = tcp6_next_pmtu(icmp6);
+		if (tp->t_port != port)
+			goto out;
+		if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) &&
+		    SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) {
+			if (errno == EMSGSIZE) {
+				/*
+				 * MTU discovery:
+				 * If we got a needfrag set the MTU
+				 * in the route to the suggested new
+				 * value (if given) and then notify.
+				 */
+				mtu = tcp6_next_pmtu(icmp6);
 
-					bzero(&inc, sizeof(inc));
-					inc.inc_fibnum = M_GETFIB(m);
-					inc.inc_flags |= INC_ISIPV6;
-					inc.inc6_faddr = *dst;
-					if (in6_setscope(&inc.inc6_faddr,
-						m->m_pkthdr.rcvif, NULL))
-						goto out;
-					/*
-					 * Only process the offered MTU if it
-					 * is smaller than the current one.
-					 */
-					if (mtu < tp->t_maxseg +
-					    sizeof (struct tcphdr) +
-					    sizeof (struct ip6_hdr)) {
-						tcp_hc_updatemtu(&inc, mtu);
-						tcp_mtudisc(inp, mtu);
-						ICMP6STAT_INC(icp6s_pmtuchg);
-					}
-				} else
-					inp = (*notify)(inp, errno);
-			}
+				bzero(&inc, sizeof(inc));
+				inc.inc_fibnum = M_GETFIB(m);
+				inc.inc_flags |= INC_ISIPV6;
+				inc.inc6_faddr = *dst;
+				if (in6_setscope(&inc.inc6_faddr,
+					m->m_pkthdr.rcvif, NULL))
+					goto out;
+				/*
+				 * Only process the offered MTU if it
+				 * is smaller than the current one.
+				 */
+				if (mtu < tp->t_maxseg +
+				    sizeof (struct tcphdr) +
+				    sizeof (struct ip6_hdr)) {
+					tcp_hc_updatemtu(&inc, mtu);
+					tcp_mtudisc(inp, mtu);
+					ICMP6STAT_INC(icp6s_pmtuchg);
+				}
+			} else
+				inp = (*notify)(inp, errno);
 		}
 	} else {
 		bzero(&inc, sizeof(inc));
@@ -3806,19 +3796,14 @@ sysctl_switch_tls(SYSCTL_HANDLER_ARGS)
 	}
 	NET_EPOCH_EXIT(et);
 	if (inp != NULL) {
-		if (inp->inp_socket == NULL) {
-			error = ECONNRESET;
-			INP_WUNLOCK(inp);
-		} else {
-			struct socket *so;
+		struct socket *so;
 
-			so = inp->inp_socket;
-			soref(so);
-			error = ktls_set_tx_mode(so,
-			    arg2 == 0 ? TCP_TLS_MODE_SW : TCP_TLS_MODE_IFNET);
-			INP_WUNLOCK(inp);
-			sorele(so);
-		}
+		so = inp->inp_socket;
+		soref(so);
+		error = ktls_set_tx_mode(so,
+		    arg2 == 0 ? TCP_TLS_MODE_SW : TCP_TLS_MODE_IFNET);
+		INP_WUNLOCK(inp);
+		sorele(so);
 	} else
 		error = ESRCH;
 	return (error);
@@ -4025,8 +4010,6 @@ tcp_inptoxtp(const struct inpcb *inp, struct xtcpcb *xt)
 
 	xt->xt_len = sizeof(struct xtcpcb);
 	in_pcbtoxinpcb(inp, &xt->xt_inp);
-	if (inp->inp_socket == NULL)
-		xt->xt_inp.xi_socket.xso_protocol = IPPROTO_TCP;
 }
 
 void
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 391b9dfdbc05..bbf5331c1d7d 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -351,6 +351,8 @@ tcp_timer_2msl(void *xtp)
 	 * If fastrecycle of FIN_WAIT_2, in FIN_WAIT_2 and receiver has closed,
 	 * there's no point in hanging onto FIN_WAIT_2 socket. Just close it.
 	 * Ignore fact that there were recent incoming segments.
+	 *
+	 * XXXGL: check if inp_socket shall always be !NULL here?
 	 */
 	if (tp->t_state == TCPS_TIME_WAIT) {
 		tcp_timer_close(tp);