]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/uipc_usrreq.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / kern / uipc_usrreq.c
index cfe63ef281a3b34ea43ff97511598d2d42a8ae22..5e45f89ee12ee9ecf76f49d61223aa94428b173e 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2000-2014 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
@@ -71,7 +71,7 @@
 #include <sys/kernel.h>
 #include <sys/domain.h>
 #include <sys/fcntl.h>
-#include <sys/malloc.h>                /* XXX must be before <sys/file.h> */
+#include <sys/malloc.h>         /* XXX must be before <sys/file.h> */
 #include <sys/file_internal.h>
 #include <sys/guarded.h>
 #include <sys/filedesc.h>
@@ -93,6 +93,7 @@
 
 #include <kern/zalloc.h>
 #include <kern/locks.h>
+#include <kern/task.h>
 
 #if CONFIG_MACF
 #include <security/mac_framework.h>
 /*
  * Maximum number of FDs that can be passed in an mbuf
  */
-#define UIPC_MAX_CMSG_FD       512
-
-#define        f_msgcount f_fglob->fg_msgcount
-#define        f_cred f_fglob->fg_cred
-#define        f_ops f_fglob->fg_ops
-#define        f_offset f_fglob->fg_offset
-#define        f_data f_fglob->fg_data
-struct zone *unp_zone;
-static unp_gen_t unp_gencnt;
-static u_int unp_count;
-
-static lck_attr_t              *unp_mtx_attr;
-static lck_grp_t               *unp_mtx_grp;
-static lck_grp_attr_t          *unp_mtx_grp_attr;
-static lck_rw_t                *unp_list_mtx;
-
-static  lck_mtx_t              *unp_disconnect_lock;
-static lck_mtx_t               *unp_connect_lock;
+#define UIPC_MAX_CMSG_FD        512
+
+ZONE_DECLARE(unp_zone, "unpzone", sizeof(struct unpcb), ZC_NONE);
+static  unp_gen_t unp_gencnt;
+static  u_int unp_count;
+
+static  LCK_ATTR_DECLARE(unp_mtx_attr, 0, 0);
+static  LCK_GRP_DECLARE(unp_mtx_grp, "unp_list");
+static  LCK_RW_DECLARE_ATTR(unp_list_mtx, &unp_mtx_grp, &unp_mtx_attr);
+
+static  LCK_MTX_DECLARE_ATTR(unp_disconnect_lock, &unp_mtx_grp, &unp_mtx_attr);
+static  LCK_MTX_DECLARE_ATTR(unp_connect_lock, &unp_mtx_grp, &unp_mtx_attr);
+static  LCK_MTX_DECLARE_ATTR(uipc_lock, &unp_mtx_grp, &unp_mtx_attr);
+
 static  u_int                   disconnect_in_progress;
 
-extern lck_mtx_t *uipc_lock;
-static struct unp_head unp_shead, unp_dhead;
+static struct unp_head unp_shead, unp_dhead;
+static int      unp_defer, unp_gcing, unp_gcwait;
+static thread_t unp_gcthread = NULL;
+static LIST_HEAD(, fileglob) unp_msghead = LIST_HEAD_INITIALIZER(unp_msghead);
+
 
 /*
  * mDNSResponder tracing.  When enabled, endpoints connected to
@@ -134,11 +134,11 @@ static    struct unp_head unp_shead, unp_dhead;
  * to the data itself; this assumes ipc_msg_hdr in dnssd_ipc.h
  * of mDNSResponder stays the same.
  */
-#define        MDNSRESPONDER_PATH      "/var/run/mDNSResponder"
+#define MDNSRESPONDER_PATH      "/var/run/mDNSResponder"
 
-static int unpst_tracemdns;    /* enable tracing */
+static int unpst_tracemdns;     /* enable tracing */
 
-#define        MDNS_IPC_MSG_HDR_VERSION_1      1
+#define MDNS_IPC_MSG_HDR_VERSION_1      1
 
 struct mdns_ipc_msg_hdr {
        uint32_t version;
@@ -161,27 +161,27 @@ struct mdns_ipc_msg_hdr {
  *     need a proper out-of-band
  *     lock pushdown
  */
-static struct  sockaddr sun_noname = { sizeof (sun_noname), AF_LOCAL, { 0 } };
-static ino_t   unp_ino;                /* prototype for fake inode numbers */
-
-static int     unp_attach(struct socket *);
-static void    unp_detach(struct unpcb *);
-static int     unp_bind(struct unpcb *, struct sockaddr *, proc_t);
-static int     unp_connect(struct socket *, struct sockaddr *, proc_t);
-static void    unp_disconnect(struct unpcb *);
-static void    unp_shutdown(struct unpcb *);
-static void    unp_drop(struct unpcb *, int);
-__private_extern__ void        unp_gc(void);
-static void    unp_scan(struct mbuf *, void (*)(struct fileglob *, void *arg), void *arg);
-static void    unp_mark(struct fileglob *, __unused void *);
-static void    unp_discard(struct fileglob *, void *);
-static int     unp_internalize(struct mbuf *, proc_t);
-static int     unp_listen(struct unpcb *, proc_t);
-static void    unpcb_to_compat(struct unpcb *, struct unpcb_compat *);
+static struct   sockaddr sun_noname = { .sa_len = sizeof(sun_noname), .sa_family = AF_LOCAL, .sa_data = { 0 } };
+static ino_t    unp_ino;                /* prototype for fake inode numbers */
+
+static int      unp_attach(struct socket *);
+static void     unp_detach(struct unpcb *);
+static int      unp_bind(struct unpcb *, struct sockaddr *, proc_t);
+static int      unp_connect(struct socket *, struct sockaddr *, proc_t);
+static void     unp_disconnect(struct unpcb *);
+static void     unp_shutdown(struct unpcb *);
+static void     unp_drop(struct unpcb *, int);
+__private_extern__ void unp_gc(void);
+static void     unp_scan(struct mbuf *, void (*)(struct fileglob *, void *arg), void *arg);
+static void     unp_mark(struct fileglob *, __unused void *);
+static void     unp_discard(struct fileglob *, void *);
+static int      unp_internalize(struct mbuf *, proc_t);
+static int      unp_listen(struct unpcb *, proc_t);
+static void     unpcb_to_compat(struct unpcb *, struct unpcb_compat *);
 static void     unp_get_locks_in_order(struct socket *so, struct socket *conn_so);
 
-static void 
-unp_get_locks_in_order(struct socket *so, struct socket *conn_so) 
+static void
+unp_get_locks_in_order(struct socket *so, struct socket *conn_so)
 {
        if (so < conn_so) {
                socket_lock(conn_so, 1);
@@ -207,12 +207,13 @@ uipc_abort(struct socket *so)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp == 0)
-               return (EINVAL);
+       if (unp == 0) {
+               return EINVAL;
+       }
        unp_drop(unp, ECONNABORTED);
        unp_detach(unp);
        sofree(so);
-       return (0);
+       return 0;
 }
 
 static int
@@ -220,8 +221,9 @@ uipc_accept(struct socket *so, struct sockaddr **nam)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp == 0)
-               return (EINVAL);
+       if (unp == 0) {
+               return EINVAL;
+       }
 
        /*
         * Pass back name of connected socket,
@@ -234,7 +236,7 @@ uipc_accept(struct socket *so, struct sockaddr **nam)
        } else {
                *nam = dup_sockaddr((struct sockaddr *)&sun_noname, 1);
        }
-       return (0);
+       return 0;
 }
 
 /*
@@ -247,9 +249,10 @@ uipc_attach(struct socket *so, __unused int proto, __unused proc_t p)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp != 0)
-               return (EISCONN);
-       return (unp_attach(so));
+       if (unp != 0) {
+               return EISCONN;
+       }
+       return unp_attach(so);
 }
 
 static int
@@ -257,10 +260,11 @@ uipc_bind(struct socket *so, struct sockaddr *nam, proc_t p)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp == 0)
-               return (EINVAL);
+       if (unp == 0) {
+               return EINVAL;
+       }
 
-       return (unp_bind(unp, nam, p));
+       return unp_bind(unp, nam, p);
 }
 
 /*
@@ -273,9 +277,10 @@ uipc_connect(struct socket *so, struct sockaddr *nam, proc_t p)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp == 0)
-               return (EINVAL);
-       return (unp_connect(so, nam, p));
+       if (unp == 0) {
+               return EINVAL;
+       }
+       return unp_connect(so, nam, p);
 }
 
 /*
@@ -289,10 +294,11 @@ uipc_connect2(struct socket *so1, struct socket *so2)
 {
        struct unpcb *unp = sotounpcb(so1);
 
-       if (unp == 0)
-               return (EINVAL);
+       if (unp == 0) {
+               return EINVAL;
+       }
 
-       return (unp_connect2(so1, so2));
+       return unp_connect2(so1, so2);
 }
 
 /* control is EOPNOTSUPP */
@@ -302,12 +308,13 @@ uipc_detach(struct socket *so)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp == 0)
-               return (EINVAL);
+       if (unp == 0) {
+               return EINVAL;
+       }
 
-       lck_mtx_assert(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
        unp_detach(unp);
-       return (0);
+       return 0;
 }
 
 static int
@@ -315,10 +322,11 @@ uipc_disconnect(struct socket *so)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp == 0)
-               return (EINVAL);
+       if (unp == 0) {
+               return EINVAL;
+       }
        unp_disconnect(unp);
-       return (0);
+       return 0;
 }
 
 /*
@@ -330,9 +338,10 @@ uipc_listen(struct socket *so, __unused proc_t p)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp == 0 || unp->unp_vnode == 0)
-               return (EINVAL);
-       return (unp_listen(unp, p));
+       if (unp == 0 || unp->unp_vnode == 0) {
+               return EINVAL;
+       }
+       return unp_listen(unp, p);
 }
 
 static int
@@ -340,15 +349,16 @@ uipc_peeraddr(struct socket *so, struct sockaddr **nam)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp == NULL)
-               return (EINVAL);
+       if (unp == NULL) {
+               return EINVAL;
+       }
        if (unp->unp_conn != NULL && unp->unp_conn->unp_addr != NULL) {
                *nam = dup_sockaddr((struct sockaddr *)
                    unp->unp_conn->unp_addr, 1);
        } else {
                *nam = dup_sockaddr((struct sockaddr *)&sun_noname, 1);
        }
-       return (0);
+       return 0;
 }
 
 static int
@@ -357,19 +367,21 @@ uipc_rcvd(struct socket *so, __unused int flags)
        struct unpcb *unp = sotounpcb(so);
        struct socket *so2;
 
-       if (unp == 0)
-               return (EINVAL);
+       if (unp == 0) {
+               return EINVAL;
+       }
        switch (so->so_type) {
        case SOCK_DGRAM:
                panic("uipc_rcvd DGRAM?");
-               /*NOTREACHED*/
+       /*NOTREACHED*/
 
        case SOCK_STREAM:
-#define        rcv (&so->so_rcv)
-#define        snd (&so2->so_snd)
-               if (unp->unp_conn == 0)
+#define rcv (&so->so_rcv)
+#define snd (&so2->so_snd)
+               if (unp->unp_conn == 0) {
                        break;
-               
+               }
+
                so2 = unp->unp_conn->unp_socket;
                unp_get_locks_in_order(so, so2);
                /*
@@ -380,7 +392,9 @@ uipc_rcvd(struct socket *so, __unused int flags)
                unp->unp_mbcnt = rcv->sb_mbcnt;
                snd->sb_hiwat += unp->unp_cc - rcv->sb_cc;
                unp->unp_cc = rcv->sb_cc;
-               sowwakeup(so2);
+               if (sb_notify(&so2->so_snd)) {
+                       sowakeup(so2, &so2->so_snd, so);
+               }
 
                socket_unlock(so2, 1);
 
@@ -391,7 +405,7 @@ uipc_rcvd(struct socket *so, __unused int flags)
        default:
                panic("uipc_rcvd unknown socktype");
        }
-       return (0);
+       return 0;
 }
 
 /* pru_rcvoob is EOPNOTSUPP */
