Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Oct 2017 08:56:11 +0000 (UTC)
From:      Julien Charbon <jch@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r324948 - stable/11/sys/netinet
Message-ID:  <201710240856.v9O8uBk2052603@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jch
Date: Tue Oct 24 08:56:11 2017
New Revision: 324948
URL: https://svnweb.freebsd.org/changeset/base/324948

Log:
  MFC r324179, r324193:
  
  r324179:
  
  Fix an infinite loop in tcp_tw_2msl_scan() when an INP_TIMEWAIT inp has
  been destroyed before its tcptw with INVARIANTS undefined.
  
  This is a symmetric change of r307551:
  
  A INP_TIMEWAIT inp should not be destroyed before its tcptw, and INVARIANTS
  will catch this case.  If INVARIANTS is undefined it will emit a log(LOG_ERR)
  and avoid a hard to debug infinite loop in tcp_tw_2msl_scan().
  
  Reported by:            Ben Rubson, hselasky
  Submitted by:           hselasky
  Tested by:              Ben Rubson, jch
  Sponsored by:           Verisign, inc
  Differential Revision:  https://reviews.freebsd.org/D12267
  
  r324193:
  
  Forgotten bits in r324179:  Include sys/syslog.h if INVARIANTS is not defined

Modified:
  stable/11/sys/netinet/tcp_timewait.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet/tcp_timewait.c
==============================================================================
--- stable/11/sys/netinet/tcp_timewait.c	Tue Oct 24 08:39:05 2017	(r324947)
+++ stable/11/sys/netinet/tcp_timewait.c	Tue Oct 24 08:56:11 2017	(r324948)
@@ -47,6 +47,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/proc.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
+#ifndef INVARIANTS
+#include <sys/syslog.h>
+#endif
 #include <sys/protosw.h>
 #include <sys/random.h>
 
@@ -711,10 +714,29 @@ tcp_tw_2msl_scan(int reuse)
 			INP_WLOCK(inp);
 			tw = intotw(inp);
 			if (in_pcbrele_wlocked(inp)) {
-				KASSERT(tw == NULL, ("%s: held last inp "
-				    "reference but tw not NULL", __func__));
-				INP_INFO_RUNLOCK(&V_tcbinfo);
-				continue;
+				if (__predict_true(tw == NULL)) {
+					INP_INFO_RUNLOCK(&V_tcbinfo);
+					continue;
+				} else {
+					/* This should not happen as in TIMEWAIT
+					 * state the inp should not be destroyed
+					 * before its tcptw. If INVARIANTS is
+					 * defined panic.
+					 */
+#ifdef INVARIANTS
+					panic("%s: Panic before an infinite "
+					    "loop: INP_TIMEWAIT && (INP_FREED "
+					    "|| inp last reference) && tw != "
+					    "NULL", __func__);
+#else
+					log(LOG_ERR, "%s: Avoid an infinite "
+					    "loop: INP_TIMEWAIT && (INP_FREED "
+					    "|| inp last reference) && tw != "
+					    "NULL", __func__);
+#endif
+					INP_INFO_RUNLOCK(&V_tcbinfo);
+					break;
+				}
 			}
 
 			if (tw == NULL) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710240856.v9O8uBk2052603>