/*
- * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <sys/fcntl.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>
#include <sys/lock.h>
#include <sys/mbuf.h>
#include <security/mac_framework.h>
#endif /* CONFIG_MACF */
+#include <mach/vm_param.h>
+
#define f_msgcount f_fglob->fg_msgcount
#define f_cred f_fglob->fg_cred
#define f_ops f_fglob->fg_ops
extern lck_mtx_t *uipc_lock;
static struct unp_head unp_shead, unp_dhead;
+/*
+ * mDNSResponder tracing. When enabled, endpoints connected to
+ * /var/run/mDNSResponder will be traced; during each send on
+ * the traced socket, we log the PID and process name of the
+ * sending process. We also print out a bit of info related
+ * to the data itself; this assumes ipc_msg_hdr in dnssd_ipc.h
+ * of mDNSResponder stays the same.
+ */
+#define MDNSRESPONDER_PATH "/var/run/mDNSResponder"
+
+static int unpst_tracemdns; /* enable tracing */
+
+#define MDNS_IPC_MSG_HDR_VERSION_1 1
+
+struct mdns_ipc_msg_hdr {
+ uint32_t version;
+ uint32_t datalen;
+ uint32_t ipc_flags;
+ uint32_t op;
+ union {
+ void *context;
+ uint32_t u32[2];
+ } __attribute__((packed));
+ uint32_t reg_index;
+} __attribute__((packed));
+
/*
* Unix communications domain.
*
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);
}
}
so2 = unp->unp_conn->unp_socket;
- unp_get_locks_in_order(so, so2);
+ if (so != so2)
+ unp_get_locks_in_order(so, so2);
if (unp->unp_addr)
from = (struct sockaddr *)unp->unp_addr;
control = NULL;
}
- socket_unlock(so2, 1);
+ if (so != so2)
+ socket_unlock(so2, 1);
m = NULL;
if (nam)
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)) {
+ printf("%s[mDNSResponder] pid=%d (%s): op=0x%x\n",
+ __func__, p->p_pid, p->p_comm, ntohl(hdr.op));
+ }
+ }
+
/*
* Send to paired receive port, and then reduce send buffer
* hiwater marks to maintain backpressure. Wake up readers.
}
struct pr_usrreqs uipc_usrreqs = {
- uipc_abort, uipc_accept, uipc_attach, uipc_bind, uipc_connect,
- uipc_connect2, pru_control_notsupp, uipc_detach, uipc_disconnect,
- uipc_listen, uipc_peeraddr, uipc_rcvd, pru_rcvoob_notsupp,
- uipc_send, uipc_sense, uipc_shutdown, uipc_sockaddr,
- sosend, soreceive, pru_sopoll_notsupp
+ .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
uipc_ctloutput(struct socket *so, struct sockopt *sopt)
{
struct unpcb *unp = sotounpcb(so);
- int error;
+ int error = 0;
+ pid_t peerpid;
+ struct socket *peerso;
switch (sopt->sopt_dir) {
case SOPT_GET:
error = EINVAL;
}
break;
+ case LOCAL_PEERPID:
+ case LOCAL_PEEREPID:
+ 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);
+ if (sopt->sopt_name == LOCAL_PEEREPID &&
+ peerso->so_flags & SOF_DELEGATED)
+ peerpid = peerso->e_pid;
+ else
+ peerpid = peerso->last_pid;
+ socket_unlock(peerso, 1);
+ error = sooptcopyout(sopt, &peerpid, sizeof (peerpid));
+ break;
+ case LOCAL_PEERUUID:
+ case LOCAL_PEEREUUID:
+ 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);
+ if (sopt->sopt_name == LOCAL_PEEREUUID &&
+ peerso->so_flags & SOF_DELEGATED)
+ error = sooptcopyout(sopt, &peerso->e_uuid,
+ sizeof (peerso->e_uuid));
+ else
+ error = sooptcopyout(sopt, &peerso->last_uuid,
+ sizeof (peerso->last_uuid));
+ socket_unlock(peerso, 1);
+ break;
default:
error = EOPNOTSUPP;
break;
error = EOPNOTSUPP;
break;
}
+
return (error);
}
static int unp_disposed; /* discarded file descriptors */
SYSCTL_DECL(_net_local_stream);
-SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW,
+SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW | CTLFLAG_LOCKED,
&unpst_sendspace, 0, "");
-SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW,
+SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW | CTLFLAG_LOCKED,
&unpst_recvspace, 0, "");
+SYSCTL_INT(_net_local_stream, OID_AUTO, tracemdns, CTLFLAG_RW | CTLFLAG_LOCKED,
+ &unpst_tracemdns, 0, "");
SYSCTL_DECL(_net_local_dgram);
-SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW,
+SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW | CTLFLAG_LOCKED,
&unpdg_sendspace, 0, "");
-SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW,
+SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW | CTLFLAG_LOCKED,
&unpdg_recvspace, 0, "");
SYSCTL_DECL(_net_local);
-SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "");
+SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD | CTLFLAG_LOCKED, &unp_rights, 0, "");
/*
* Returns: 0 Success
return (ENOBUFS);
bzero(unp, sizeof (*unp));
- unp->unp_mtx = lck_mtx_alloc_init(unp_mtx_grp, unp_mtx_attr);
- if (unp->unp_mtx == NULL) {
- zfree(unp_zone, unp);
- return(ENOBUFS);
- }
+ lck_mtx_init(&unp->unp_mtx,
+ unp_mtx_grp, unp_mtx_attr);
lck_rw_lock_exclusive(unp_list_mtx);
LIST_INIT(&unp->unp_refs);
static void
unp_detach(struct unpcb *unp)
{
+ int so_locked = 1;
+
lck_rw_lock_exclusive(unp_list_mtx);
LIST_REMOVE(unp, unp_link);
+ --unp_count;
+ ++unp_gencnt;
lck_rw_done(unp_list_mtx);
if (unp->unp_vnode) {
struct vnode *tvp = NULL;
if (unp->unp_conn)
unp_disconnect(unp);
while (unp->unp_refs.lh_first) {
- struct unpcb *unp2 = unp->unp_refs.lh_first;
- socket_unlock(unp->unp_socket, 0);
-
- socket_lock(unp2->unp_socket, 1);
- unp_drop(unp2, ECONNRESET);
- socket_unlock(unp2->unp_socket, 1);
+ 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
+ * to check disconnect_in_progress
+ */
+ if (so_locked == 1) {
+ socket_unlock(unp->unp_socket, 0);
+ so_locked = 0;
+ }
+ lck_mtx_lock(unp_disconnect_lock);
+ while (disconnect_in_progress != 0) {
+ (void)msleep((caddr_t)&disconnect_in_progress, unp_disconnect_lock,
+ PSOCK, "disconnect", NULL);
+ }
+ disconnect_in_progress = 1;
+ 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);
+ }
+
+ lck_mtx_lock(unp_disconnect_lock);
+ disconnect_in_progress = 0;
+ wakeup(&disconnect_in_progress);
+ 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);
+ }
+ }
+
+ if (so_locked == 0) {
socket_lock(unp->unp_socket, 0);
+ so_locked = 1;
}
soisdisconnected(unp->unp_socket);
/* makes sure we're getting dealloced */
socket_unlock(so, 0);
strlcpy(buf, soun->sun_path, namelen+1);
- NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_SYSSPACE,
+ 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) {
/* create the socket */
- error = vn_create(dvp, &vp, &nd.ni_cnd, &va, 0, ctx);
+ error = vn_create(dvp, &vp, &nd, &va, 0, 0, NULL, ctx);
}
nameidone(&nd);
strlcpy(buf, soun->sun_path, len+1);
socket_unlock(so, 0);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
+ NDINIT(&nd, LOOKUP, OP_LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
CAST_USER_ADDR_T(buf), ctx);
error = namei(&nd);
if (error) {
if (so2->so_pcb == NULL) {
error = ECONNREFUSED;
- socket_unlock(so2, 1);
- socket_lock(so, 0);
+ if (so != so2) {
+ socket_unlock(so2, 1);
+ socket_lock(so, 0);
+ } else {
+ /* Release the reference held for the listen socket */
+ so2->so_usecount--;
+ }
goto out;
}
socket_unlock(so2, 0);
socket_lock(so, 0);
socket_lock(so2, 0);
- } else {
+ } else if (so > so2) {
socket_lock(so, 0);
}
/*
* XXX - probably shouldn't return an error for SOCK_DGRAM
*/
if ((so->so_state & SS_ISCONNECTED) != 0) {
- socket_unlock(so2, 1);
error = EISCONN;
- goto out;
+ goto decref_out;
}
if (so->so_type != so2->so_type) {
- socket_unlock(so2, 1);
error = EPROTOTYPE;
- goto out;
+ goto decref_out;
}
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
(so3 = sonewconn(so2, 0, nam)) == 0) {
error = ECONNREFUSED;
- socket_unlock(so2, 1);
- socket_lock(so, 0);
+ if (so != so2) {
+ socket_unlock(so2, 1);
+ socket_lock(so, 0);
+ } else {
+ socket_lock(so, 0);
+ /* Release the reference held for
+ * listen socket.
+ */
+ so2->so_usecount--;
+ }
goto out;
}
unp2 = sotounpcb(so2);
socket_lock(so3, 1);
so2 = so3;
+ /*
+ * Enable tracing for mDNSResponder endpoints. (The use
+ * of sizeof instead of strlen below takes the null
+ * terminating character into account.)
+ */
+ if (unpst_tracemdns &&
+ !strncmp(soun->sun_path, MDNSRESPONDER_PATH,
+ sizeof (MDNSRESPONDER_PATH))) {
+ unp->unp_flags |= UNP_TRACE_MDNS;
+ unp2->unp_flags |= UNP_TRACE_MDNS;
+ }
}
error = unp_connect2(so, so2);
+
+decref_out:
if (so2 != NULL) {
- socket_unlock(so2, 1);
+ if (so != so2) {
+ socket_unlock(so2, 1);
+ } else {
+ /* Release the extra reference held for the listen socket.
+ * This is possible only for SOCK_DGRAM sockets. We refuse
+ * connecting to the same socket for SOCK_STREAM sockets.
+ */
+ so2->so_usecount--;
+ }
}
if (list_so != NULL) {
socket_lock(list_so, 0);
socket_unlock(list_so, 1);
}
+
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);
}
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)
switch (so->so_type) {
case SOCK_DGRAM:
- lck_rw_lock_exclusive(unp_list_mtx);
LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink);
- lck_rw_done(unp_list_mtx);
-
- /* 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
- */
- socket_unlock(so2, 0);
- soisconnected(so);
- unp_get_locks_in_order(so, so2);
- so2->so_usecount--;
+ 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
+ */
+ socket_unlock(so2, 0);
+ soisconnected(so);
+ unp_get_locks_in_order(so, so2);
+ so2->so_usecount--;
+ } else {
+ soisconnected(so);
+ }
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);
+ lck_mtx_assert(&unp->unp_mtx, LCK_MTX_ASSERT_OWNED);
+ lck_mtx_assert(&unp2->unp_mtx, LCK_MTX_ASSERT_OWNED);
return (0);
}
so2 = unp2->unp_socket;
try_again:
- if (so < so2) {
+ if (so == so2) {
+ if (so_locked == 0) {
+ socket_lock(so, 0);
+ }
+ waitso = so;
+ } else if (so < so2) {
if (so_locked == 0) {
socket_lock(so, 0);
}
socket_lock(so, 0);
waitso = so;
}
+ 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) {
- socket_unlock(so2, 1);
+ if (so != so2) {
+ socket_unlock(so2, 1);
+ }
so_locked = 0;
- (void)msleep(waitso->so_pcb, unp->unp_mtx,
+ (void)msleep(waitso->so_pcb, &unp->unp_mtx,
PSOCK | PDROP, "unpdisconnect", NULL);
goto try_again;
}
unp->unp_conn = NULL;
so2->so_usecount--;
+ if (unp->unp_flags & UNP_TRACE_MDNS)
+ unp->unp_flags &= ~UNP_TRACE_MDNS;
+
switch (unp->unp_socket->so_type) {
case SOCK_DGRAM:
- lck_rw_lock_exclusive(unp_list_mtx);
LIST_REMOVE(unp, unp_reflink);
- lck_rw_done(unp_list_mtx);
unp->unp_socket->so_state &= ~SS_ISCONNECTED;
- socket_unlock(so2, 1);
+ if (so != so2)
+ socket_unlock(so2, 1);
break;
case SOCK_STREAM:
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)
+ unp2->unp_flags &= ~UNP_TRACE_MDNS;
+
strdisconn = 1;
break;
default:
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;
}
unpcb_to_compat(struct unpcb *up, struct unpcb_compat *cp)
{
#if defined(__LP64__)
- cp->unp_link.le_next = (u_int32_t)(uintptr_t)up->unp_link.le_next;
- cp->unp_link.le_prev = (u_int32_t)(uintptr_t)up->unp_link.le_prev;
+ cp->unp_link.le_next = (u_int32_t)
+ VM_KERNEL_ADDRPERM(up->unp_link.le_next);
+ cp->unp_link.le_prev = (u_int32_t)
+ VM_KERNEL_ADDRPERM(up->unp_link.le_prev);
#else
- cp->unp_link.le_next = (struct unpcb_compat *)up->unp_link.le_next;
- cp->unp_link.le_prev = (struct unpcb_compat **)up->unp_link.le_prev;
+ cp->unp_link.le_next = (struct unpcb_compat *)
+ VM_KERNEL_ADDRPERM(up->unp_link.le_next);
+ cp->unp_link.le_prev = (struct unpcb_compat **)
+ VM_KERNEL_ADDRPERM(up->unp_link.le_prev);
#endif
- cp->unp_socket = (_UNPCB_PTR(struct socket *))(uintptr_t)up->unp_socket;
- cp->unp_vnode = (_UNPCB_PTR(struct vnode *))(uintptr_t)up->unp_vnode;
+ cp->unp_socket = (_UNPCB_PTR(struct socket *))
+ VM_KERNEL_ADDRPERM(up->unp_socket);
+ cp->unp_vnode = (_UNPCB_PTR(struct vnode *))
+ VM_KERNEL_ADDRPERM(up->unp_vnode);
cp->unp_ino = up->unp_ino;
cp->unp_conn = (_UNPCB_PTR(struct unpcb_compat *))
- (uintptr_t)up->unp_conn;
- cp->unp_refs = (u_int32_t)(uintptr_t)up->unp_refs.lh_first;
+ VM_KERNEL_ADDRPERM(up->unp_conn);
+ cp->unp_refs = (u_int32_t)VM_KERNEL_ADDRPERM(up->unp_refs.lh_first);
#if defined(__LP64__)
cp->unp_reflink.le_next =
- (u_int32_t)(uintptr_t)up->unp_reflink.le_next;
+ (u_int32_t)VM_KERNEL_ADDRPERM(up->unp_reflink.le_next);
cp->unp_reflink.le_prev =
- (u_int32_t)(uintptr_t)up->unp_reflink.le_prev;
+ (u_int32_t)VM_KERNEL_ADDRPERM(up->unp_reflink.le_prev);
#else
cp->unp_reflink.le_next =
- (struct unpcb_compat *)up->unp_reflink.le_next;
+ (struct unpcb_compat *)VM_KERNEL_ADDRPERM(up->unp_reflink.le_next);
cp->unp_reflink.le_prev =
- (struct unpcb_compat **)up->unp_reflink.le_prev;
+ (struct unpcb_compat **)VM_KERNEL_ADDRPERM(up->unp_reflink.le_prev);
#endif
cp->unp_addr = (_UNPCB_PTR(struct sockaddr_un *))
- (uintptr_t)up->unp_addr;
+ VM_KERNEL_ADDRPERM(up->unp_addr);
cp->unp_cc = up->unp_cc;
cp->unp_mbcnt = up->unp_mbcnt;
cp->unp_gencnt = up->unp_gencnt;
bzero(&xu, sizeof (xu));
xu.xu_len = sizeof (xu);
xu.xu_unpp = (_UNPCB_PTR(struct unpcb_compat *))
- (uintptr_t)unp;
+ VM_KERNEL_ADDRPERM(unp);
/*
* XXX - need more locking here to protect against
* connect/disconnect races for SMP.
return (error);
}
-SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist, CTLFLAG_RD,
+SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist, 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, CTLFLAG_RD,
+SYSCTL_PROC(_net_local_stream, OID_AUTO, pcblist, CTLFLAG_RD | CTLFLAG_LOCKED,
(caddr_t)(long)SOCK_STREAM, 0, unp_pcblist, "S,xunpcb",
"List of active local stream sockets");
-#if !CONFIG_EMBEDDED
static int
unp_pcblist64 SYSCTL_HANDLER_ARGS
bzero(&xu, xu_len);
xu.xu_len = xu_len;
- xu.xu_unpp = (u_int64_t)(uintptr_t)unp;
- xu.xunp_link.le_next =
- (u_int64_t)(uintptr_t)unp->unp_link.le_next;
- xu.xunp_link.le_prev =
- (u_int64_t)(uintptr_t)unp->unp_link.le_prev;
- xu.xunp_socket = (u_int64_t)(uintptr_t)unp->unp_socket;
- xu.xunp_vnode = (u_int64_t)(uintptr_t)unp->unp_vnode;
+ 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);
+ xu.xunp_link.le_prev = (u_int64_t)
+ VM_KERNEL_ADDRPERM(unp->unp_link.le_prev);
+ xu.xunp_socket = (u_int64_t)
+ VM_KERNEL_ADDRPERM(unp->unp_socket);
+ xu.xunp_vnode = (u_int64_t)
+ VM_KERNEL_ADDRPERM(unp->unp_vnode);
xu.xunp_ino = unp->unp_ino;
- xu.xunp_conn = (u_int64_t)(uintptr_t)unp->unp_conn;
- xu.xunp_refs = (u_int64_t)(uintptr_t)unp->unp_refs.lh_first;
- xu.xunp_reflink.le_next =
- (u_int64_t)(uintptr_t)unp->unp_reflink.le_next;
- xu.xunp_reflink.le_prev =
- (u_int64_t)(uintptr_t)unp->unp_reflink.le_prev;
+ xu.xunp_conn = (u_int64_t)
+ VM_KERNEL_ADDRPERM(unp->unp_conn);
+ xu.xunp_refs = (u_int64_t)
+ VM_KERNEL_ADDRPERM(unp->unp_refs.lh_first);
+ xu.xunp_reflink.le_next = (u_int64_t)
+ VM_KERNEL_ADDRPERM(unp->unp_reflink.le_next);
+ xu.xunp_reflink.le_prev = (u_int64_t)
+ VM_KERNEL_ADDRPERM(unp->unp_reflink.le_prev);
xu.xunp_cc = unp->unp_cc;
xu.xunp_mbcnt = unp->unp_mbcnt;
xu.xunp_gencnt = unp->unp_gencnt;
return (error);
}
-SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist64, CTLFLAG_RD,
+SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist64, 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, CTLFLAG_RD,
+SYSCTL_PROC(_net_local_stream, OID_AUTO, pcblist64, CTLFLAG_RD | CTLFLAG_LOCKED,
(caddr_t)(long)SOCK_STREAM, 0, unp_pcblist64, "S,xunpcb64",
"List of active local stream sockets 64 bit");
-#endif /* !CONFIG_EMBEDDED */
static void
unp_shutdown(struct unpcb *unp)
if (fdalloc(p, 0, &f))
panic("unp_externalize:fdalloc");
fg = rp[i];
- MALLOC_ZONE(fp, struct fileproc *, sizeof (struct fileproc),
- M_FILEPROC, M_WAITOK);
+ fp = fileproc_alloc_init(NULL);
if (fp == NULL)
panic("unp_externalize: MALLOC_ZONE");
- bzero(fp, sizeof (struct fileproc));
fp->f_iocount = 0;
fp->f_fglob = fg;
fg_removeuipc(fg);
if (((error = fdgetf_noref(p, fds[i], &tmpfp)) != 0)) {
proc_fdunlock(p);
return (error);
- } else if (!filetype_issendable(tmpfp->f_fglob->fg_type)) {
+ } else if (!filetype_issendable(FILEGLOB_DTYPE(tmpfp->f_fglob))) {
proc_fdunlock(p);
return (EINVAL);
+ } else if (FP_ISGUARDED(tmpfp, GUARD_SOCKET_IPC)) {
+ error = fp_guard_exception(p,
+ fds[i], tmpfp, kGUARD_EXC_SOCKET_IPC);
+ proc_fdunlock(p);
+ return (error);
}
}
rp = (struct fileglob **)(cm + 1);
* accessible and not already marked so.
* Now check if it is possibly one of OUR sockets.
*/
- if (fg->fg_type != DTYPE_SOCKET ||
+ if (FILEGLOB_DTYPE(fg) != DTYPE_SOCKET ||
(so = (struct socket *)fg->fg_data) == 0) {
lck_mtx_unlock(&fg->fg_lock);
continue;
}
- if (so->so_proto->pr_domain != &localdomain ||
+ if (so->so_proto->pr_domain != localdomain ||
(so->so_proto->pr_flags&PR_RIGHTS) == 0) {
lck_mtx_unlock(&fg->fg_lock);
continue;
tfg = *fpp;
- if (tfg->fg_type == DTYPE_SOCKET && tfg->fg_data != NULL) {
+ if (FILEGLOB_DTYPE(tfg) == DTYPE_SOCKET &&
+ tfg->fg_data != NULL) {
so = (struct socket *)(tfg->fg_data);
socket_lock(so, 0);
else lr_saved = lr;
if (so->so_pcb) {
- lck_mtx_lock(((struct unpcb *)so->so_pcb)->unp_mtx);
+ 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_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;
+ 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;
FREE(unp->unp_addr, M_SONAME);
lck_mtx_unlock(mutex_held);
- if (unp->unp_mtx)
- lck_mtx_free(unp->unp_mtx, unp_mtx_grp);
- unp->unp_gencnt = ++unp_gencnt;
+ lck_mtx_destroy(&unp->unp_mtx, unp_mtx_grp);
zfree(unp_zone, unp);
- --unp_count;
unp_gc();
} else {
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);
+ return(&unp->unp_mtx);
} else {
panic("unp_getlock: so=%p NULL so_pcb\n", so);
return (so->so_proto->pr_domain->dom_mtx);