@@ -437,8 +451,9 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
                socket_unlock(so, 0);
                error = unp_internalize(control, p);
                socket_lock(so, 0);
-               if (error)
+               if (error) {
                        goto release;
+               }
        }
 
        switch (so->so_type) {
@@ -452,8 +467,10 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
                                break;
                        }
                        error = unp_connect(so, nam, p);
-                       if (error)
+                       if (error) {
+                               so->so_state &= ~SS_ISCONNECTING;
                                break;
+                       }
                } else {
                        if (unp->unp_conn == 0) {
                                error = ENOTCONN;
@@ -462,13 +479,15 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
                }
 
                so2 = unp->unp_conn->unp_socket;
-               if (so != so2)
+               if (so != so2) {
                        unp_get_locks_in_order(so, so2);
+               }
 
-               if (unp->unp_addr)
+               if (unp->unp_addr) {
                        from = (struct sockaddr *)unp->unp_addr;
-               else
+               } else {
                        from = &sun_noname;
+               }
                /*
                 * sbappendaddr() will fail when the receiver runs out of
                 * space; in contrast to SOCK_STREAM, we will lose messages
@@ -479,25 +498,29 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
                 */
                if (sbappendaddr(&so2->so_rcv, from, m, control, &error)) {
                        control = NULL;
-                       sorwakeup(so2);
+                       if (sb_notify(&so2->so_rcv)) {
+                               sowakeup(so2, &so2->so_rcv, so);
+                       }
                } else if (control != NULL && error == 0) {
                        /* A socket filter took control; don't touch it */
                        control = NULL;
                }
 
-               if (so != so2) 
+               if (so != so2) {
                        socket_unlock(so2, 1);
+               }
 
                m = NULL;
-               if (nam)
+               if (nam) {
                        unp_disconnect(unp);
+               }
                break;
        }
 
        case SOCK_STREAM: {
                int didreceive = 0;
-#define        rcv (&so2->so_rcv)
-#define        snd (&so->so_snd)
+#define rcv (&so2->so_rcv)
+#define snd (&so->so_snd)
                /* Connect if not connected yet. */
                /*
                 * Note: A better implementation would complain
@@ -506,8 +529,10 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
                if ((so->so_state & SS_ISCONNECTED) == 0) {
                        if (nam) {
                                error = unp_connect(so, nam, p);
-                               if (error)
-                                       break;  /* XXX */
+                               if (error) {
+                                       so->so_state &= ~SS_ISCONNECTING;
+                                       break;  /* XXX */
+                               }
                        } else {
                                error = ENOTCONN;
                                break;
@@ -518,13 +543,14 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
                        error = EPIPE;
                        break;
                }
-               if (unp->unp_conn == 0)
+               if (unp->unp_conn == 0) {
                        panic("uipc_send connected but no connection?");
+               }
 
                so2 = unp->unp_conn->unp_socket;
                unp_get_locks_in_order(so, so2);
 
-               /* Check socket state again as we might have unlocked the socket 
+               /* Check socket state again as we might have unlocked the socket
                 * while trying to get the locks in order
                 */
 
@@ -532,13 +558,13 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
                        error = EPIPE;
                        socket_unlock(so2, 1);
                        break;
-               }       
+               }
 
                if (unp->unp_flags & UNP_TRACE_MDNS) {
                        struct mdns_ipc_msg_hdr hdr;
 
-                       if (mbuf_copydata(m, 0, sizeof (hdr), &hdr) == 0 &&
-                           hdr.version  == ntohl(MDNS_IPC_MSG_HDR_VERSION_1)) {
+                       if (mbuf_copydata(m, 0, sizeof(hdr), &hdr) == 0 &&
+                           hdr.version == ntohl(MDNS_IPC_MSG_HDR_VERSION_1)) {
                                printf("%s[mDNSResponder] pid=%d (%s): op=0x%x\n",
                                    __func__, p->p_pid, p->p_comm, ntohl(hdr.op));
                        }
@@ -558,7 +584,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
 
                snd->sb_mbmax -= rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt;
                unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt;
-               if ((int32_t)snd->sb_hiwat >= 
+               if ((int32_t)snd->sb_hiwat >=
                    (int32_t)(rcv->sb_cc - unp->unp_conn->unp_cc)) {
                        snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc;
                } else {
@@ -567,7 +593,9 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
                unp->unp_conn->unp_cc = rcv->sb_cc;
                if (didreceive) {
                        control = NULL;
-                       sorwakeup(so2);
+                       if (sb_notify(&so2->so_rcv)) {
+                               sowakeup(so2, &so2->so_rcv, so);
+                       }
                } else if (control != NULL && error == 0) {
                        /* A socket filter took control; don't touch it */
                        control = NULL;
@@ -577,8 +605,8 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
                m = NULL;
 #undef snd
 #undef rcv
-               }
-               break;
+       }
+       break;
 
        default:
                panic("uipc_send unknown socktype");
@@ -600,11 +628,13 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
        }
 
 release:
-       if (control)
+       if (control) {
                m_freem(control);
-       if (m)
+       }
+       if (m) {
                m_freem(m);
-       return (error);
+       }
+       return error;
 }
 
 static int
@@ -614,16 +644,18 @@ uipc_sense(struct socket *so, void *ub, int isstat64)
        struct socket *so2;
        blksize_t blksize;
 
-       if (unp == 0)
-               return (EINVAL);
+       if (unp == 0) {
+               return EINVAL;
+       }
 
        blksize = so->so_snd.sb_hiwat;
        if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) {
                so2 = unp->unp_conn->unp_socket;
                blksize += so2->so_rcv.sb_cc;
        }
-       if (unp->unp_ino == 0)
+       if (unp->unp_ino == 0) {
                unp->unp_ino = unp_ino++;
+       }
 
        if (isstat64 != 0) {
                struct stat64  *sb64;
@@ -641,7 +673,7 @@ uipc_sense(struct socket *so, void *ub, int isstat64)
                sb->st_ino = (ino_t)(uintptr_t)unp->unp_ino;
        }
 
-       return (0);
+       return 0;
 }
 
 /*
@@ -658,11 +690,12 @@ uipc_shutdown(struct socket *so)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp == 0)
-               return (EINVAL);
+       if (unp == 0) {
+               return EINVAL;
+       }
        socantsendmore(so);
        unp_shutdown(unp);
-       return (0);
+       return 0;
 }
 
 /*
@@ -674,34 +707,35 @@ uipc_sockaddr(struct socket *so, struct sockaddr **nam)
 {
        struct unpcb *unp = sotounpcb(so);
 
-       if (unp == NULL)
-               return (EINVAL);
+       if (unp == NULL) {
+               return EINVAL;
+       }
        if (unp->unp_addr != NULL) {
                *nam = dup_sockaddr((struct sockaddr *)unp->unp_addr, 1);
        } else {
                *nam = dup_sockaddr((struct sockaddr *)&sun_noname, 1);
        }
-       return (0);
+       return 0;
 }
 
 struct pr_usrreqs uipc_usrreqs = {
-       .pru_abort =            uipc_abort,
-       .pru_accept =           uipc_accept,
-       .pru_attach =           uipc_attach,
-       .pru_bind =             uipc_bind,
-       .pru_connect =          uipc_connect,
-       .pru_connect2 =         uipc_connect2,
-       .pru_detach =           uipc_detach,
-       .pru_disconnect =       uipc_disconnect,
-       .pru_listen =           uipc_listen,
-       .pru_peeraddr =         uipc_peeraddr,
-       .pru_rcvd =             uipc_rcvd,
-       .pru_send =             uipc_send,
-       .pru_sense =            uipc_sense,
-       .pru_shutdown =         uipc_shutdown,
-       .pru_sockaddr =         uipc_sockaddr,
-       .pru_sosend =           sosend,
-       .pru_soreceive =        soreceive,
+       .pru_abort =            uipc_abort,
+       .pru_accept =           uipc_accept,
+       .pru_attach =           uipc_attach,
+       .pru_bind =             uipc_bind,
+       .pru_connect =          uipc_connect,
+       .pru_connect2 =         uipc_connect2,
+       .pru_detach =           uipc_detach,
+       .pru_disconnect =       uipc_disconnect,
+       .pru_listen =           uipc_listen,
+       .pru_peeraddr =         uipc_peeraddr,
+       .pru_rcvd =             uipc_rcvd,
+       .pru_send =             uipc_send,
+       .pru_sense =            uipc_sense,
+       .pru_shutdown =         uipc_shutdown,
+       .pru_sockaddr =         uipc_sockaddr,
+       .pru_sosend =           sosend,
+       .pru_soreceive =        soreceive,
 };
 
 int
@@ -710,6 +744,8 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
        struct unpcb *unp = sotounpcb(so);
        int error = 0;
        pid_t peerpid;
+       proc_t p;
+       task_t t;
        struct socket *peerso;
 
        switch (sopt->sopt_dir) {
@@ -718,12 +754,13 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
                case LOCAL_PEERCRED:
                        if (unp->unp_flags & UNP_HAVEPC) {
                                error = sooptcopyout(sopt, &unp->unp_peercred,
-                                   sizeof (unp->unp_peercred));
+                                   sizeof(unp->unp_peercred));
                        } else {
-                               if (so->so_type == SOCK_STREAM)
+                               if (so->so_type == SOCK_STREAM) {
                                        error = ENOTCONN;
-                               else
+                               } else {
                                        error = EINVAL;
+                               }
                        }
                        break;
                case LOCAL_PEERPID:
@@ -733,16 +770,18 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
                                break;
                        }
                        peerso = unp->unp_conn->unp_socket;
-                       if (peerso == NULL)
+                       if (peerso == NULL) {
                                panic("peer is connected but has no socket?");
+                       }
                        unp_get_locks_in_order(so, peerso);
                        if (sopt->sopt_name == LOCAL_PEEREPID &&
-                           peerso->so_flags & SOF_DELEGATED)
+                           peerso->so_flags & SOF_DELEGATED) {
                                peerpid = peerso->e_pid;
-                       else
+                       } else {
                                peerpid = peerso->last_pid;
+                       }
                        socket_unlock(peerso, 1);
-                       error = sooptcopyout(sopt, &peerpid, sizeof (peerpid));
+                       error = sooptcopyout(sopt, &peerpid, sizeof(peerpid));
                        break;
                case LOCAL_PEERUUID:
                case LOCAL_PEEREUUID:
@@ -751,16 +790,49 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
                                break;
                        }
                        peerso = unp->unp_conn->unp_socket;
-                       if (peerso == NULL)
+                       if (peerso == NULL) {
                                panic("peer is connected but has no socket?");
+                       }
                        unp_get_locks_in_order(so, peerso);
                        if (sopt->sopt_name == LOCAL_PEEREUUID &&
-                           peerso->so_flags & SOF_DELEGATED)
+                           peerso->so_flags & SOF_DELEGATED) {
                                error = sooptcopyout(sopt, &peerso->e_uuid,
-                                   sizeof (peerso->e_uuid));
-                       else
+                                   sizeof(peerso->e_uuid));
+                       } else {
                                error = sooptcopyout(sopt, &peerso->last_uuid,
-                                   sizeof (peerso->last_uuid));
+                                   sizeof(peerso->last_uuid));
+                       }
+                       socket_unlock(peerso, 1);
+                       break;
+               case LOCAL_PEERTOKEN:
+                       if (unp->unp_conn == NULL) {
+                               error = ENOTCONN;
+                               break;
+                       }
+                       peerso = unp->unp_conn->unp_socket;
+                       if (peerso == NULL) {
+                               panic("peer is connected but has no socket?");
+                       }
+                       unp_get_locks_in_order(so, peerso);
+                       peerpid = peerso->last_pid;
+                       p = proc_find(peerpid);
+                       if (p != PROC_NULL) {
+                               t = proc_task(p);
+                               if (t != TASK_NULL) {
+                                       audit_token_t peertoken;
+                                       mach_msg_type_number_t count = TASK_AUDIT_TOKEN_COUNT;
+                                       if (task_info(t, TASK_AUDIT_TOKEN, (task_info_t)&peertoken, &count) == KERN_SUCCESS) {
+                                               error = sooptcopyout(sopt, &peertoken, sizeof(peertoken));
+                                       } else {
+                                               error = EINVAL;
+                                       }
+                               } else {
+                                       error = EINVAL;
+                               }
+                               proc_rele(p);
+                       } else {
+                               error = EINVAL;
+                       }
                        socket_unlock(peerso, 1);
                        break;
                default:
@@ -774,7 +846,7 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
                break;
        }
 
-       return (error);
+       return error;
 }
 
 /*
@@ -786,28 +858,28 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
  * be large enough for at least one max-size datagram plus address.
  */
 #ifndef PIPSIZ
