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))
 
_______________________________________________
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