Author: tuexen
Date: Wed Aug  9 13:26:12 2017
New Revision: 322315
URL: https://svnweb.freebsd.org/changeset/base/322315

Log:
  MFC r317208:
  
  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
  Differential Revision:        https://reviews.freebsd.org/D10272

Modified:
  stable/10/sys/netinet/tcp_syncache.c
  stable/10/sys/netinet/tcp_syncache.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/netinet/tcp_syncache.c
==============================================================================
--- stable/10/sys/netinet/tcp_syncache.c        Wed Aug  9 13:25:27 2017        
(r322314)
+++ stable/10/sys/netinet/tcp_syncache.c        Wed Aug  9 13:26:12 2017        
(r322315)
@@ -277,6 +277,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. */
@@ -357,6 +358,7 @@ syncache_insert(struct syncache *sc, struct syncache_h
                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);
        }
@@ -985,10 +987,13 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt
                /*
                 * 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) {
@@ -999,6 +1004,15 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt
                                    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);
@@ -1336,8 +1350,10 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *t
                 * 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: stable/10/sys/netinet/tcp_syncache.h
==============================================================================
--- stable/10/sys/netinet/tcp_syncache.h        Wed Aug  9 13:25:27 2017        
(r322314)
+++ stable/10/sys/netinet/tcp_syncache.h        Wed Aug  9 13:26:12 2017        
(r322315)
@@ -100,6 +100,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-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to