-#define        PIPSIZ  8192
+#define PIPSIZ  8192
 #endif
-static u_int32_t       unpst_sendspace = PIPSIZ;
-static u_int32_t       unpst_recvspace = PIPSIZ;
-static u_int32_t       unpdg_sendspace = 2*1024;       /* really max datagram size */
-static u_int32_t       unpdg_recvspace = 4*1024;
+static u_int32_t        unpst_sendspace = PIPSIZ;
+static u_int32_t        unpst_recvspace = PIPSIZ;
+static u_int32_t        unpdg_sendspace = 2 * 1024;       /* really max datagram size */
+static u_int32_t        unpdg_recvspace = 4 * 1024;
 
-static int     unp_rights;                     /* file descriptors in flight */
-static int     unp_disposed;                   /* discarded file descriptors */
+static int      unp_rights;                     /* file descriptors in flight */
+static int      unp_disposed;                   /* discarded file descriptors */
 
 SYSCTL_DECL(_net_local_stream);
 SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW | CTLFLAG_LOCKED,
-   &unpst_sendspace, 0, "");
+    &unpst_sendspace, 0, "");
 SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW | CTLFLAG_LOCKED,
-   &unpst_recvspace, 0, "");
+    &unpst_recvspace, 0, "");
 SYSCTL_INT(_net_local_stream, OID_AUTO, tracemdns, CTLFLAG_RW | CTLFLAG_LOCKED,
-   &unpst_tracemdns, 0, "");
+    &unpst_tracemdns, 0, "");
 SYSCTL_DECL(_net_local_dgram);
 SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW | CTLFLAG_LOCKED,
-   &unpdg_sendspace, 0, "");
+    &unpdg_sendspace, 0, "");
 SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW | CTLFLAG_LOCKED,
-   &unpdg_recvspace, 0, "");
+    &unpdg_recvspace, 0, "");
 SYSCTL_DECL(_net_local);
 SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD | CTLFLAG_LOCKED, &unp_rights, 0, "");
 
@@ -824,7 +896,6 @@ unp_attach(struct socket *so)
 
        if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
                switch (so->so_type) {
-
                case SOCK_STREAM:
                        error = soreserve(so, unpst_sendspace, unpst_recvspace);
                        break;
@@ -836,25 +907,26 @@ unp_attach(struct socket *so)
                default:
                        panic("unp_attach");
                }
-               if (error)
-                       return (error);
+               if (error) {
+                       return error;
+               }
        }
        unp = (struct unpcb *)zalloc(unp_zone);
-       if (unp == NULL)
-               return (ENOBUFS);
-       bzero(unp, sizeof (*unp));
+       if (unp == NULL) {
+               return ENOBUFS;
+       }
+       bzero(unp, sizeof(*unp));
 
-       lck_mtx_init(&unp->unp_mtx, 
-               unp_mtx_grp, unp_mtx_attr);
+       lck_mtx_init(&unp->unp_mtx, &unp_mtx_grp, &unp_mtx_attr);
 
-       lck_rw_lock_exclusive(unp_list_mtx);
+       lck_rw_lock_exclusive(&unp_list_mtx);
        LIST_INIT(&unp->unp_refs);
        unp->unp_socket = so;
        unp->unp_gencnt = ++unp_gencnt;
        unp_count++;
        LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ?
            &unp_dhead : &unp_shead, unp, unp_link);
-       lck_rw_done(unp_list_mtx);
+       lck_rw_done(&unp_list_mtx);
        so->so_pcb = (caddr_t)unp;
        /*
         * Mark AF_UNIX socket buffers accordingly so that:
@@ -876,7 +948,7 @@ unp_attach(struct socket *so)
         */
        so->so_rcv.sb_flags |= SB_UNIX;
        so->so_snd.sb_flags |= SB_UNIX;
-       return (0);
+       return 0;
 }
 
 static void
@@ -884,11 +956,11 @@ unp_detach(struct unpcb *unp)
 {
        int so_locked = 1;
 
-       lck_rw_lock_exclusive(unp_list_mtx);
+       lck_rw_lock_exclusive(&unp_list_mtx);
        LIST_REMOVE(unp, unp_link);
-       --unp_count; 
+       --unp_count;
        ++unp_gencnt;
-       lck_rw_done(unp_list_mtx);
+       lck_rw_done(&unp_list_mtx);
        if (unp->unp_vnode) {
                struct vnode *tvp = NULL;
                socket_unlock(unp->unp_socket, 0);
@@ -897,54 +969,56 @@ unp_detach(struct unpcb *unp)
                 * a thread closing the listening socket and a thread
                 * connecting to it.
                 */
-               lck_mtx_lock(unp_connect_lock);
+               lck_mtx_lock(&unp_connect_lock);
                socket_lock(unp->unp_socket, 0);
                if (unp->unp_vnode) {
                        tvp = unp->unp_vnode;
                        unp->unp_vnode->v_socket = NULL;
                        unp->unp_vnode = NULL;
                }
-               lck_mtx_unlock(unp_connect_lock);
-               if (tvp != NULL)
-                       vnode_rele(tvp);                /* drop the usecount */
+               lck_mtx_unlock(&unp_connect_lock);
+               if (tvp != NULL) {
+                       vnode_rele(tvp);                /* drop the usecount */
+               }
        }
-       if (unp->unp_conn)
+       if (unp->unp_conn) {
                unp_disconnect(unp);
+       }
        while (unp->unp_refs.lh_first) {
                struct unpcb *unp2 = NULL;
 
                /* This datagram socket is connected to one or more
                 * sockets. In order to avoid a race condition between removing
-                * this reference and closing the connected socket, we need 
+                * this reference and closing the connected socket, we need
                 * to check disconnect_in_progress
                 */
                if (so_locked == 1) {
                        socket_unlock(unp->unp_socket, 0);
                        so_locked = 0;
                }
-               lck_mtx_lock(unp_disconnect_lock);
+               lck_mtx_lock(&unp_disconnect_lock);
                while (disconnect_in_progress != 0) {
-                       (void)msleep((caddr_t)&disconnect_in_progress, unp_disconnect_lock,
-                               PSOCK, "disconnect", NULL);
+                       (void)msleep((caddr_t)&disconnect_in_progress, &unp_disconnect_lock,
+                           PSOCK, "disconnect", NULL);
                }
                disconnect_in_progress = 1;
-               lck_mtx_unlock(unp_disconnect_lock);
+               lck_mtx_unlock(&unp_disconnect_lock);
 
                /* Now we are sure that any unpcb socket disconnect is not happening */
                if (unp->unp_refs.lh_first != NULL) {
-                       unp2 = unp->unp_refs.lh_first;
-                       socket_lock(unp2->unp_socket, 1);
+                       unp2 = unp->unp_refs.lh_first;
+                       socket_lock(unp2->unp_socket, 1);
                }
-               
-               lck_mtx_lock(unp_disconnect_lock);
+
+               lck_mtx_lock(&unp_disconnect_lock);
                disconnect_in_progress = 0;
                wakeup(&disconnect_in_progress);
-               lck_mtx_unlock(unp_disconnect_lock);
-                       
+               lck_mtx_unlock(&unp_disconnect_lock);
+
                if (unp2 != NULL) {
                        /* We already locked this socket and have a reference on it */
-                       unp_drop(unp2, ECONNRESET);
-                       socket_unlock(unp2->unp_socket, 1);
+                       unp_drop(unp2, ECONNRESET);
+                       socket_unlock(unp2->unp_socket, 1);
                }
        }
 
@@ -984,25 +1058,45 @@ unp_bind(
        char buf[SOCK_MAXADDRLEN];
 
        if (nam->sa_family != 0 && nam->sa_family != AF_UNIX) {
-               return (EAFNOSUPPORT);
+               return EAFNOSUPPORT;
+       }
+
+       /*
+        * Check if the socket is already bound to an address
+        */
+       if (unp->unp_vnode != NULL) {
+               return EINVAL;
+       }
+       /*
+        * Check if the socket may have been shut down
+        */
+       if ((so->so_state & (SS_CANTRCVMORE | SS_CANTSENDMORE)) ==
+           (SS_CANTRCVMORE | SS_CANTSENDMORE)) {
+               return EINVAL;
        }
 
-       if (unp->unp_vnode != NULL)
-               return (EINVAL);
        namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
-       if (namelen <= 0)
-               return (EINVAL);
+       if (namelen <= 0) {
+               return EINVAL;
+       }
+       /*
+        * Note: sun_path is not a zero terminated "C" string
+        */
+       if (namelen >= SOCK_MAXADDRLEN) {
+               return EINVAL;
+       }
+       bcopy(soun->sun_path, buf, namelen);
+       buf[namelen] = 0;
 
        socket_unlock(so, 0);
 
-       strlcpy(buf, soun->sun_path, namelen+1);
        NDINIT(&nd, CREATE, OP_MKFIFO, FOLLOW | LOCKPARENT, UIO_SYSSPACE,
            CAST_USER_ADDR_T(buf), ctx);
        /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
        error = namei(&nd);
        if (error) {
                socket_lock(so, 0);
-               return (error);
+               return error;
        }
        dvp = nd.ni_dvp;
        vp = nd.ni_vp;
@@ -1018,7 +1112,7 @@ unp_bind(
                vnode_put(vp);
 
                socket_lock(so, 0);
-               return (EADDRINUSE);
+               return EADDRINUSE;
        }
 
        VATTR_INIT(&va);
@@ -1050,16 +1144,28 @@ unp_bind(
 
        if (error) {
                socket_lock(so, 0);
-               return (error);
+               return error;
        }
-       vnode_ref(vp);  /* gain a longterm reference */
+
        socket_lock(so, 0);
+
+       if (unp->unp_vnode != NULL) {
+               vnode_put(vp); /* drop the iocount */
+               return EINVAL;
+       }
+
+       error = vnode_ref(vp);  /* gain a longterm reference */
+       if (error) {
+               vnode_put(vp); /* drop the iocount */
+               return error;
+       }
+
        vp->v_socket = unp->unp_socket;
        unp->unp_vnode = vp;
        unp->unp_addr = (struct sockaddr_un *)dup_sockaddr(nam, 1);
-       vnode_put(vp);          /* drop the iocount */
+       vnode_put(vp);          /* drop the iocount */
 
-       return (0);
+       return 0;
 }
 
 
@@ -1084,7 +1190,7 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
 {
        struct sockaddr_un *soun = (struct sockaddr_un *)nam;
        struct vnode *vp;
-       struct socket *so2, *so3, *list_so=NULL;
+       struct socket *so2, *so3, *list_so = NULL;
        struct unpcb *unp, *unp2, *unp3;
        vfs_context_t ctx = vfs_context_current();
        int error, len;
@@ -1092,17 +1198,28 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
        char buf[SOCK_MAXADDRLEN];
 
        if (nam->sa_family != 0 && nam->sa_family != AF_UNIX) {
-               return (EAFNOSUPPORT);
+               return EAFNOSUPPORT;
        }
 
        unp = sotounpcb(so);
        so2 = so3 = NULL;
 
        len = nam->sa_len - offsetof(struct sockaddr_un, sun_path);
-       if (len <= 0)
-               return (EINVAL);
+       if (len <= 0) {
+               return EINVAL;
+       }
+       /*
+        * Note: sun_path is not a zero terminated "C" string
+        */
+       if (len >= SOCK_MAXADDRLEN) {
+               return EINVAL;
+       }
+
+       soisconnecting(so);
+
+       bcopy(soun->sun_path, buf, len);
+       buf[len] = 0;
 
-       strlcpy(buf, soun->sun_path, len+1);
        socket_unlock(so, 0);
 
        NDINIT(&nd, LOOKUP, OP_LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
@@ -1110,7 +1227,7 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
        error = namei(&nd);
        if (error) {
                socket_lock(so, 0);
-               return (error);
+               return error;
        }
        nameidone(&nd);
        vp = nd.ni_vp;
@@ -1121,7 +1238,7 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
        }
 
 #if CONFIG_MACF_SOCKET_SUBSET
-       error = mac_vnode_check_uipc_connect(ctx, vp);
+       error = mac_vnode_check_uipc_connect(ctx, vp, so);
        if (error) {
                socket_lock(so, 0);
                goto out;
@@ -1134,10 +1251,10 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
                goto out;
        }
 
-       lck_mtx_lock(unp_connect_lock);
+       lck_mtx_lock(&unp_connect_lock);
 
        if (vp->v_socket == 0) {
-               lck_mtx_unlock(unp_connect_lock);
+               lck_mtx_unlock(&unp_connect_lock);
                error = ECONNREFUSED;
                socket_lock(so, 0);
                goto out;
@@ -1145,7 +1262,7 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
 
        socket_lock(vp->v_socket, 1); /* Get a reference on the listening socket */
        so2 = vp->v_socket;
-       lck_mtx_unlock(unp_connect_lock);
+       lck_mtx_unlock(&unp_connect_lock);
 
 
        if (so2->so_pcb == NULL) {
@@ -1155,6 +1272,7 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
                        socket_lock(so, 0);
                } else {
                        /* Release the reference held for the listen socket */
+                       VERIFY(so2->so_usecount > 0);
                        so2->so_usecount--;
                }
                goto out;
@@ -1197,15 +1315,17 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
                                /* Release the reference held for
                                 * listen socket.
                                 */
+                               VERIFY(so2->so_usecount > 0);
                                so2->so_usecount--;
                        }
                        goto out;
                }
                unp2 = sotounpcb(so2);
                unp3 = sotounpcb(so3);
-               if (unp2->unp_addr)
+               if (unp2->unp_addr) {
                        unp3->unp_addr = (struct sockaddr_un *)
                            dup_sockaddr((struct sockaddr *)unp2->unp_addr, 1);
+               }
 
                /*
                 * unp_peercred management:
@@ -1243,19 +1363,12 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
                        socket_unlock(so2, 1);
                        socket_lock(so3, 0);
                        sofreelastref(so3, 1);
-                       goto out;
+                       goto out;
                }
                memcpy(&unp->unp_peercred, &unp2->unp_peercred,
-                   sizeof (unp->unp_peercred));
+                   sizeof(unp->unp_peercred));
                unp->unp_flags |= UNP_HAVEPC;
 
-#if CONFIG_MACF_SOCKET
-               /* XXXMAC: recursive lock: SOCK_LOCK(so); */
-               mac_socketpeer_label_associate_socket(so, so3);
-               mac_socketpeer_label_associate_socket(so3, so);
-               /* XXXMAC: SOCK_UNLOCK(so); */
-#endif /* MAC_SOCKET */
-
                /* Hold the reference on listening socket until the end */
                socket_unlock(so2, 0);
                list_so = so2;
@@ -1271,12 +1384,12 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
                 */
                if (unpst_tracemdns &&
                    !strncmp(soun->sun_path, MDNSRESPONDER_PATH,
-                   sizeof (MDNSRESPONDER_PATH))) {
+                   sizeof(MDNSRESPONDER_PATH))) {
                        unp->unp_flags |= UNP_TRACE_MDNS;
                        unp2->unp_flags |= UNP_TRACE_MDNS;
                }
        }
