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

Michael Tuexen tuexen at FreeBSD.org
Wed Apr 26 06:20:59 UTC 2017


Author: tuexen
Date: Wed Apr 26 06:20:58 2017
New Revision: 317435
URL: https://svnweb.freebsd.org/changeset/base/317435

Log:
  When a SYN-ACK is received in SYN-SENT state, RFC 793 requires the
  validation of SEG.ACK as the first step. If the ACK is not acceptable,
  a RST segment should be sent and the segment should be dropped.
  Up to now, the segment was partially processed.
  This patch moves the check for the SEG.ACK validation up to the front
  as required.
  Reviewed by:		hiren, gnn
  MFC after:		1 week
  Sponsored by:		Netflix, Inc.
  Differential Revision:	https://reviews.freebsd.org/D10424

Modified:
  head/sys/netinet/tcp_input.c
  head/sys/netinet/tcp_stacks/fastpath.c

Modified: head/sys/netinet/tcp_input.c
==============================================================================
--- head/sys/netinet/tcp_input.c	Wed Apr 26 02:37:25 2017	(r317434)
+++ head/sys/netinet/tcp_input.c	Wed Apr 26 06:20:58 2017	(r317435)
@@ -1624,6 +1624,16 @@ tcp_do_segment(struct mbuf *m, struct tc
 	}
 
 	/*
+	 * If a segment with the ACK-bit set arrives in the SYN-SENT state
+	 * check SEQ.ACK first.
+	 */
+	if ((tp->t_state == TCPS_SYN_SENT) && (thflags & TH_ACK) &&
+	    (SEQ_LEQ(th->th_ack, tp->iss) || SEQ_GT(th->th_ack, tp->snd_max))) {
+		rstreason = BANDLIM_UNLIMITED;
+		goto dropwithreset;
+	}
+
+	/*
 	 * Segment received on connection.
 	 * Reset idle time and keep-alive timer.
 	 * XXX: This should be done after segment
@@ -2001,7 +2011,6 @@ tcp_do_segment(struct mbuf *m, struct tc
 
 	/*
 	 * If the state is SYN_SENT:
-	 *	if seg contains an ACK, but not for our SYN, drop the input.
 	 *	if seg contains a RST, then drop the connection.
 	 *	if seg does not contain SYN, then drop it.
 	 * Otherwise this is an acceptable SYN segment
@@ -2014,12 +2023,6 @@ tcp_do_segment(struct mbuf *m, struct tc
 	 *	continue processing rest of data/controls, beginning with URG
 	 */
 	case TCPS_SYN_SENT:
-		if ((thflags & TH_ACK) &&
-		    (SEQ_LEQ(th->th_ack, tp->iss) ||
-		     SEQ_GT(th->th_ack, tp->snd_max))) {
-			rstreason = BANDLIM_UNLIMITED;
-			goto dropwithreset;
-		}
 		if ((thflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) {
 			TCP_PROBE5(connect__refused, NULL, tp,
 			    m, tp, th);

Modified: head/sys/netinet/tcp_stacks/fastpath.c
==============================================================================
--- head/sys/netinet/tcp_stacks/fastpath.c	Wed Apr 26 02:37:25 2017	(r317434)
+++ head/sys/netinet/tcp_stacks/fastpath.c	Wed Apr 26 06:20:58 2017	(r317435)
@@ -497,7 +497,6 @@ tcp_do_slowpath(struct mbuf *m, struct t
 
 	/*
 	 * If the state is SYN_SENT:
-	 *	if seg contains an ACK, but not for our SYN, drop the input.
 	 *	if seg contains a RST, then drop the connection.
 	 *	if seg does not contain SYN, then drop it.
 	 * Otherwise this is an acceptable SYN segment
@@ -510,12 +509,6 @@ tcp_do_slowpath(struct mbuf *m, struct t
 	 *	continue processing rest of data/controls, beginning with URG
 	 */
 	case TCPS_SYN_SENT:
-		if ((thflags & TH_ACK) &&
-		    (SEQ_LEQ(th->th_ack, tp->iss) ||
-		     SEQ_GT(th->th_ack, tp->snd_max))) {
-			rstreason = BANDLIM_UNLIMITED;
-			goto dropwithreset;
-		}
 		if ((thflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) {
 			TCP_PROBE5(connect__refused, NULL, tp, m, tp, th);
 			tp = tcp_drop(tp, ECONNREFUSED);
@@ -1775,6 +1768,20 @@ tcp_do_segment_fastslow(struct mbuf *m, 
 		m_freem(m);
 		return;
 	}
+	
+	/*
+	 * If a segment with the ACK-bit set arrives in the SYN-SENT state
+	 * check SEQ.ACK first.
+	 */
+	if ((tp->t_state == TCPS_SYN_SENT) && (thflags & TH_ACK) &&
+	    (SEQ_LEQ(th->th_ack, tp->iss) || SEQ_GT(th->th_ack, tp->snd_max))) {
+		tcp_dropwithreset(m, th, tp, tlen, BANDLIM_UNLIMITED);
+		if (ti_locked == TI_RLOCKED) {
+			INP_INFO_RUNLOCK(&V_tcbinfo);
+		}
+		INP_WUNLOCK(tp->t_inpcb);
+		return;
+	}
 
 	tp->sackhint.last_sack_ack = 0;
 
@@ -2237,6 +2244,20 @@ tcp_do_segment_fastack(struct mbuf *m, s
 		return;
 	}
 
+	/*
+	 * If a segment with the ACK-bit set arrives in the SYN-SENT state
+	 * check SEQ.ACK first.
+	 */
+	if ((tp->t_state == TCPS_SYN_SENT) && (thflags & TH_ACK) &&
+	    (SEQ_LEQ(th->th_ack, tp->iss) || SEQ_GT(th->th_ack, tp->snd_max))) {
+		tcp_dropwithreset(m, th, tp, tlen, BANDLIM_UNLIMITED);
+		if (ti_locked == TI_RLOCKED) {
+			INP_INFO_RUNLOCK(&V_tcbinfo);
+		}
+		INP_WUNLOCK(tp->t_inpcb);
+		return;
+	}
+	
 	tp->sackhint.last_sack_ack = 0;
 
 	/*


More information about the svn-src-head mailing list