Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 31 Aug 2016 21:35:51 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r305161 - in stable/10/sys: kern sys
Message-ID:  <201608312135.u7VLZpHO022095@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Wed Aug 31 21:35:51 2016
New Revision: 305161
URL: https://svnweb.freebsd.org/changeset/base/305161

Log:
  MFC 303855:
  Handle races with listening socket close when connecting a unix socket.
  
  PR:	211531

Modified:
  stable/10/sys/kern/uipc_usrreq.c
  stable/10/sys/sys/unpcb.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/uipc_usrreq.c
==============================================================================
--- stable/10/sys/kern/uipc_usrreq.c	Wed Aug 31 21:35:38 2016	(r305160)
+++ stable/10/sys/kern/uipc_usrreq.c	Wed Aug 31 21:35:51 2016	(r305161)
@@ -429,6 +429,8 @@ uipc_attach(struct socket *so, int proto
 	unp->unp_socket = so;
 	so->so_pcb = unp;
 	unp->unp_refcount = 1;
+	if (so->so_head != NULL)
+		unp->unp_flags |= UNP_NASCENT;
 
 	UNP_LIST_LOCK();
 	unp->unp_gencnt = ++unp_gencnt;
@@ -651,14 +653,22 @@ uipc_detach(struct socket *so)
 	unp = sotounpcb(so);
 	KASSERT(unp != NULL, ("uipc_detach: unp == NULL"));
 
-	UNP_LINK_WLOCK();
+	vp = NULL;
+	local_unp_rights = 0;
+
 	UNP_LIST_LOCK();
-	UNP_PCB_LOCK(unp);
 	LIST_REMOVE(unp, unp_link);
 	unp->unp_gencnt = ++unp_gencnt;
 	--unp_count;
 	UNP_LIST_UNLOCK();
 
+	if ((unp->unp_flags & UNP_NASCENT) != 0) {
+		UNP_PCB_LOCK(unp);
+		goto teardown;
+	}
+	UNP_LINK_WLOCK();
+	UNP_PCB_LOCK(unp);
+
 	/*
 	 * XXXRW: Should assert vp->v_socket == so.
 	 */
@@ -686,6 +696,7 @@ uipc_detach(struct socket *so)
 	}
 	local_unp_rights = unp_rights;
 	UNP_LINK_WUNLOCK();
+teardown:
 	unp->unp_socket->so_pcb = NULL;
 	saved_unp_addr = unp->unp_addr;
 	unp->unp_addr = NULL;
@@ -1441,6 +1452,7 @@ unp_connect2(struct socket *so, struct s
 
 	if (so2->so_type != so->so_type)
 		return (EPROTOTYPE);
+	unp2->unp_flags &= ~UNP_NASCENT;
 	unp->unp_conn = unp2;
 
 	switch (so->so_type) {

Modified: stable/10/sys/sys/unpcb.h
==============================================================================
--- stable/10/sys/sys/unpcb.h	Wed Aug 31 21:35:38 2016	(r305160)
+++ stable/10/sys/sys/unpcb.h	Wed Aug 31 21:35:51 2016	(r305161)
@@ -103,10 +103,6 @@ struct unpcb {
 #define	UNP_WANTCRED			0x004	/* credentials wanted */
 #define	UNP_CONNWAIT			0x008	/* connect blocks until accepted */
 
-#define	UNPGC_REF			0x1	/* unpcb has external ref. */
-#define	UNPGC_DEAD			0x2	/* unpcb might be dead. */
-#define	UNPGC_SCANNED			0x4	/* Has been scanned. */
-
 /*
  * These flags are used to handle non-atomicity in connect() and bind()
  * operations on a socket: in particular, to avoid races between multiple
@@ -114,6 +110,14 @@ struct unpcb {
  */
 #define	UNP_CONNECTING			0x010	/* Currently connecting. */
 #define	UNP_BINDING			0x020	/* Currently binding. */
+#define	UNP_NASCENT			0x040	/* Newborn child socket. */
+
+/*
+ * Flags in unp_gcflag.
+ */
+#define	UNPGC_REF			0x1	/* unpcb has external ref. */
+#define	UNPGC_DEAD			0x2	/* unpcb might be dead. */
+#define	UNPGC_SCANNED			0x4	/* Has been scanned. */
 
 #define	sotounpcb(so)	((struct unpcb *)((so)->so_pcb))
 



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