-       
+
        error = unp_connect2(so, so2);
 
 decref_out:
@@ -1288,6 +1401,7 @@ decref_out:
                         * This is possible only for SOCK_DGRAM sockets. We refuse
                         * connecting to the same socket for SOCK_STREAM sockets.
                         */
+                       VERIFY(so2->so_usecount > 0);
                        so2->so_usecount--;
                }
        }
@@ -1298,9 +1412,9 @@ decref_out:
        }
 
 out:
-       lck_mtx_assert(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
        vnode_put(vp);
-       return (error);
+       return error;
 }
 
 /*
@@ -1314,34 +1428,36 @@ unp_connect2(struct socket *so, struct socket *so2)
        struct unpcb *unp = sotounpcb(so);
        struct unpcb *unp2;
 
-       if (so2->so_type != so->so_type)
-               return (EPROTOTYPE);
+       if (so2->so_type != so->so_type) {
+               return EPROTOTYPE;
+       }
 
        unp2 = sotounpcb(so2);
 
-       lck_mtx_assert(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
-       lck_mtx_assert(&unp2->unp_mtx, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(&unp2->unp_mtx, LCK_MTX_ASSERT_OWNED);
 
        /* Verify both sockets are still opened */
-       if (unp == 0 || unp2 == 0)
-               return (EINVAL);
+       if (unp == 0 || unp2 == 0) {
+               return EINVAL;
+       }
 
        unp->unp_conn = unp2;
