git: 15d6a1f03ba7 - stable/13 - tcp: Rewind erraneous RTO only while performing RTO retransmissions

From: Richard Scheffenegger <rscheff_at_FreeBSD.org>
Date: Sun, 30 Jan 2022 10:40:29 UTC
The branch stable/13 has been updated by rscheff:

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

commit 15d6a1f03ba79dd264e3542ba83b3f701dedfdb3
Author:     Richard Scheffenegger <rscheff@FreeBSD.org>
AuthorDate: 2022-01-27 17:35:47 +0000
Commit:     Richard Scheffenegger <rscheff@FreeBSD.org>
CommitDate: 2022-01-30 09:29:15 +0000

    tcp: Rewind erraneous RTO only while performing RTO retransmissions
    
    Under rare circumstances, a spurious retranmission is
    incorrectly detected and rewound, messing up various tcpcb values,
    which can lead to a panic when SACK is in use.
    
    Reviewed By: tuexen, chengc_netapp.com, #transport
    MFC after:   3 days
    Sponsored by:        NetApp, Inc.
    Differential Revision: https://reviews.freebsd.org/D33979
    
    (cherry picked from commit 68e623c3f0afb4c9b338046fd1d4476befd82324)
---
 sys/netinet/tcp_input.c | 1 +
 sys/netinet/tcp_var.h   | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index f7ca4ce05200..0848afd3c2b0 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1654,6 +1654,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
 		if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks()))
 			to.to_tsecr = 0;
 		else if (tp->t_flags & TF_PREVVALID &&
+			 tp->t_rxtshift == 1 &&
 			 tp->t_badrxtwin != 0 && SEQ_LT(to.to_tsecr, tp->t_badrxtwin))
 			cc_cong_signal(tp, th, CC_RTO_ERR);
 	}
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 86783c0eae38..3dfe3cc2a035 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -398,7 +398,11 @@ TAILQ_HEAD(tcp_funchead, tcp_function);
 #define	TF_NEEDSYN	0x00000400	/* send SYN (implicit state) */
 #define	TF_NEEDFIN	0x00000800	/* send FIN (implicit state) */
 #define	TF_NOPUSH	0x00001000	/* don't push */
-#define	TF_PREVVALID	0x00002000	/* saved values for bad rxmit valid */
+#define	TF_PREVVALID	0x00002000	/* saved values for bad rxmit valid
+					 * Note: accessing and restoring from
+					 * these may only be done in the 1st
+					 * RTO recovery round (t_rxtshift == 1)
+					 */
 #define	TF_WAKESOR	0x00004000	/* wake up receive socket */
 #define	TF_GPUTINPROG	0x00008000	/* Goodput measurement in progress */
 #define	TF_MORETOCOME	0x00010000	/* More data to be appended to sock */