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);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to