-       so2->so_usecount++; 
-       
-       switch (so->so_type) {
+       so2->so_usecount++;
 
+       switch (so->so_type) {
        case SOCK_DGRAM:
                LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink);
 
-               if (so != so2) {        
+               if (so != so2) {
                        /* Avoid lock order reversals due to drop/acquire in soisconnected. */
-                       /* Keep an extra reference on so2 that will be dropped
-                        * soon after getting the locks in order 
-                        */ 
+                       /* Keep an extra reference on so2 that will be dropped
+                        * soon after getting the locks in order
+                        */
                        socket_unlock(so2, 0);
                        soisconnected(so);
                        unp_get_locks_in_order(so, so2);
+                       VERIFY(so2->so_usecount > 0);
                        so2->so_usecount--;
                } else {
                        soisconnected(so);
@@ -1376,15 +1492,16 @@ unp_connect2(struct socket *so, struct socket *so2)
 
                unp_get_locks_in_order(so, so2);
                /* Decrement the extra reference left before */
+               VERIFY(so2->so_usecount > 0);
                so2->so_usecount--;
                break;
 
        default:
                panic("unknown socket type %d in unp_connect2", so->so_type);
        }
-       lck_mtx_assert(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
-       lck_mtx_assert(&unp2->unp_mtx, LCK_MTX_ASSERT_OWNED);
-       return (0);
+       LCK_MTX_ASSERT(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(&unp2->unp_mtx, LCK_MTX_ASSERT_OWNED);
+       return 0;
 }
 
 static void
@@ -1399,17 +1516,17 @@ unp_disconnect(struct unpcb *unp)
        if (unp->unp_conn == NULL) {
                return;
        }
-       lck_mtx_lock(unp_disconnect_lock);
+       lck_mtx_lock(&unp_disconnect_lock);
        while (disconnect_in_progress != 0) {
                if (so_locked == 1) {
                        socket_unlock(so, 0);
                        so_locked = 0;
                }
-               (void)msleep((caddr_t)&disconnect_in_progress, unp_disconnect_lock,
-                       PSOCK, "disconnect", NULL);
+               (void)msleep((caddr_t)&disconnect_in_progress, &unp_disconnect_lock,
+                   PSOCK, "disconnect", NULL);
        }
        disconnect_in_progress = 1;
-       lck_mtx_unlock(unp_disconnect_lock);
+       lck_mtx_unlock(&unp_disconnect_lock);
 
        if (so_locked == 0) {
                socket_lock(so, 0);
@@ -1436,7 +1553,7 @@ try_again:
                socket_lock(so2, 1);
                waitso = so2;
        } else {
-               if (so_locked == 1) { 
+               if (so_locked == 1) {
                        socket_unlock(so, 0);
                }
                socket_lock(so2, 1);
@@ -1445,59 +1562,63 @@ try_again:
        }
        so_locked = 1;
 
-       lck_mtx_assert(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
-       lck_mtx_assert(&unp2->unp_mtx, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(&unp2->unp_mtx, LCK_MTX_ASSERT_OWNED);
 
        /* Check for the UNP_DONTDISCONNECT flag, if it
         * is set, release both sockets and go to sleep
         */
-       
+
        if ((((struct unpcb *)waitso->so_pcb)->unp_flags & UNP_DONTDISCONNECT) != 0) {
                if (so != so2) {
                        socket_unlock(so2, 1);
                }
                so_locked = 0;
 
-               (void)msleep(waitso->so_pcb, &unp->unp_mtx, 
-                       PSOCK | PDROP, "unpdisconnect", NULL);
+               (void)msleep(waitso->so_pcb, &unp->unp_mtx,
+                   PSOCK | PDROP, "unpdisconnect", NULL);
                goto try_again;
        }
-       
+
        if (unp->unp_conn == NULL) {
                panic("unp_conn became NULL after sleep");
        }
 
        unp->unp_conn = NULL;
+       VERIFY(so2->so_usecount > 0);
        so2->so_usecount--;
 
-       if (unp->unp_flags & UNP_TRACE_MDNS)
+       if (unp->unp_flags & UNP_TRACE_MDNS) {
                unp->unp_flags &= ~UNP_TRACE_MDNS;
+       }
 
        switch (unp->unp_socket->so_type) {
-
        case SOCK_DGRAM:
                LIST_REMOVE(unp, unp_reflink);
                unp->unp_socket->so_state &= ~SS_ISCONNECTED;
-               if (so != so2)
+               if (so != so2) {
                        socket_unlock(so2, 1);
+               }
                break;
 
        case SOCK_STREAM:
                unp2->unp_conn = NULL;
+               VERIFY(so->so_usecount > 0);
                so->so_usecount--;
 
                /* Set the socket state correctly but do a wakeup later when
                 * we release all locks except the socket lock, this will avoid
                 * a deadlock.
                 */
-               unp->unp_socket->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
-               unp->unp_socket->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
+               unp->unp_socket->so_state &= ~(SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING);
+               unp->unp_socket->so_state |= (SS_CANTRCVMORE | SS_CANTSENDMORE | SS_ISDISCONNECTED);
 
-               unp2->unp_socket->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
-               unp->unp_socket->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
+               unp2->unp_socket->so_state &= ~(SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING);
+               unp->unp_socket->so_state |= (SS_CANTRCVMORE | SS_CANTSENDMORE | SS_ISDISCONNECTED);
 
-               if (unp2->unp_flags & UNP_TRACE_MDNS)
+               if (unp2->unp_flags & UNP_TRACE_MDNS) {
                        unp2->unp_flags &= ~UNP_TRACE_MDNS;
+               }
 
                strdisconn = 1;
                break;
@@ -1505,20 +1626,20 @@ try_again:
                panic("unknown socket type %d", so->so_type);
        }
 out:
-       lck_mtx_lock(unp_disconnect_lock);
+       lck_mtx_lock(&unp_disconnect_lock);
        disconnect_in_progress = 0;
        wakeup(&disconnect_in_progress);
-       lck_mtx_unlock(unp_disconnect_lock);
+       lck_mtx_unlock(&unp_disconnect_lock);
 
        if (strdisconn) {
                socket_unlock(so, 0);
                soisdisconnected(so2);
                socket_unlock(so2, 1);
 
-               socket_lock(so,0);
+               socket_lock(so, 0);
                soisdisconnected(so);
        }
-       lck_mtx_assert(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
        return;
 }
 
@@ -1576,7 +1697,7 @@ unp_pcblist SYSCTL_HANDLER_ARGS
        struct xunpgen xug;
        struct unp_head *head;
 
-       lck_rw_lock_shared(unp_list_mtx);
+       lck_rw_lock_shared(&unp_list_mtx);
        head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead);
 
        /*
@@ -1585,15 +1706,15 @@ unp_pcblist SYSCTL_HANDLER_ARGS
         */
        if (req->oldptr == USER_ADDR_NULL) {
                n = unp_count;
-               req->oldidx = 2 * sizeof (xug) + (n + n / 8) *
-                   sizeof (struct xunpcb);
-               lck_rw_done(unp_list_mtx);
-               return (0);
+               req->oldidx = 2 * sizeof(xug) + (n + n / 8) *
+                   sizeof(struct xunpcb);
+               lck_rw_done(&unp_list_mtx);
+               return 0;
        }
 
        if (req->newptr != USER_ADDR_NULL) {
-               lck_rw_done(unp_list_mtx);
-               return (EPERM);
+               lck_rw_done(&unp_list_mtx);
+               return EPERM;
        }
 
        /*
@@ -1602,38 +1723,39 @@ unp_pcblist SYSCTL_HANDLER_ARGS
        gencnt = unp_gencnt;
        n = unp_count;
 
-       bzero(&xug, sizeof (xug));
-       xug.xug_len = sizeof (xug);
+       bzero(&xug, sizeof(xug));
+       xug.xug_len = sizeof(xug);
        xug.xug_count = n;
        xug.xug_gen = gencnt;
        xug.xug_sogen = so_gencnt;
-       error = SYSCTL_OUT(req, &xug, sizeof (xug));
+       error = SYSCTL_OUT(req, &xug, sizeof(xug));
        if (error) {
-               lck_rw_done(unp_list_mtx);
-               return (error);
+               lck_rw_done(&unp_list_mtx);
+               return error;
        }
 
        /*
         * We are done if there is no pcb
         */
-       if (n == 0)  {
-               lck_rw_done(unp_list_mtx);
-               return (0);
+       if (n == 0) {
+               lck_rw_done(&unp_list_mtx);
+               return 0;
        }
 
-       MALLOC(unp_list, struct unpcb **, n * sizeof (*unp_list),
-           M_TEMP, M_WAITOK);
+       size_t unp_list_len = n * sizeof(*unp_list);
+       unp_list = kheap_alloc(KHEAP_TEMP, unp_list_len, Z_WAITOK);
        if (unp_list == 0) {
-               lck_rw_done(unp_list_mtx);
-               return (ENOMEM);
+               lck_rw_done(&unp_list_mtx);
+               return ENOMEM;
        }
 
        for (unp = head->lh_first, i = 0; unp && i < n;
            unp = unp->unp_link.le_next) {
-               if (unp->unp_gencnt <= gencnt)
+               if (unp->unp_gencnt <= gencnt) {
                        unp_list[i++] = unp;
+               }
        }
-       n = i;                  /* in case we lost some during malloc */
+       n = i;                  /* in case we lost some during malloc */
 
        error = 0;
        for (i = 0; i < n; i++) {
@@ -1641,24 +1763,26 @@ unp_pcblist SYSCTL_HANDLER_ARGS
                if (unp->unp_gencnt <= gencnt) {
                        struct xunpcb xu;
 
-                       bzero(&xu, sizeof (xu));
-                       xu.xu_len = sizeof (xu);
+                       bzero(&xu, sizeof(xu));
+                       xu.xu_len = sizeof(xu);
                        xu.xu_unpp = (_UNPCB_PTR(struct unpcb_compat *))
                            VM_KERNEL_ADDRPERM(unp);
                        /*
                         * XXX - need more locking here to protect against
                         * connect/disconnect races for SMP.
                         */
-                       if (unp->unp_addr)
-                               bcopy(unp->unp_addr, &xu.xu_addr,
+                       if (unp->unp_addr) {
+                               bcopy(unp->unp_addr, &xu.xu_au,
                                    unp->unp_addr->sun_len);
-                       if (unp->unp_conn && unp->unp_conn->unp_addr)
+                       }
+                       if (unp->unp_conn && unp->unp_conn->unp_addr) {
                                bcopy(unp->unp_conn->unp_addr,
-                                   &xu.xu_caddr,
+                                   &xu.xu_cau,
                                    unp->unp_conn->unp_addr->sun_len);
+                       }
                        unpcb_to_compat(unp, &xu.xu_unp);
                        sotoxsocket(unp->unp_socket, &xu.xu_socket);
-                       error = SYSCTL_OUT(req, &xu, sizeof (xu));
+                       error = SYSCTL_OUT(req, &xu, sizeof(xu));
                }
        }
        if (!error) {
@@ -1669,27 +1793,28 @@ unp_pcblist SYSCTL_HANDLER_ARGS
                 * while we were processing this request, and it
                 * might be necessary to retry.
                 */
-               bzero(&xug, sizeof (xug));
-               xug.xug_len = sizeof (xug);
+               bzero(&xug, sizeof(xug));
+               xug.xug_len = sizeof(xug);
                xug.xug_gen = unp_gencnt;
                xug.xug_sogen = so_gencnt;
                xug.xug_count = unp_count;
-               error = SYSCTL_OUT(req, &xug, sizeof (xug));
+               error = SYSCTL_OUT(req, &xug, sizeof(xug));
        }
-       FREE(unp_list, M_TEMP);
-       lck_rw_done(unp_list_mtx);
-       return (error);
+       kheap_free(KHEAP_TEMP, unp_list, unp_list_len);
+       lck_rw_done(&unp_list_mtx);
+       return error;
 }
 
 SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist,
-            CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
-            (caddr_t)(long)SOCK_DGRAM, 0, unp_pcblist, "S,xunpcb",
-            "List of active local datagram sockets");
+    CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
+    (caddr_t)(long)SOCK_DGRAM, 0, unp_pcblist, "S,xunpcb",
+    "List of active local datagram sockets");
 SYSCTL_PROC(_net_local_stream, OID_AUTO, pcblist,
-            CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
-            (caddr_t)(long)SOCK_STREAM, 0, unp_pcblist, "S,xunpcb",
-            "List of active local stream sockets");
+    CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
+    (caddr_t)(long)SOCK_STREAM, 0, unp_pcblist, "S,xunpcb",
+    "List of active local stream sockets");
 
+#if XNU_TARGET_OS_OSX
 
 static int
 unp_pcblist64 SYSCTL_HANDLER_ARGS
@@ -1701,7 +1826,7 @@ unp_pcblist64 SYSCTL_HANDLER_ARGS
        struct xunpgen xug;
        struct unp_head *head;
 
-       lck_rw_lock_shared(unp_list_mtx);
+       lck_rw_lock_shared(&unp_list_mtx);
        head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead);
 
        /*
@@ -1710,15 +1835,15 @@ unp_pcblist64 SYSCTL_HANDLER_ARGS
         */
        if (req->oldptr == USER_ADDR_NULL) {
                n = unp_count;
-               req->oldidx = 2 * sizeof (xug) + (n + n / 8) *
-                   (sizeof (struct xunpcb64)); 
-               lck_rw_done(unp_list_mtx);
-               return (0);
+               req->oldidx = 2 * sizeof(xug) + (n + n / 8) *
+                   (sizeof(struct xunpcb64));
+               lck_rw_done(&unp_list_mtx);
+               return 0;
        }
 
        if (req->newptr != USER_ADDR_NULL) {
-               lck_rw_done(unp_list_mtx);
-               return (EPERM);
+               lck_rw_done(&unp_list_mtx);
+               return EPERM;
        }
 
        /*
@@ -1727,48 +1852,49 @@ unp_pcblist64 SYSCTL_HANDLER_ARGS
        gencnt = unp_gencnt;
        n = unp_count;
 
-       bzero(&xug, sizeof (xug));
-       xug.xug_len = sizeof (xug);
+       bzero(&xug, sizeof(xug));
+       xug.xug_len = sizeof(xug);
        xug.xug_count = n;
        xug.xug_gen = gencnt;
        xug.xug_sogen = so_gencnt;
-       error = SYSCTL_OUT(req, &xug, sizeof (xug));
+       error = SYSCTL_OUT(req, &xug, sizeof(xug));
        if (error) {
-               lck_rw_done(unp_list_mtx);
-               return (error);
+               lck_rw_done(&unp_list_mtx);
+               return error;
        }
 
        /*
         * We are done if there is no pcb
         */
-       if (n == 0)  {
-               lck_rw_done(unp_list_mtx);
-               return (0);
+       if (n == 0) {
+               lck_rw_done(&unp_list_mtx);
+               return 0;
        }
 
-       MALLOC(unp_list, struct unpcb **, n * sizeof (*unp_list),
-           M_TEMP, M_WAITOK);
+       size_t unp_list_size = n * sizeof(*unp_list);
+       unp_list = kheap_alloc(KHEAP_TEMP, unp_list_size, Z_WAITOK);
        if (unp_list == 0) {
-               lck_rw_done(unp_list_mtx);
-               return (ENOMEM);
+               lck_rw_done(&unp_list_mtx);
+               return ENOMEM;
        }
 
        for (unp = head->lh_first, i = 0; unp && i < n;
            unp = unp->unp_link.le_next) {
-               if (unp->unp_gencnt <= gencnt)
+               if (unp->unp_gencnt <= gencnt) {
                        unp_list[i++] = unp;
+               }
        }
-       n = i;                  /* in case we lost some during malloc */
+       n = i;                  /* in case we lost some during malloc */
 
        error = 0;
        for (i = 0; i < n; i++) {
                unp = unp_list[i];
                if (unp->unp_gencnt <= gencnt) {
                        struct xunpcb64 xu;
-                       size_t          xu_len = sizeof(struct xunpcb64);
+                       size_t          xu_len = sizeof(struct xunpcb64);
 
                        bzero(&xu, xu_len);
-                       xu.xu_len = xu_len;
+                       xu.xu_len = (u_int32_t)xu_len;
                        xu.xu_unpp = (u_int64_t)VM_KERNEL_ADDRPERM(unp);
                        xu.xunp_link.le_next = (u_int64_t)
                            VM_KERNEL_ADDRPERM(unp->unp_link.le_next);
@@ -1791,20 +1917,23 @@ unp_pcblist64 SYSCTL_HANDLER_ARGS
                        xu.xunp_mbcnt = unp->unp_mbcnt;
                        xu.xunp_gencnt = unp->unp_gencnt;
 
-                       if (unp->unp_socket)
+                       if (unp->unp_socket) {
                                sotoxsocket64(unp->unp_socket, &xu.xu_socket);
+                       }
 
                        /*
                         * XXX - need more locking here to protect against
                         * connect/disconnect races for SMP.
                         */
-                        if (unp->unp_addr)
-                                bcopy(unp->unp_addr, &xu.xunp_addr,
-                                    unp->unp_addr->sun_len);
-                        if (unp->unp_conn && unp->unp_conn->unp_addr)
-                                bcopy(unp->unp_conn->unp_addr,
-                                    &xu.xunp_caddr,
-                                    unp->unp_conn->unp_addr->sun_len);
+                       if (unp->unp_addr) {
+                               bcopy(unp->unp_addr, &xu.xu_au,
+                                   unp->unp_addr->sun_len);
+                       }
+                       if (unp->unp_conn && unp->unp_conn->unp_addr) {
+                               bcopy(unp->unp_conn->unp_addr,
+                                   &xu.xu_cau,
+                                   unp->unp_conn->unp_addr->sun_len);
+                       }
 
                        error = SYSCTL_OUT(req, &xu, xu_len);
                }
@@ -1817,27 +1946,28 @@ unp_pcblist64 SYSCTL_HANDLER_ARGS
                 * while we were processing this request, and it
                 * might be necessary to retry.
                 */
-               bzero(&xug, sizeof (xug));
-               xug.xug_len = sizeof (xug);
+               bzero(&xug, sizeof(xug));
+               xug.xug_len = sizeof(xug);
                xug.xug_gen = unp_gencnt;
                xug.xug_sogen = so_gencnt;
                xug.xug_count = unp_count;
-               error = SYSCTL_OUT(req, &xug, sizeof (xug));
+               error = SYSCTL_OUT(req, &xug, sizeof(xug));
        }
-       FREE(unp_list, M_TEMP);
-       lck_rw_done(unp_list_mtx);
-       return (error);
+       kheap_free(KHEAP_TEMP, unp_list, unp_list_size);
+       lck_rw_done(&unp_list_mtx);
+       return error;
 }
 
 SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist64,
-           CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
-           (caddr_t)(long)SOCK_DGRAM, 0, unp_pcblist64, "S,xunpcb64",
-           "List of active local datagram sockets 64 bit");
+    CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
+    (caddr_t)(long)SOCK_DGRAM, 0, unp_pcblist64, "S,xunpcb64",
+    "List of active local datagram sockets 64 bit");
 SYSCTL_PROC(_net_local_stream, OID_AUTO, pcblist64,
-           CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
-           (caddr_t)(long)SOCK_STREAM, 0, unp_pcblist64, "S,xunpcb64",
-           "List of active local stream sockets 64 bit");
+    CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
+    (caddr_t)(long)SOCK_STREAM, 0, unp_pcblist64, "S,xunpcb64",
+    "List of active local stream sockets 64 bit");
 
