Author: tuexen
Date: Thu Apr 20 19:19:33 2017
New Revision: 317208
URL: https://svnweb.freebsd.org/changeset/base/317208

Log:
  Syncoockies can be used in combination with the syncache. If the cache
  overflows, syncookies are used.
  This patch restricts the usage of syncookies in this case: accept
  syncookies only if there was an overflow of the syncache recently.
  This mitigates a problem reported in PR217637, where is syncookie was
  accepted without any recent drops.
  Thanks to glebius@ for suggesting an improvement.
  
  PR:                   217637
  Reviewed by:          gnn, glebius
  MFC after:            1 week
  Sponsored by:         Netflix, Inc.
  Differential Revision:        https://reviews.freebsd.org/D10272

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

Modified: head/sys/netinet/tcp_syncache.c
==============================================================================
--- head/sys/netinet/tcp_syncache.c     Thu Apr 20 19:14:52 2017        
(r317207)
+++ head/sys/netinet/tcp_syncache.c     Thu Apr 20 19:19:33 2017        
(r317208)
@@ -260,6 +260,7 @@ syncache_init(void)
                         &V_tcp_syncache.hashbase[i].sch_mtx, 0);
                V_tcp_syncache.hashbase[i].sch_length = 0;
                V_tcp_syncache.hashbase[i].sch_sc = &V_tcp_syncache;
+               V_tcp_syncache.hashbase[i].sch_last_overflow = INT64_MIN;
        }
 
        /* Create the syncache entry zone. */
@@ -335,6 +336,7 @@ syncache_insert(struct syncache *sc, str
                KASSERT(!TAILQ_EMPTY(&sch->sch_bucket),
                        ("sch->sch_length incorrect"));
                sc2 = TAILQ_LAST(&sch->sch_bucket, sch_head);
+               sch->sch_last_overflow = time_uptime;
                syncache_drop(sc2, sch);
                TCPSTAT_INC(tcps_sc_bucketoverflow);
        }
@@ -974,10 +976,13 @@ syncache_expand(struct in_conninfo *inc,
                /*
                 * There is no syncache entry, so see if this ACK is
                 * a returning syncookie.  To do this, first:
-                *  A. See if this socket has had a syncache entry dropped in
-                *     the past.  We don't want to accept a bogus syncookie
-                *     if we've never received a SYN.
-                *  B. check that the syncookie is valid.  If it is, then
+                *  A. Check if syncookies are used in case of syncache
+                *     overflows
+                *  B. See if this socket has had a syncache entry dropped in
+                *     the recent past. We don't want to accept a bogus
+                *     syncookie if we've never received a SYN or accept it
+                *     twice.
+                *  C. check that the syncookie is valid.  If it is, then
                 *     cobble up a fake syncache entry, and return.
                 */
                if (!V_tcp_syncookies) {
@@ -988,6 +993,15 @@ syncache_expand(struct in_conninfo *inc,
                                    s, __func__);
                        goto failed;
                }
+               if (!V_tcp_syncookiesonly &&
+                   sch->sch_last_overflow < time_uptime - SYNCOOKIE_LIFETIME) {
+                       SCH_UNLOCK(sch);
+                       if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+                               log(LOG_DEBUG, "%s; %s: Spurious ACK, "
+                                   "segment rejected (no syncache entry)\n",
+                                   s, __func__);
+                       goto failed;
+               }
                bzero(&scs, sizeof(scs));
                sc = syncookie_lookup(inc, sch, &scs, th, to, *lsop);
                SCH_UNLOCK(sch);
@@ -1411,8 +1425,10 @@ syncache_add(struct in_conninfo *inc, st
                 * entry and insert the new one.
                 */
                TCPSTAT_INC(tcps_sc_zonefail);
-               if ((sc = TAILQ_LAST(&sch->sch_bucket, sch_head)) != NULL)
+               if ((sc = TAILQ_LAST(&sch->sch_bucket, sch_head)) != NULL) {
+                       sch->sch_last_overflow = time_uptime;
                        syncache_drop(sc, sch);
+               }
                sc = uma_zalloc(V_tcp_syncache.zone, M_NOWAIT | M_ZERO);
                if (sc == NULL) {
                        if (V_tcp_syncookies) {

Modified: head/sys/netinet/tcp_syncache.h
==============================================================================
--- head/sys/netinet/tcp_syncache.h     Thu Apr 20 19:14:52 2017        
(r317207)
+++ head/sys/netinet/tcp_syncache.h     Thu Apr 20 19:19:33 2017        
(r317208)
@@ -99,6 +99,7 @@ struct syncache_head {
        int             sch_nextc;
        u_int           sch_length;
        struct tcp_syncache *sch_sc;
+       time_t          sch_last_overflow;
 };
 
 #define        SYNCOOKIE_SECRET_SIZE   16
_______________________________________________
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