svn commit: r317208 - head/sys/netinet

Michael Tuexen tuexen at FreeBSD.org
Thu Apr 20 19:19:35 UTC 2017


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


More information about the svn-src-head mailing list