+#endif /* XNU_TARGET_OS_OSX */
 
 static void
 unp_shutdown(struct unpcb *unp)
@@ -1857,10 +1987,156 @@ unp_drop(struct unpcb *unp, int errno)
 {
        struct socket *so = unp->unp_socket;
 
-       so->so_error = errno;
+       so->so_error = (u_short)errno;
        unp_disconnect(unp);
 }
 
+/* always called under uipc_lock */
+static void
+unp_gc_wait(void)
+{
+       if (unp_gcthread == current_thread()) {
+               return;
+       }
+
+       while (unp_gcing != 0) {
+               unp_gcwait = 1;
+               msleep(&unp_gcing, &uipc_lock, 0, "unp_gc_wait", NULL);
+       }
+}
+
+/*
+ * fg_insertuipc_mark
+ *
+ * Description:        Mark fileglob for insertion onto message queue if needed
+ *             Also takes fileglob reference
+ *
+ * Parameters: fg      Fileglob pointer to insert
+ *
+ * Returns:    true, if the fileglob needs to be inserted onto msg queue
+ *
+ * Locks:      Takes and drops fg_lock, potentially many times
+ */
+static boolean_t
+fg_insertuipc_mark(struct fileglob * fg)
+{
+       boolean_t insert = FALSE;
+
+       lck_mtx_lock_spin(&fg->fg_lock);
+       while (fg->fg_lflags & FG_RMMSGQ) {
+               lck_mtx_convert_spin(&fg->fg_lock);
+
+               fg->fg_lflags |= FG_WRMMSGQ;
+               msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_insertuipc", NULL);
+       }
+
+       os_ref_retain_raw(&fg->fg_count, &f_refgrp);
+       fg->fg_msgcount++;
+       if (fg->fg_msgcount == 1) {
+               fg->fg_lflags |= FG_INSMSGQ;
+               insert = TRUE;
+       }
+       lck_mtx_unlock(&fg->fg_lock);
+       return insert;
+}
+
+/*
+ * fg_insertuipc
+ *
+ * Description:        Insert marked fileglob onto message queue
+ *
+ * Parameters: fg      Fileglob pointer to insert
+ *
+ * Returns:    void
+ *
+ * Locks:      Takes and drops fg_lock & uipc_lock
+ *             DO NOT call this function with proc_fdlock held as unp_gc()
+ *             can potentially try to acquire proc_fdlock, which can result
+ *             in a deadlock if this function is in unp_gc_wait().
+ */
+static void
+fg_insertuipc(struct fileglob * fg)
+{
+       if (fg->fg_lflags & FG_INSMSGQ) {
+               lck_mtx_lock_spin(&uipc_lock);
+               unp_gc_wait();
+               LIST_INSERT_HEAD(&unp_msghead, fg, f_msglist);
+               lck_mtx_unlock(&uipc_lock);
+               lck_mtx_lock(&fg->fg_lock);
+               fg->fg_lflags &= ~FG_INSMSGQ;
+               if (fg->fg_lflags & FG_WINSMSGQ) {
+                       fg->fg_lflags &= ~FG_WINSMSGQ;
+                       wakeup(&fg->fg_lflags);
+               }
+               lck_mtx_unlock(&fg->fg_lock);
+       }
+}
+
+/*
+ * fg_removeuipc_mark
+ *
+ * Description:        Mark the fileglob for removal from message queue if needed
+ *             Also releases fileglob message queue reference
+ *
+ * Parameters: fg      Fileglob pointer to remove
+ *
+ * Returns:    true, if the fileglob needs to be removed from msg queue
+ *
+ * Locks:      Takes and drops fg_lock, potentially many times
+ */
+static boolean_t
+fg_removeuipc_mark(struct fileglob * fg)
+{
+       boolean_t remove = FALSE;
+
+       lck_mtx_lock_spin(&fg->fg_lock);
+       while (fg->fg_lflags & FG_INSMSGQ) {
+               lck_mtx_convert_spin(&fg->fg_lock);
+
+               fg->fg_lflags |= FG_WINSMSGQ;
+               msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_removeuipc", NULL);
+       }
+       fg->fg_msgcount--;
+       if (fg->fg_msgcount == 0) {
+               fg->fg_lflags |= FG_RMMSGQ;
+               remove = TRUE;
+       }
+       lck_mtx_unlock(&fg->fg_lock);
+       return remove;
+}
+
+/*
+ * fg_removeuipc
+ *
+ * Description:        Remove marked fileglob from message queue
+ *
+ * Parameters: fg      Fileglob pointer to remove
+ *
+ * Returns:    void
+ *
+ * Locks:      Takes and drops fg_lock & uipc_lock
+ *             DO NOT call this function with proc_fdlock held as unp_gc()
+ *             can potentially try to acquire proc_fdlock, which can result
+ *             in a deadlock if this function is in unp_gc_wait().
+ */
+static void
+fg_removeuipc(struct fileglob * fg)
+{
+       if (fg->fg_lflags & FG_RMMSGQ) {
+               lck_mtx_lock_spin(&uipc_lock);
+               unp_gc_wait();
+               LIST_REMOVE(fg, f_msglist);
+               lck_mtx_unlock(&uipc_lock);
+               lck_mtx_lock(&fg->fg_lock);
+               fg->fg_lflags &= ~FG_RMMSGQ;
+               if (fg->fg_lflags & FG_WRMMSGQ) {
+                       fg->fg_lflags &= ~FG_WRMMSGQ;
+                       wakeup(&fg->fg_lflags);
+               }
+               lck_mtx_unlock(&fg->fg_lock);
+       }
+}
+
 /*
  * Returns:    0                       Success
  *             EMSGSIZE                The new fd's will not fit
@@ -1869,19 +2145,19 @@ unp_drop(struct unpcb *unp, int errno)
 int
 unp_externalize(struct mbuf *rights)
 {
-       proc_t p = current_proc();              /* XXX */
+       proc_t p = current_proc();              /* XXX */
        int i;
        struct cmsghdr *cm = mtod(rights, struct cmsghdr *);
        struct fileglob **rp = (struct fileglob **)(cm + 1);
        int *fds = (int *)(cm + 1);
        struct fileproc *fp;
-       struct fileglob **fgl;
-       int newfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int);
+       struct fileproc **fileproc_l;
+       int newfds = (cm->cmsg_len - sizeof(*cm)) / sizeof(int);
        int f, error = 0;
 
