svn commit: r307337 - head/sys/netinet

Patrick Kelsey pkelsey at FreeBSD.org
Sat Oct 15 01:41:29 UTC 2016


Author: pkelsey
Date: Sat Oct 15 01:41:28 2016
New Revision: 307337
URL: https://svnweb.freebsd.org/changeset/base/307337

Log:
  Fix cases where the TFO pending counter would leak references, and eventually, memory.
  
  Also renamed some tfo labels and added/reworked comments for clarity.
  
  Based on an initial patch from jtl.
  
  PR: 213424
  Reviewed by:	jtl
  MFC after:	1 week
  Differential Revision:	https://reviews.freebsd.org/D8235

Modified:
  head/sys/netinet/tcp_input.c
  head/sys/netinet/tcp_syncache.c

Modified: head/sys/netinet/tcp_input.c
==============================================================================
--- head/sys/netinet/tcp_input.c	Sat Oct 15 00:29:15 2016	(r307336)
+++ head/sys/netinet/tcp_input.c	Sat Oct 15 01:41:28 2016	(r307337)
@@ -1121,7 +1121,7 @@ relocked:
 				goto dropwithreset;
 			}
 #ifdef TCP_RFC7413
-new_tfo_socket:
+tfo_socket_result:
 #endif
 			if (so == NULL) {
 				/*
@@ -1387,7 +1387,7 @@ new_tfo_socket:
 		tcp_dooptions(&to, optp, optlen, TO_SYN);
 #ifdef TCP_RFC7413
 		if (syncache_add(&inc, &to, th, inp, &so, m, NULL, NULL))
-			goto new_tfo_socket;
+			goto tfo_socket_result;
 #else
 		syncache_add(&inc, &to, th, inp, &so, m, NULL, NULL);
 #endif

Modified: head/sys/netinet/tcp_syncache.c
==============================================================================
--- head/sys/netinet/tcp_syncache.c	Sat Oct 15 00:29:15 2016	(r307336)
+++ head/sys/netinet/tcp_syncache.c	Sat Oct 15 01:41:28 2016	(r307337)
@@ -1151,11 +1151,10 @@ syncache_tfo_expand(struct syncache *sc,
  * the data, we avoid this DoS scenario.
  *
  * The exception to the above is when a SYN with a valid TCP Fast Open (TFO)
- * cookie is processed, V_tcp_fastopen_enabled set to true, and the
- * TCP_FASTOPEN socket option is set.  In this case, a new socket is created
- * and returned via lsop, the mbuf is not freed so that tcp_input() can
- * queue its data to the socket, and 1 is returned to indicate the
- * TFO-socket-creation path was taken.
+ * cookie is processed and a new socket is created.  In this case, any data
+ * accompanying the SYN will be queued to the socket by tcp_input() and will
+ * be ACKed either when the application sends response data or the delayed
+ * ACK timer expires, whichever comes first.
  */
 int
 syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
@@ -1181,6 +1180,7 @@ syncache_add(struct in_conninfo *inc, st
 	struct ucred *cred;
 #ifdef TCP_RFC7413
 	uint64_t tfo_response_cookie;
+	unsigned int *tfo_pending = NULL;
 	int tfo_cookie_valid = 0;
 	int tfo_response_cookie_valid = 0;
 #endif
@@ -1226,8 +1226,13 @@ syncache_add(struct in_conninfo *inc, st
 			    &tfo_response_cookie);
 			tfo_cookie_valid = (result > 0);
 			tfo_response_cookie_valid = (result >= 0);
-		} else
-			atomic_subtract_int(tp->t_tfo_pending, 1);
+		}
+
+		/*
+		 * Remember the TFO pending counter as it will have to be
+		 * decremented below if we don't make it to syncache_tfo_expand().
+		 */
+		tfo_pending = tp->t_tfo_pending;
 	}
 #endif
 
@@ -1468,9 +1473,9 @@ skip_alloc:
 #ifdef TCP_RFC7413
 	if (tfo_cookie_valid) {
 		syncache_tfo_expand(sc, lsop, m, tfo_response_cookie);
-		/* INP_WUNLOCK(inp) will be performed by the called */
+		/* INP_WUNLOCK(inp) will be performed by the caller */
 		rv = 1;
-		goto tfo_done;
+		goto tfo_expanded;
 	}
 #endif
 
@@ -1496,7 +1501,16 @@ done:
 		m_freem(m);
 	}
 #ifdef TCP_RFC7413
-tfo_done:
+	/*
+	 * If tfo_pending is not NULL here, then a TFO SYN that did not
+	 * result in a new socket was processed and the associated pending
+	 * counter has not yet been decremented.  All such TFO processing paths
+	 * transit this point.
+	 */
+	if (tfo_pending != NULL)
+		tcp_fastopen_decrement_counter(tfo_pending);
+
+tfo_expanded:
 #endif
 	if (cred != NULL)
 		crfree(cred);


More information about the svn-src-head mailing list