summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_usrreq.c
diff options
context:
space:
mode:
authorjch <jch@FreeBSD.org>2016-10-25 12:58:36 +0000
committerjch <jch@FreeBSD.org>2016-10-25 12:58:36 +0000
commit6498e6ff373c949b402b936ee26e299074de318a (patch)
treed2bc5fed5e991a1f8c82f1f5cc3831bb655abb41 /sys/netinet/tcp_usrreq.c
parent5bfa0fd12817c6fb8a546d52473156175cd9d2e5 (diff)
downloadFreeBSD-src-6498e6ff373c949b402b936ee26e299074de318a.zip
FreeBSD-src-6498e6ff373c949b402b936ee26e299074de318a.tar.gz
MFC r307551:
Fix a double-free when an inp transitions to INP_TIMEWAIT state after having been dropped. This change enforces in_pcbdrop() logic in tcp_input(): "in_pcbdrop() is used by TCP to mark an inpcb as unused and avoid future packet delivery or event notification when a socket remains open but TCP has closed." PR: 203175 Reported by: Palle Girgensohn, Slawa Olhovchenkov Tested by: Slawa Olhovchenkov Reviewed by: Slawa Olhovchenkov Approved by: gnn, Slawa Olhovchenkov Differential Revision: https://reviews.freebsd.org/D8211 Sponsored by: Verisign, inc
Diffstat (limited to 'sys/netinet/tcp_usrreq.c')
-rw-r--r--sys/netinet/tcp_usrreq.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 9955468..131eb28 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/jail.h>
+#include <sys/syslog.h>
#ifdef DDB
#include <ddb/ddb.h>
@@ -202,10 +203,26 @@ tcp_detach(struct socket *so, struct inpcb *inp)
* In all three cases the tcptw should not be freed here.
*/
if (inp->inp_flags & INP_DROPPED) {
- KASSERT(tp == NULL, ("tcp_detach: INP_TIMEWAIT && "
- "INP_DROPPED && tp != NULL"));
in_pcbdetach(inp);
- in_pcbfree(inp);
+ if (__predict_true(tp == NULL)) {
+ in_pcbfree(inp);
+ } else {
+ /*
+ * This case 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 inp double-free: "
+ "INP_TIMEWAIT && INP_DROPPED && tp != NULL"
+ , __func__);
+#else
+ log(LOG_ERR, "%s: Avoid an inp double-free: "
+ "INP_TIMEWAIT && INP_DROPPED && tp != NULL"
+ , __func__);
+#endif
+ INP_WUNLOCK(inp);
+ }
} else {
in_pcbdetach(inp);
INP_WUNLOCK(inp);
OpenPOWER on IntegriCloud