-       MALLOC(fgl, struct fileglob **, newfds * sizeof (struct fileglob *),
-               M_TEMP, M_WAITOK);
-       if (fgl == NULL) {
+       fileproc_l = kheap_alloc(KHEAP_TEMP,
+           newfds * sizeof(struct fileproc *), Z_WAITOK);
+       if (fileproc_l == NULL) {
                error = ENOMEM;
                goto discard;
        }
@@ -1900,103 +2176,78 @@ unp_externalize(struct mbuf *rights)
         * now change each pointer to an fd in the global table to
         * an integer that is the index to the local fd table entry
         * that we set up to point to the global one we are transferring.
-        * XXX (1) this assumes a pointer and int are the same size, 
+        * XXX (1) this assumes a pointer and int are the same size,
         * XXX     or the mbuf can hold the expansion
         * XXX (2) allocation failures should be non-fatal
         */
        for (i = 0; i < newfds; i++) {
-#if CONFIG_MACF_SOCKET
-               /*
-                * If receive access is denied, don't pass along
-                * and error message, just discard the descriptor.
-                */
-               if (mac_file_check_receive(kauth_cred_get(), rp[i])) {
-                       proc_fdunlock(p);
-                       unp_discard(rp[i], p);
-                       fds[i] = 0;
-                       proc_fdlock(p);
-                       continue;
-               }
-#endif
-               if (fdalloc(p, 0, &f))
+               if (fdalloc(p, 0, &f)) {
                        panic("unp_externalize:fdalloc");
+               }
                fp = fileproc_alloc_init(NULL);
-               if (fp == NULL)
-                       panic("unp_externalize: MALLOC_ZONE");
-               fp->f_iocount = 0;
-               fp->f_fglob = rp[i];
-               if (fg_removeuipc_mark(rp[i]))
-                       fgl[i] = rp[i];
-               else
-                       fgl[i] = NULL;
+               if (fp == NULL) {
+                       panic("unp_externalize:fileproc_alloc_init");
+               }
+               fp->fp_glob = rp[i];
+               if (fg_removeuipc_mark(rp[i])) {
+                       /*
+                        * Take an iocount on the fp for completing the
+                        * removal from the global msg queue
+                        */
+                       os_ref_retain_locked(&fp->fp_iocount);
+                       fileproc_l[i] = fp;
+               } else {
+                       fileproc_l[i] = NULL;
+               }
                procfdtbl_releasefd(p, f, fp);
                fds[i] = f;
        }
        proc_fdunlock(p);
 
        for (i = 0; i < newfds; i++) {
-               if (fgl[i] != NULL) {
-                       VERIFY(fgl[i]->fg_lflags & FG_RMMSGQ);
-                       fg_removeuipc(fgl[i]);
+               if (fileproc_l[i] != NULL) {
+                       VERIFY(fileproc_l[i]->fp_glob != NULL &&
+                           (fileproc_l[i]->fp_glob->fg_lflags & FG_RMMSGQ));
+                       VERIFY(fds[i] >= 0);
+                       fg_removeuipc(fileproc_l[i]->fp_glob);
+
+                       /* Drop the iocount */
+                       fp_drop(p, fds[i], fileproc_l[i], 0);
+                       fileproc_l[i] = NULL;
                }
-               if (fds[i])
+               if (fds[i] != 0) {
                        (void) OSAddAtomic(-1, &unp_rights);
+               }
        }
 
 discard:
-       if (fgl)
-               FREE(fgl, M_TEMP);
+       kheap_free(KHEAP_TEMP, fileproc_l,
+           newfds * sizeof(struct fileproc *));
        if (error) {
                for (i = 0; i < newfds; i++) {
                        unp_discard(*rp, p);
                        *rp++ = NULL;
                }
        }
-       return (error);
+       return error;
 }
 
 void
 unp_init(void)
 {
        _CASSERT(UIPC_MAX_CMSG_FD >= (MCLBYTES / sizeof(int)));
-       unp_zone = zinit(sizeof (struct unpcb),
-           (nmbclusters * sizeof (struct unpcb)), 4096, "unpzone");
-
-       if (unp_zone == 0)
-               panic("unp_init");
        LIST_INIT(&unp_dhead);
        LIST_INIT(&unp_shead);
-
-       /*
-        * allocate lock group attribute and group for udp pcb mutexes
-        */
-       unp_mtx_grp_attr = lck_grp_attr_alloc_init();
-
-       unp_mtx_grp = lck_grp_alloc_init("unp_list", unp_mtx_grp_attr);
-
-       unp_mtx_attr = lck_attr_alloc_init();
-
-       if ((unp_list_mtx = lck_rw_alloc_init(unp_mtx_grp,
-           unp_mtx_attr)) == NULL)
-               return; /* pretty much dead if this fails... */
-
-       if ((unp_disconnect_lock = lck_mtx_alloc_init(unp_mtx_grp,
-               unp_mtx_attr)) == NULL)
-               return;
-
-       if ((unp_connect_lock = lck_mtx_alloc_init(unp_mtx_grp,
-               unp_mtx_attr)) == NULL)
-               return;
 }
 
 #ifndef MIN
-#define        MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
 #endif
 
 /*
  * Returns:    0                       Success
  *             EINVAL
- *     fdgetf_noref:EBADF
+ *             EBADF
  */
 static int
 unp_internalize(struct mbuf *control, proc_t p)
@@ -2012,9 +2263,9 @@ unp_internalize(struct mbuf *control, proc_t p)
        /* 64bit: cmsg_len is 'uint32_t', m_len is 'long' */
        if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
            (socklen_t)cm->cmsg_len != (socklen_t)control->m_len) {
-               return (EINVAL);
+               return EINVAL;
        }
-       oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int);
+       oldfds = (cm->cmsg_len - sizeof(*cm)) / sizeof(int);
        bzero(fg_ins, sizeof(fg_ins));
 
        proc_fdlock(p);
@@ -2022,29 +2273,30 @@ unp_internalize(struct mbuf *control, proc_t p)
 
        for (i = 0; i < oldfds; i++) {
                struct fileproc *tmpfp;
-               if (((error = fdgetf_noref(p, fds[i], &tmpfp)) != 0)) {
+               if ((tmpfp = fp_get_noref_locked(p, fds[i])) == NULL) {
                        proc_fdunlock(p);
-                       return (error);
-               } else if (!file_issendable(p, tmpfp)) {
+                       return EBADF;
+               } else if (!fg_sendable(tmpfp->fp_glob)) {
                        proc_fdunlock(p);
-                       return (EINVAL);
-               } else if (FP_ISGUARDED(tmpfp, GUARD_SOCKET_IPC)) {
+                       return EINVAL;
+               } else if (fp_isguarded(tmpfp, GUARD_SOCKET_IPC)) {
                        error = fp_guard_exception(p,
-                               fds[i], tmpfp, kGUARD_EXC_SOCKET_IPC);
+                           fds[i], tmpfp, kGUARD_EXC_SOCKET_IPC);
                        proc_fdunlock(p);
-                       return (error);
+                       return error;
                }
        }
        rp = (struct fileglob **)(cm + 1);
 
-       /* On K64 we need to walk backwards because a fileglob * is twice the size of an fd 
+       /* On K64 we need to walk backwards because a fileglob * is twice the size of an fd
         * and doing them in-order would result in stomping over unprocessed fd's
         */
        for (i = (oldfds - 1); i >= 0; i--) {
-               (void) fdgetf_noref(p, fds[i], &fp);
-               if (fg_insertuipc_mark(fp->f_fglob))
+               fp = fp_get_noref_locked(p, fds[i]);
+               if (fg_insertuipc_mark(fp->fp_glob)) {
                        fg_ins[i / 8] |= 0x80 >> (i % 8);
-               rp[i] = fp->f_fglob;
+               }
+               rp[i] = fp->fp_glob;
        }
        proc_fdunlock(p);
 
@@ -2056,26 +2308,9 @@ unp_internalize(struct mbuf *control, proc_t p)
                (void) OSAddAtomic(1, &unp_rights);
        }
 
-       return (0);
-}
-
-static int     unp_defer, unp_gcing, unp_gcwait;
-static thread_t unp_gcthread = NULL;
-
-/* always called under uipc_lock */
-void
-unp_gc_wait(void)
-{
-       if (unp_gcthread == current_thread())
-               return;
-
-       while (unp_gcing != 0) {
-               unp_gcwait = 1;
-               msleep(&unp_gcing, uipc_lock, 0 , "unp_gc_wait", NULL);
-       }
+       return 0;
 }
 
