svn commit: r352868 - in head/sys/netinet: . tcp_stacks

Michael Tuexen tuexen at FreeBSD.org
Sun Sep 29 10:45:14 UTC 2019


Author: tuexen
Date: Sun Sep 29 10:45:13 2019
New Revision: 352868
URL: https://svnweb.freebsd.org/changeset/base/352868

Log:
  RFC 7112 requires a host to put the complete IP header chain
  including the TCP header in the first IP packet.
  Enforce this in tcp_output(). In addition make sure that at least
  one byte payload fits in the TCP segement to allow making progress.
  Without this check, a kernel with INVARIANTS will panic.
  This issue was found by running an instance of syzkaller.
  
  Reviewed by:		jtl@
  MFC after:		3 days
  Sponsored by:		Netflix, Inc.
  Differential Revision:	https://reviews.freebsd.org/D21665

Modified:
  head/sys/netinet/tcp_output.c
  head/sys/netinet/tcp_stacks/bbr.c
  head/sys/netinet/tcp_stacks/rack.c

Modified: head/sys/netinet/tcp_output.c
==============================================================================
--- head/sys/netinet/tcp_output.c	Sun Sep 29 06:12:51 2019	(r352867)
+++ head/sys/netinet/tcp_output.c	Sun Sep 29 10:45:13 2019	(r352868)
@@ -941,6 +941,20 @@ send:
 			if (tp->t_flags & TF_NEEDFIN)
 				sendalot = 1;
 		} else {
+			if (optlen + ipoptlen >= tp->t_maxseg) {
+				/*
+				 * Since we don't have enough space to put
+				 * the IP header chain and the TCP header in
+				 * one packet as required by RFC 7112, don't
+				 * send it. Also ensure that at least one
+				 * byte of the payload can be put into the
+				 * TCP segment.
+				 */
+				SOCKBUF_UNLOCK(&so->so_snd);
+				error = EMSGSIZE;
+				sack_rxmit = 0;
+				goto out;
+			}
 			len = tp->t_maxseg - optlen - ipoptlen;
 			sendalot = 1;
 			if (dont_sendalot)

Modified: head/sys/netinet/tcp_stacks/bbr.c
==============================================================================
--- head/sys/netinet/tcp_stacks/bbr.c	Sun Sep 29 06:12:51 2019	(r352867)
+++ head/sys/netinet/tcp_stacks/bbr.c	Sun Sep 29 10:45:13 2019	(r352868)
@@ -13343,12 +13343,14 @@ send:
 			}
 		} else {
 			/* Not doing TSO */
-			if (optlen + ipoptlen > tp->t_maxseg) {
+			if (optlen + ipoptlen >= tp->t_maxseg) {
 				/*
 				 * Since we don't have enough space to put
 				 * the IP header chain and the TCP header in
 				 * one packet as required by RFC 7112, don't
-				 * send it.
+				 * send it. Also ensure that at least one
+				 * byte of the payload can be put into the
+				 * TCP segment.
 				 */
 				SOCKBUF_UNLOCK(&so->so_snd);
 				error = EMSGSIZE;

Modified: head/sys/netinet/tcp_stacks/rack.c
==============================================================================
--- head/sys/netinet/tcp_stacks/rack.c	Sun Sep 29 06:12:51 2019	(r352867)
+++ head/sys/netinet/tcp_stacks/rack.c	Sun Sep 29 10:45:13 2019	(r352868)
@@ -9200,12 +9200,14 @@ send:
 				sendalot = 1;
 
 		} else {
-			if (optlen + ipoptlen > tp->t_maxseg) {
+			if (optlen + ipoptlen >= tp->t_maxseg) {
 				/*
 				 * Since we don't have enough space to put
 				 * the IP header chain and the TCP header in
 				 * one packet as required by RFC 7112, don't
-				 * send it.
+				 * send it. Also ensure that at least one
+				 * byte of the payload can be put into the
+				 * TCP segment.
 				 */
 				SOCKBUF_UNLOCK(&so->so_snd);
 				error = EMSGSIZE;


More information about the svn-src-all mailing list