git: bc92b6240ddf - stable/11 - tcp: Correctly compute the retransmit length for all 64-bit platforms.

From: Hans Petter Selasky <hselasky_at_FreeBSD.org>
Date: Mon, 06 Jun 2022 20:12:32 UTC
The branch stable/11 has been updated by hselasky:

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

commit bc92b6240ddf6ab11813abe439653308da14ee54
Author:     Hans Petter Selasky <hselasky@FreeBSD.org>
AuthorDate: 2022-06-02 18:33:21 +0000
Commit:     Hans Petter Selasky <hselasky@FreeBSD.org>
CommitDate: 2022-06-06 20:09:38 +0000

    tcp: Correctly compute the retransmit length for all 64-bit platforms.
    
    When the TCP sequence number subtracted is greater than 2**32 minus
    the window size, or 2**31 minus the window size, the use of unsigned
    long as an intermediate variable, may result in an incorrect retransmit
    length computation on all 64-bit platforms.
    
    While at it create a helper macro to facilitate the computation of
    the difference between two TCP sequence numbers.
    
    Differential Revision:  https://reviews.freebsd.org/D35388
    Reviewed by:    rscheff
    Sponsored by:   NVIDIA Networking
    
    (cherry picked from commit 28173d49dccb91e50be9c401dbad1da908a5dc75)
---
 sys/netinet/tcp_output.c | 15 +++++++++------
 sys/netinet/tcp_seq.h    |  1 +
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 53e3623e7616..cd12e2714d72 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -296,13 +296,16 @@ again:
 				 */
 				p = NULL;
 				goto after_sack_rexmit;
-			} else
+			} else {
 				/* Can rexmit part of the current hole */
-				len = ((long)ulmin(cwin,
-						   tp->snd_recover - p->rxmit));
-		} else
-			len = ((long)ulmin(cwin, p->end - p->rxmit));
-		off = p->rxmit - tp->snd_una;
+				len = ((int32_t)ulmin(cwin,
+				    SEQ_SUB(tp->snd_recover, p->rxmit)));
+			}
+		} else {
+			len = ((int32_t)ulmin(cwin,
+			    SEQ_SUB(p->end, p->rxmit)));
+		}
+		off = SEQ_SUB(p->rxmit, tp->snd_una);
 		KASSERT(off >= 0,("%s: sack block to the left of una : %d",
 		    __func__, off));
 		if (len > 0) {
diff --git a/sys/netinet/tcp_seq.h b/sys/netinet/tcp_seq.h
index ca1adbaaeab6..7a812e17cc54 100644
--- a/sys/netinet/tcp_seq.h
+++ b/sys/netinet/tcp_seq.h
@@ -41,6 +41,7 @@
 #define	SEQ_LEQ(a,b)	((int)((a)-(b)) <= 0)
 #define	SEQ_GT(a,b)	((int)((a)-(b)) > 0)
 #define	SEQ_GEQ(a,b)	((int)((a)-(b)) >= 0)
+#define	SEQ_SUB(a,b)	((int)((a)-(b)))
 
 #define	SEQ_MIN(a, b)	((SEQ_LT(a, b)) ? (a) : (b))
 #define	SEQ_MAX(a, b)	((SEQ_GT(a, b)) ? (a) : (b))