-
 __private_extern__ void
 unp_gc(void)
 {
@@ -2086,32 +2321,30 @@ unp_gc(void)
        int nunref, i;
        int need_gcwakeup = 0;
 
-       lck_mtx_lock(uipc_lock);
+       lck_mtx_lock(&uipc_lock);
        if (unp_gcing) {
-               lck_mtx_unlock(uipc_lock);
+               lck_mtx_unlock(&uipc_lock);
                return;
        }
        unp_gcing = 1;
        unp_defer = 0;
        unp_gcthread = current_thread();
-       lck_mtx_unlock(uipc_lock);
+       lck_mtx_unlock(&uipc_lock);
        /*
         * before going through all this, set all FDs to
         * be NOT defered and NOT externally accessible
         */
-       for (fg = fmsghead.lh_first; fg != 0; fg = fg->f_msglist.le_next) {
-               lck_mtx_lock(&fg->fg_lock);
-               fg->fg_flag &= ~(FMARK|FDEFER);
-               lck_mtx_unlock(&fg->fg_lock);
+       for (fg = unp_msghead.lh_first; fg != 0; fg = fg->f_msglist.le_next) {
+               os_atomic_andnot(&fg->fg_flag, FMARK | FDEFER, relaxed);
        }
        do {
-               for (fg = fmsghead.lh_first; fg != 0;
+               for (fg = unp_msghead.lh_first; fg != 0;
                    fg = fg->f_msglist.le_next) {
                        lck_mtx_lock(&fg->fg_lock);
                        /*
                         * If the file is not open, skip it
                         */
-                       if (fg->fg_count == 0) {
+                       if (os_ref_get_count_raw(&fg->fg_count) == 0) {
                                lck_mtx_unlock(&fg->fg_lock);
                                continue;
                        }
@@ -2121,7 +2354,7 @@ unp_gc(void)
                         * and un-mark it
                         */
                        if (fg->fg_flag & FDEFER) {
-                               fg->fg_flag &= ~FDEFER;
+                               os_atomic_andnot(&fg->fg_flag, FDEFER, relaxed);
                                unp_defer--;
                        } else {
                                /*
@@ -2137,7 +2370,8 @@ unp_gc(void)
                                 * in transit, then skip it. it's not
                                 * externally accessible.
                                 */
-                               if (fg->fg_count == fg->fg_msgcount) {
+                               if (os_ref_get_count_raw(&fg->fg_count) ==
+                                   fg->fg_msgcount) {
                                        lck_mtx_unlock(&fg->fg_lock);
                                        continue;
                                }
@@ -2145,7 +2379,7 @@ unp_gc(void)
                                 * If it got this far then it must be
                                 * externally accessible.
                                 */
-                               fg->fg_flag |= FMARK;
+                               os_atomic_or(&fg->fg_flag, FMARK, relaxed);
                        }
                        /*
                         * either it was defered, or it is externally
@@ -2158,7 +2392,7 @@ unp_gc(void)
                                continue;
                        }
                        if (so->so_proto->pr_domain != localdomain ||
-                           (so->so_proto->pr_flags&PR_RIGHTS) == 0) {
+                           (so->so_proto->pr_flags & PR_RIGHTS) == 0) {
                                lck_mtx_unlock(&fg->fg_lock);
                                continue;
                        }
@@ -2185,7 +2419,7 @@ unp_gc(void)
                         * message buffers. Follow those links and mark them
                         * as accessible too.
                         *
-                        * In case a file is passed onto itself we need to 
+                        * In case a file is passed onto itself we need to
                         * release the file lock.
                         */
                        lck_mtx_unlock(&fg->fg_lock);
@@ -2201,7 +2435,7 @@ unp_gc(void)
         * The bug in the orginal code is a little tricky, so I'll describe
         * what's wrong with it here.
         *
-        * It is incorrect to simply unp_discard each entry for f_msgcount
+        * It is incorrect to simply unp_discard each entry for fg_msgcount
         * times -- consider the case of sockets A and B that contain
         * references to each other.  On a last close of some other socket,
         * we trigger a gc since the number of outstanding rights (unp_rights)
@@ -2232,11 +2466,12 @@ unp_gc(void)
         *
         * 91/09/19, bsy@cs.cmu.edu
         */
-       extra_ref = _MALLOC(nfiles * sizeof (struct fileglob *),
-           M_FILEGLOB, M_WAITOK);
-       if (extra_ref == NULL)
+       size_t extra_ref_size = nfiles * sizeof(struct fileglob *);
+       extra_ref = kheap_alloc(KHEAP_TEMP, extra_ref_size, Z_WAITOK);
+       if (extra_ref == NULL) {
                goto bail;
-       for (nunref = 0, fg = fmsghead.lh_first, fpp = extra_ref; fg != 0;
+       }
+       for (nunref = 0, fg = unp_msghead.lh_first, fpp = extra_ref; fg != 0;
            fg = nextfg) {
                lck_mtx_lock(&fg->fg_lock);
 
@@ -2244,7 +2479,7 @@ unp_gc(void)
                /*
                 * If it's not open, skip it
                 */
-               if (fg->fg_count == 0) {
+               if (os_ref_get_count_raw(&fg->fg_count) == 0) {
                        lck_mtx_unlock(&fg->fg_lock);
                        continue;
                }
@@ -2254,8 +2489,12 @@ unp_gc(void)
                 * of (shut-down) FDs, so include it in our
                 * list of FDs to remove
                 */
-               if (fg->fg_count == fg->fg_msgcount && !(fg->fg_flag & FMARK)) {
-                       fg->fg_count++;
+               if (fg->fg_flag & FMARK) {
+                       lck_mtx_unlock(&fg->fg_lock);
+                       continue;
+               }
+               if (os_ref_get_count_raw(&fg->fg_count) == fg->fg_msgcount) {
+                       os_ref_retain_raw(&fg->fg_count, &f_refgrp);
                        *fpp++ = fg;
                        nunref++;
                }
@@ -2274,18 +2513,20 @@ unp_gc(void)
                        so = (struct socket *)(tfg->fg_data);
 
                        socket_lock(so, 0);
-                       
+
                        sorflush(so);
 
                        socket_unlock(so, 0);
                }
        }
-       for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
-               closef_locked((struct fileproc *)0, *fpp, (proc_t)NULL);
+       for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) {
+               fg_drop(PROC_NULL, *fpp);
+       }
+
+       kheap_free(KHEAP_TEMP, extra_ref, extra_ref_size);
 
-       FREE((caddr_t)extra_ref, M_FILEGLOB);
 bail:
-        lck_mtx_lock(uipc_lock);
+       lck_mtx_lock(&uipc_lock);
        unp_gcing = 0;
        unp_gcthread = NULL;
 
@@ -2293,10 +2534,11 @@ bail:
                unp_gcwait = 0;
                need_gcwakeup = 1;
        }
-       lck_mtx_unlock(uipc_lock);
+       lck_mtx_unlock(&uipc_lock);
 
-       if (need_gcwakeup != 0)
+       if (need_gcwakeup != 0) {
                wakeup(&unp_gcing);
+       }
 }
 
 void
@@ -2317,7 +2559,7 @@ unp_listen(struct unpcb *unp, proc_t p)
        cru2x(safecred, &unp->unp_peercred);
        kauth_cred_unref(&safecred);
        unp->unp_flags |= UNP_HAVEPCCACHED;
-       return (0);
+       return 0;
 }
 
 static void
@@ -2330,20 +2572,23 @@ unp_scan(struct mbuf *m0, void (*op)(struct fileglob *, void *arg), void *arg)
        int qfds;
 
        while (m0) {
-               for (m = m0; m; m = m->m_next)
+               for (m = m0; m; m = m->m_next) {
                        if (m->m_type == MT_CONTROL &&
-                           (size_t)m->m_len >= sizeof (*cm)) {
+                           (size_t)m->m_len >= sizeof(*cm)) {
                                cm = mtod(m, struct cmsghdr *);
                                if (cm->cmsg_level != SOL_SOCKET ||
-                                   cm->cmsg_type != SCM_RIGHTS)
+                                   cm->cmsg_type != SCM_RIGHTS) {
                                        continue;
-                               qfds = (cm->cmsg_len - sizeof (*cm)) /
-                                   sizeof (int);
+                               }
+                               qfds = (cm->cmsg_len - sizeof(*cm)) /
+                                   sizeof(int);
                                rp = (struct fileglob **)(cm + 1);
-                               for (i = 0; i < qfds; i++)
+                               for (i = 0; i < qfds; i++) {
                                        (*op)(*rp++, arg);
-                               break;          /* XXX, but saves time */
+                               }
+                               break;          /* XXX, but saves time */
                        }
+               }
                m0 = m0->m_act;
        }
 }
@@ -2351,15 +2596,14 @@ unp_scan(struct mbuf *m0, void (*op)(struct fileglob *, void *arg), void *arg)
 static void
 unp_mark(struct fileglob *fg, __unused void *arg)
 {
-       lck_mtx_lock(&fg->fg_lock);
+       uint32_t oflags, nflags;
 
-       if (fg->fg_flag & FMARK) {
-               lck_mtx_unlock(&fg->fg_lock);
-               return;
-       }
-       fg->fg_flag |= (FMARK|FDEFER);
-
-       lck_mtx_unlock(&fg->fg_lock);
+       os_atomic_rmw_loop(&fg->fg_flag, oflags, nflags, relaxed, {
+               if (oflags & FMARK) {
+                       os_atomic_rmw_loop_give_up(return );
+               }
+               nflags = oflags | FMARK | FDEFER;
+       });
 
        unp_defer++;
 }
@@ -2367,9 +2611,9 @@ unp_mark(struct fileglob *fg, __unused void *arg)
 static void
 unp_discard(struct fileglob *fg, void *p)
 {
-       if (p == NULL)
-               p = current_proc();             /* XXX */
-
+       if (p == NULL) {
+               p = current_proc();             /* XXX */
+       }
        (void) OSAddAtomic(1, &unp_disposed);
        if (fg_removeuipc_mark(fg)) {
                VERIFY(fg->fg_lflags & FG_RMMSGQ);
@@ -2377,72 +2621,79 @@ unp_discard(struct fileglob *fg, void *p)
        }
        (void) OSAddAtomic(-1, &unp_rights);
 
-       proc_fdlock(p);
-       (void) closef_locked((struct fileproc *)0, fg, p);
-       proc_fdunlock(p);
+       (void) fg_drop(p, fg);
 }
 
 int
 unp_lock(struct socket *so, int refcount, void * lr)
- {
-        void * lr_saved;
-        if (lr == 0)
-                lr_saved = (void *)  __builtin_return_address(0);
-        else lr_saved = lr;
-
-        if (so->so_pcb) {
-                lck_mtx_lock(&((struct unpcb *)so->so_pcb)->unp_mtx);
-        } else  {
-                panic("unp_lock: so=%p NO PCB! lr=%p ref=0x%x\n", 
-                       so, lr_saved, so->so_usecount);
-        }
-
-        if (so->so_usecount < 0)
-                panic("unp_lock: so=%p so_pcb=%p lr=%p ref=0x%x\n",
-                so, so->so_pcb, lr_saved, so->so_usecount);
-
-        if (refcount)
-                so->so_usecount++;
-
-        so->lock_lr[so->next_lock_lr] = lr_saved;
-        so->next_lock_lr = (so->next_lock_lr+1) % SO_LCKDBG_MAX;
-        return (0);
+{
+       void * lr_saved;
+       if (lr == 0) {
+               lr_saved = (void *)  __builtin_return_address(0);
+       } else {
+               lr_saved = lr;
+       }
+
+       if (so->so_pcb) {
+               lck_mtx_lock(&((struct unpcb *)so->so_pcb)->unp_mtx);
+       } else {
+               panic("unp_lock: so=%p NO PCB! lr=%p ref=0x%x\n",
+                   so, lr_saved, so->so_usecount);
+       }
+
+       if (so->so_usecount < 0) {
+               panic("unp_lock: so=%p so_pcb=%p lr=%p ref=0x%x\n",
+                   so, so->so_pcb, lr_saved, so->so_usecount);
+       }
+
+       if (refcount) {
+               VERIFY(so->so_usecount > 0);
+               so->so_usecount++;
+       }
+       so->lock_lr[so->next_lock_lr] = lr_saved;
+       so->next_lock_lr = (so->next_lock_lr + 1) % SO_LCKDBG_MAX;
+       return 0;
 }
 
 int
 unp_unlock(struct socket *so, int refcount, void * lr)
 {
-        void * lr_saved;
-        lck_mtx_t * mutex_held = NULL;
+       void * lr_saved;
+       lck_mtx_t * mutex_held = NULL;
        struct unpcb *unp = sotounpcb(so);
 
-        if (lr == 0)
-                lr_saved = (void *) __builtin_return_address(0);
-        else lr_saved = lr;
-
-        if (refcount)
-                so->so_usecount--;
-
-        if (so->so_usecount < 0)
-                panic("unp_unlock: so=%p usecount=%x\n", so, so->so_usecount);
-        if (so->so_pcb == NULL) {
-                panic("unp_unlock: so=%p NO PCB usecount=%x\n", so, so->so_usecount);
-        } else {
-                mutex_held = &((struct unpcb *)so->so_pcb)->unp_mtx;
-        }
-        lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
-        so->unlock_lr[so->next_unlock_lr] = lr_saved;
-        so->next_unlock_lr = (so->next_unlock_lr+1) % SO_LCKDBG_MAX;
-
-        if (so->so_usecount == 0 && (so->so_flags & SOF_PCBCLEARING)) {
+       if (lr == 0) {
+               lr_saved = (void *) __builtin_return_address(0);
+       } else {
+               lr_saved = lr;
+       }
+
+       if (refcount) {
+               so->so_usecount--;
+       }
+
+       if (so->so_usecount < 0) {
+               panic("unp_unlock: so=%p usecount=%x\n", so, so->so_usecount);
+       }
+       if (so->so_pcb == NULL) {
+               panic("unp_unlock: so=%p NO PCB usecount=%x\n", so, so->so_usecount);
+       } else {
+               mutex_held = &((struct unpcb *)so->so_pcb)->unp_mtx;
+       }
+       LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
+       so->unlock_lr[so->next_unlock_lr] = lr_saved;
+       so->next_unlock_lr = (so->next_unlock_lr + 1) % SO_LCKDBG_MAX;
+
+       if (so->so_usecount == 0 && (so->so_flags & SOF_PCBCLEARING)) {
                sofreelastref(so, 1);
 
-               if (unp->unp_addr)
+               if (unp->unp_addr) {
                        FREE(unp->unp_addr, M_SONAME);
-               
+               }
+
                lck_mtx_unlock(mutex_held);
 
-               lck_mtx_destroy(&unp->unp_mtx, unp_mtx_grp);
+               lck_mtx_destroy(&unp->unp_mtx, &unp_mtx_grp);
                zfree(unp_zone, unp);
 
                unp_gc();
@@ -2450,22 +2701,22 @@ unp_unlock(struct socket *so, int refcount, void * lr)
                lck_mtx_unlock(mutex_held);
        }
 
-        return (0);
+       return 0;
 }
 
 lck_mtx_t *
-unp_getlock(struct socket *so, __unused int locktype)
+unp_getlock(struct socket *so, __unused int flags)
 {
-        struct unpcb *unp = (struct unpcb *)so->so_pcb;
+       struct unpcb *unp = (struct unpcb *)so->so_pcb;
 
 
-        if (so->so_pcb)  {
-                if (so->so_usecount < 0)
-                        panic("unp_getlock: so=%p usecount=%x\n", so, so->so_usecount);
-                return(&unp->unp_mtx);
-        } else {
-                panic("unp_getlock: so=%p NULL so_pcb\n", so);
-                return (so->so_proto->pr_domain->dom_mtx);
-        }
+       if (so->so_pcb) {
+               if (so->so_usecount < 0) {
+                       panic("unp_getlock: so=%p usecount=%x\n", so, so->so_usecount);
+               }
+               return &unp->unp_mtx;
+       } else {
+               panic("unp_getlock: so=%p NULL so_pcb\n", so);
+               return so->so_proto->pr_domain->dom_mtx;
+       }
 }
-