]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/uipc_syscalls.c
xnu-1699.24.8.tar.gz
[apple/xnu.git] / bsd / kern / uipc_syscalls.c
index 1126e7955d59b249dfa1ffe7bc9142ac5edcd244..521de769e9c1b439b716f5215872e0668e8bb7fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -86,8 +86,9 @@
 #include <sys/kernel.h>
 #include <sys/uio_internal.h>
 #include <sys/kauth.h>
+#include <kern/task.h>
 
-#include <bsm/audit_kernel.h>
+#include <security/audit/audit.h>
 
 #include <sys/kdebug.h>
 #include <sys/sysproto.h>
@@ -133,13 +134,13 @@ static pid_t last_pid_4056224 = 0;
 int falloc_locked(proc_t, struct fileproc **, int *, vfs_context_t, int);
 
 static int sendit(struct proc *, int, struct user_msghdr *, uio_t, int,
-    register_t *);
+    int32_t *);
 static int recvit(struct proc *, int, struct user_msghdr *, uio_t, user_addr_t,
-    register_t *);
+    int32_t *);
 static int getsockaddr(struct socket *, struct sockaddr **, user_addr_t,
-    size_t);
+    size_t, boolean_t);
 static int getsockaddr_s(struct socket *, struct sockaddr_storage *,
-    user_addr_t, size_t);
+    user_addr_t, size_t, boolean_t);
 #if SENDFILE
 static void alloc_sendpkt(int, size_t, unsigned int *, struct mbuf **,
     boolean_t);
@@ -166,7 +167,7 @@ extern      struct fileops socketops;
  *     socreate:???                    [other protocol families, IPSEC]
  */
 int
-socket(struct proc *p, struct socket_args *uap, register_t *retval)
+socket(struct proc *p, struct socket_args *uap, int32_t *retval)
 {
        struct socket *so;
        struct fileproc *fp;
@@ -198,7 +199,12 @@ socket(struct proc *p, struct socket_args *uap, register_t *retval)
                ut = get_bsdthread_info(thread);
                        
                /* if this is a backgrounded thread then throttle all new sockets */
-               if ( (ut->uu_flag & UT_BACKGROUND) != 0 ) {
+#if !CONFIG_EMBEDDED
+               if (proc_get_selfthread_isbackground() != 0)
+#else /* !CONFIG_EMBEDDED */
+               if ( (ut->uu_flag & UT_BACKGROUND) != 0 ) 
+#endif /* !CONFIG_EMBEDDED */
+               {
                        so->so_traffic_mgt_flags |= TRAFFIC_MGT_SO_BACKGROUND;
                        so->so_background_thread = thread;
                }
@@ -230,7 +236,7 @@ socket(struct proc *p, struct socket_args *uap, register_t *retval)
  */
 /* ARGSUSED */
 int
-bind(__unused proc_t p, struct bind_args *uap, __unused register_t *retval)
+bind(__unused proc_t p, struct bind_args *uap, __unused int32_t *retval)
 {
        struct sockaddr_storage ss;
        struct sockaddr *sa = NULL;
@@ -251,9 +257,9 @@ bind(__unused proc_t p, struct bind_args *uap, __unused register_t *retval)
                goto out;
        }
        if (uap->namelen > sizeof (ss)) {
-               error = getsockaddr(so, &sa, uap->name, uap->namelen);
+               error = getsockaddr(so, &sa, uap->name, uap->namelen, TRUE);
        } else {
-               error = getsockaddr_s(so, &ss, uap->name, uap->namelen);
+               error = getsockaddr_s(so, &ss, uap->name, uap->namelen, TRUE);
                if (error == 0) {
                        sa = (struct sockaddr *)&ss;
                        want_free = FALSE;
@@ -287,7 +293,7 @@ out:
  */
 int
 listen(__unused struct proc *p, struct listen_args *uap,
-    __unused register_t *retval)
+    __unused int32_t *retval)
 {
        int error;
        struct socket *so;
@@ -332,7 +338,7 @@ listen(__unused struct proc *p, struct listen_args *uap,
  */
 int
 accept_nocancel(struct proc *p, struct accept_nocancel_args *uap,
-    register_t *retval)
+    int32_t *retval)
 {
        struct fileproc *fp;
        struct sockaddr *sa = NULL;
@@ -498,8 +504,6 @@ accept_nocancel(struct proc *p, struct accept_nocancel_args *uap,
                namelen = 0;
                if (uap->name)
                        goto gotnoname;
-               if (dosocklock)
-                       socket_unlock(so, 1);
                error = 0;
                goto releasefd;
        }
@@ -521,23 +525,19 @@ gotnoname:
        }
        FREE(sa, M_SONAME);
 
+releasefd:
        /*
-        * If the socket has been marked as inactive by soacceptfilter(),
-        * disallow further operations on it.  We explicitly call shutdown
-        * on both data directions to ensure that SS_CANT{RCV,SEND}MORE
-        * states are set for the socket.  This would also flush out data
-        * hanging off the receive list of this socket.
+        * If the socket has been marked as inactive by sosetdefunct(),
+        * disallow further operations on it.
         */
        if (so->so_flags & SOF_DEFUNCT) {
-               (void) soshutdownlock(so, SHUT_RD);
-               (void) soshutdownlock(so, SHUT_WR);
-               (void) sodisconnectlocked(so);
+               sodefunct(current_proc(), so,
+                   SHUTDOWN_SOCKET_LEVEL_DISCONNECT_INTERNAL);
        }
 
        if (dosocklock)
                socket_unlock(so, 1);
 
-releasefd:
        proc_fdlock(p);
        procfdtbl_releasefd(p, newfd, NULL);
        fp_drop(p, newfd, fp, 1);
@@ -549,7 +549,7 @@ out:
 }
 
 int
-accept(struct proc *p, struct accept_args *uap, register_t *retval)
+accept(struct proc *p, struct accept_args *uap, int32_t *retval)
 {
        __pthread_testcancel(1);
        return(accept_nocancel(p, (struct accept_nocancel_args *)uap, retval));
@@ -579,14 +579,14 @@ accept(struct proc *p, struct accept_args *uap, register_t *retval)
  */
 /* ARGSUSED */
 int
-connect(struct proc *p, struct connect_args *uap, register_t *retval)
+connect(struct proc *p, struct connect_args *uap, int32_t *retval)
 {
        __pthread_testcancel(1);
        return(connect_nocancel(p, (struct connect_nocancel_args *)uap, retval));
 }
 
 int
-connect_nocancel(__unused proc_t p, struct connect_nocancel_args *uap, __unused register_t *retval)
+connect_nocancel(__unused proc_t p, struct connect_nocancel_args *uap, __unused int32_t *retval)
 {
        struct socket *so;
        struct sockaddr_storage ss;
@@ -595,6 +595,7 @@ connect_nocancel(__unused proc_t p, struct connect_nocancel_args *uap, __unused
        boolean_t want_free = TRUE;
        int error;
        int fd = uap->s;
+       boolean_t dgram;
 
        AUDIT_ARG(fd, uap->s);
        error = file_socket(fd, &so);
@@ -605,11 +606,17 @@ connect_nocancel(__unused proc_t p, struct connect_nocancel_args *uap, __unused
                goto out;
        }
 
+       /*
+        * Ask getsockaddr{_s} to not translate AF_UNSPEC to AF_INET
+        * if this is a datagram socket; translate for other types.
+        */
+       dgram = (so->so_type == SOCK_DGRAM);
+
        /* Get socket address now before we obtain socket lock */
        if (uap->namelen > sizeof (ss)) {
-               error = getsockaddr(so, &sa, uap->name, uap->namelen);
+               error = getsockaddr(so, &sa, uap->name, uap->namelen, !dgram);
        } else {
-               error = getsockaddr_s(so, &ss, uap->name, uap->namelen);
+               error = getsockaddr_s(so, &ss, uap->name, uap->namelen, !dgram);
                if (error == 0) {
                        sa = (struct sockaddr *)&ss;
                        want_free = FALSE;
@@ -693,7 +700,7 @@ out:
  */
 int
 socketpair(struct proc *p, struct socketpair_args *uap,
-    __unused register_t *retval)
+    __unused int32_t *retval)
 {
        struct fileproc *fp1, *fp2;
        struct socket *so1, *so2;
@@ -741,6 +748,9 @@ socketpair(struct proc *p, struct socketpair_args *uap,
                }
        }
 
+       if ((error = copyout(sv, uap->rsv, 2 * sizeof (int))) != 0)
+               goto free4;
+
        proc_fdlock(p);
        procfdtbl_releasefd(p, sv[0], NULL);
        procfdtbl_releasefd(p, sv[1], NULL);
@@ -748,8 +758,7 @@ socketpair(struct proc *p, struct socketpair_args *uap,
        fp_drop(p, sv[1], fp2, 1);
        proc_fdunlock(p);
 
-       error = copyout((caddr_t)sv, uap->rsv, 2 * sizeof (int));
-       return (error);
+       return (0);
 free4:
        fp_free(p, sv[1], fp2);
 free3:
@@ -803,7 +812,7 @@ free1:
  */
 static int
 sendit(struct proc *p, int s, struct user_msghdr *mp, uio_t uiop,
-    int flags, register_t *retval)
+    int flags, int32_t *retval)
 {
        struct mbuf *control = NULL;
        struct sockaddr_storage ss;
@@ -827,10 +836,10 @@ sendit(struct proc *p, int s, struct user_msghdr *mp, uio_t uiop,
        if (mp->msg_name != USER_ADDR_NULL) {
                if (mp->msg_namelen > sizeof (ss)) {
                        error = getsockaddr(so, &to, mp->msg_name,
-                           mp->msg_namelen);
+                           mp->msg_namelen, TRUE);
                } else {
                        error = getsockaddr_s(so, &ss, mp->msg_name,
-                           mp->msg_namelen);
+                           mp->msg_namelen, TRUE);
                        if (error == 0) {
                                to = (struct sockaddr *)&ss;
                                want_free = FALSE;
@@ -891,14 +900,14 @@ out:
  *     write:???                       [4056224: applicable for pipes]
  */
 int
-sendto(struct proc *p, struct sendto_args *uap, register_t *retval)
+sendto(struct proc *p, struct sendto_args *uap, int32_t *retval)
 {
        __pthread_testcancel(1);
        return(sendto_nocancel(p, (struct sendto_nocancel_args *)uap, retval));
 }
 
 int
-sendto_nocancel(struct proc *p, struct sendto_nocancel_args *uap, register_t *retval)
+sendto_nocancel(struct proc *p, struct sendto_nocancel_args *uap, int32_t *retval)
 {
        struct user_msghdr msg;
        int error;
@@ -977,34 +986,32 @@ sendto_nocancel(struct proc *p, struct sendto_nocancel_args *uap, register_t *re
  *     sendit:???                      [see sendit definition in this file]
  */
 int
-sendmsg(struct proc *p, struct sendmsg_args *uap, register_t *retval)
+sendmsg(struct proc *p, struct sendmsg_args *uap, int32_t *retval)
 {
        __pthread_testcancel(1);
        return(sendmsg_nocancel(p, (struct sendmsg_nocancel_args *)uap, retval));
 }
 
 int
-sendmsg_nocancel(struct proc *p, struct sendmsg_nocancel_args *uap, register_t *retval)
+sendmsg_nocancel(struct proc *p, struct sendmsg_nocancel_args *uap, int32_t *retval)
 {
-       struct msghdr msg;
+       struct user32_msghdr msg32;
+       struct user64_msghdr msg64;
        struct user_msghdr user_msg;
        caddr_t msghdrp;
        int     size_of_msghdr;
        int error;
-       int size_of_iovec;
        uio_t auio = NULL;
        struct user_iovec *iovp;
 
        KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_START, 0, 0, 0, 0, 0);
        AUDIT_ARG(fd, uap->s);
        if (IS_64BIT_PROCESS(p)) {
-               msghdrp = (caddr_t)&user_msg;
-               size_of_msghdr = sizeof (user_msg);
-               size_of_iovec = sizeof (struct user_iovec);
+               msghdrp = (caddr_t)&msg64;
+               size_of_msghdr = sizeof (msg64);
        } else {
-               msghdrp = (caddr_t)&msg;
-               size_of_msghdr = sizeof (msg);
-               size_of_iovec = sizeof (struct iovec);
+               msghdrp = (caddr_t)&msg32;
+               size_of_msghdr = sizeof (msg32);
        }
        error = copyin(uap->msg, msghdrp, size_of_msghdr);
        if (error) {
@@ -1012,15 +1019,22 @@ sendmsg_nocancel(struct proc *p, struct sendmsg_nocancel_args *uap, register_t *
                return (error);
        }
 
-       /* only need to copy if user process is not 64-bit */
-       if (!IS_64BIT_PROCESS(p)) {
-               user_msg.msg_flags = msg.msg_flags;
-               user_msg.msg_controllen = msg.msg_controllen;
-               user_msg.msg_control = CAST_USER_ADDR_T(msg.msg_control);
-               user_msg.msg_iovlen = msg.msg_iovlen;
-               user_msg.msg_iov = CAST_USER_ADDR_T(msg.msg_iov);
-               user_msg.msg_namelen = msg.msg_namelen;
-               user_msg.msg_name = CAST_USER_ADDR_T(msg.msg_name);
+       if (IS_64BIT_PROCESS(p)) {
+               user_msg.msg_flags = msg64.msg_flags;
+               user_msg.msg_controllen = msg64.msg_controllen;
+               user_msg.msg_control = msg64.msg_control;
+               user_msg.msg_iovlen = msg64.msg_iovlen;
+               user_msg.msg_iov = msg64.msg_iov;
+               user_msg.msg_namelen = msg64.msg_namelen;
+               user_msg.msg_name = msg64.msg_name;
+       } else {
+               user_msg.msg_flags = msg32.msg_flags;
+               user_msg.msg_controllen = msg32.msg_controllen;
+               user_msg.msg_control = msg32.msg_control;
+               user_msg.msg_iovlen = msg32.msg_iovlen;
+               user_msg.msg_iov = msg32.msg_iov;
+               user_msg.msg_namelen = msg32.msg_namelen;
+               user_msg.msg_name = msg32.msg_name;
        }
 
        if (user_msg.msg_iovlen <= 0 || user_msg.msg_iovlen > UIO_MAXIOV) {
@@ -1048,8 +1062,9 @@ sendmsg_nocancel(struct proc *p, struct sendmsg_nocancel_args *uap, register_t *
                        error = ENOBUFS;
                        goto done;
                }
-               error = copyin(user_msg.msg_iov, (caddr_t)iovp,
-                   (user_msg.msg_iovlen * size_of_iovec));
+               error = copyin_user_iovec_array(user_msg.msg_iov,
+                       IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32,
+                       user_msg.msg_iovlen, iovp);
                if (error)
                        goto done;
                user_msg.msg_iov = CAST_USER_ADDR_T(iovp);
@@ -1097,7 +1112,7 @@ done:
  */
 static int
 recvit(struct proc *p, int s, struct user_msghdr *mp, uio_t uiop,
-    user_addr_t namelenp, register_t *retval)
+    user_addr_t namelenp, int32_t *retval)
 {
        int len, error;
        struct mbuf *m, *control = 0;
@@ -1148,7 +1163,9 @@ recvit(struct proc *p, int s, struct user_msghdr *mp, uio_t uiop,
        error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, uiop,
            (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
            &mp->msg_flags);
-       AUDIT_ARG(sockaddr, vfs_context_cwd(vfs_context_current()), fromsa);
+       if (fromsa)
+               AUDIT_ARG(sockaddr, vfs_context_cwd(vfs_context_current()),
+                   fromsa);
        if (error) {
                if (uio_resid(uiop) != len && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
@@ -1191,21 +1208,80 @@ recvit(struct proc *p, int s, struct user_msghdr *mp, uio_t uiop,
 
                while (m && len > 0) {
                        unsigned int tocopy;
-
-                       if (len >= m->m_len) {
-                               tocopy = m->m_len;
-                       } else {
-                               mp->msg_flags |= MSG_CTRUNC;
-                               tocopy = len;
+                       struct cmsghdr *cp = mtod(m, struct cmsghdr *);
+                       int cp_size = CMSG_ALIGN(cp->cmsg_len);
+                       int buflen = m->m_len;
+                       
+                       while (buflen > 0 && len > 0) {
+                               
+                               /* 
+                                SCM_TIMESTAMP hack because  struct timeval has a 
+                                * different size for 32 bits and 64 bits processes
+                                */
+                               if (cp->cmsg_level == SOL_SOCKET &&  cp->cmsg_type == SCM_TIMESTAMP) {
+                                       unsigned char tmp_buffer[CMSG_SPACE(sizeof(struct user64_timeval))];
+                                       struct cmsghdr *tmp_cp = (struct cmsghdr *)tmp_buffer;
+                                       int tmp_space;
+                                       struct timeval *tv = (struct timeval *)CMSG_DATA(cp);
+                                       
+                                       tmp_cp->cmsg_level = SOL_SOCKET;
+                                       tmp_cp->cmsg_type = SCM_TIMESTAMP;
+                                       
+                                       if (proc_is64bit(p)) {
+                                               struct user64_timeval *tv64 = (struct user64_timeval *)CMSG_DATA(tmp_cp);
+                                               
+                                               tv64->tv_sec = tv->tv_sec;
+                                               tv64->tv_usec = tv->tv_usec;
+                                               
+                                               tmp_cp->cmsg_len = CMSG_LEN(sizeof(struct user64_timeval));
+                                               tmp_space = CMSG_SPACE(sizeof(struct user64_timeval));
+                                       } else {
+                                               struct user32_timeval *tv32 = (struct user32_timeval *)CMSG_DATA(tmp_cp);
+                                               
+                                               tv32->tv_sec = tv->tv_sec;
+                                               tv32->tv_usec = tv->tv_usec;
+                                               
+                                               tmp_cp->cmsg_len = CMSG_LEN(sizeof(struct user32_timeval));
+                                               tmp_space = CMSG_SPACE(sizeof(struct user32_timeval));
+                                       }
+                                       if (len >= tmp_space) {
+                                               tocopy = tmp_space;
+                                       } else {
+                                               mp->msg_flags |= MSG_CTRUNC;
+                                               tocopy = len;
+                                       }
+                                       error = copyout(tmp_buffer, ctlbuf, tocopy);
+                                       if (error)
+                                               goto out;
+                                       
+                               } else {
+                                       
+                                       if (cp_size > buflen) {
+                                               panic("cp_size > buflen, something wrong with alignment!");
+                                       }
+                                       
+                                       if (len >= cp_size) {
+                                               tocopy = cp_size;
+                                       } else {
+                                               mp->msg_flags |= MSG_CTRUNC;
+                                               tocopy = len;
+                                       }
+                                       
+                                       error = copyout((caddr_t) cp, ctlbuf,
+                                                                       tocopy);
+                                       if (error)
+                                               goto out;
+                               }
+                               
+                               
+                               ctlbuf += tocopy;
+                               len -= tocopy;
+                               
+                               buflen -= cp_size;
+                               cp = (struct cmsghdr *) ((unsigned char *) cp + cp_size);
+                               cp_size = CMSG_ALIGN(cp->cmsg_len);
                        }
-
-                       error = copyout((caddr_t)mtod(m, caddr_t), ctlbuf,
-                           tocopy);
-                       if (error)
-                               goto out;
-
-                       ctlbuf += tocopy;
-                       len -= tocopy;
+                       
                        m = m->m_next;
                }
                mp->msg_controllen = ctlbuf - mp->msg_control;
@@ -1221,7 +1297,6 @@ out1:
        return (error);
 }
 
-
 /*
  * Returns:    0                       Success
  *             ENOMEM
@@ -1238,14 +1313,14 @@ out1:
  *             the block header for the recvit function.
  */
 int
-recvfrom(struct proc *p, struct recvfrom_args *uap, register_t *retval)
+recvfrom(struct proc *p, struct recvfrom_args *uap, int32_t *retval)
 {
        __pthread_testcancel(1);
        return(recvfrom_nocancel(p, (struct recvfrom_nocancel_args *)uap, retval));
 }
 
 int
-recvfrom_nocancel(struct proc *p, struct recvfrom_nocancel_args *uap, register_t *retval)
+recvfrom_nocancel(struct proc *p, struct recvfrom_nocancel_args *uap, int32_t *retval)
 {
        struct user_msghdr msg;
        int error;
@@ -1335,35 +1410,33 @@ recvfrom_nocancel(struct proc *p, struct recvfrom_nocancel_args *uap, register_t
  *             the block header for the recvit function.
  */
 int
-recvmsg(struct proc *p, struct recvmsg_args *uap, register_t *retval)
+recvmsg(struct proc *p, struct recvmsg_args *uap, int32_t *retval)
 {
        __pthread_testcancel(1);
        return(recvmsg_nocancel(p, (struct recvmsg_nocancel_args *)uap, retval));
 }
 
 int
-recvmsg_nocancel(struct proc *p, struct recvmsg_nocancel_args *uap, register_t *retval)
+recvmsg_nocancel(struct proc *p, struct recvmsg_nocancel_args *uap, int32_t *retval)
 {
-       struct msghdr msg;
+       struct user32_msghdr msg32;
+       struct user64_msghdr msg64;
        struct user_msghdr user_msg;
        caddr_t msghdrp;
        int     size_of_msghdr;
        user_addr_t uiov;
        int error;
-       int size_of_iovec;
        uio_t auio = NULL;
        struct user_iovec *iovp;
 
        KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_START, 0, 0, 0, 0, 0);
        AUDIT_ARG(fd, uap->s);
        if (IS_64BIT_PROCESS(p)) {
-               msghdrp = (caddr_t)&user_msg;
-               size_of_msghdr = sizeof (user_msg);
-               size_of_iovec = sizeof (struct user_iovec);
+               msghdrp = (caddr_t)&msg64;
+               size_of_msghdr = sizeof (msg64);
        } else {
-               msghdrp = (caddr_t)&msg;
-               size_of_msghdr = sizeof (msg);
-               size_of_iovec = sizeof (struct iovec);
+               msghdrp = (caddr_t)&msg32;
+               size_of_msghdr = sizeof (msg32);
        }
        error = copyin(uap->msg, msghdrp, size_of_msghdr);
        if (error) {
@@ -1372,14 +1445,22 @@ recvmsg_nocancel(struct proc *p, struct recvmsg_nocancel_args *uap, register_t *
        }
 
        /* only need to copy if user process is not 64-bit */
-       if (!IS_64BIT_PROCESS(p)) {
-               user_msg.msg_flags = msg.msg_flags;
-               user_msg.msg_controllen = msg.msg_controllen;
-               user_msg.msg_control = CAST_USER_ADDR_T(msg.msg_control);
-               user_msg.msg_iovlen = msg.msg_iovlen;
-               user_msg.msg_iov = CAST_USER_ADDR_T(msg.msg_iov);
-               user_msg.msg_namelen = msg.msg_namelen;
-               user_msg.msg_name = CAST_USER_ADDR_T(msg.msg_name);
+       if (IS_64BIT_PROCESS(p)) {
+               user_msg.msg_flags = msg64.msg_flags;
+               user_msg.msg_controllen = msg64.msg_controllen;
+               user_msg.msg_control = msg64.msg_control;
+               user_msg.msg_iovlen = msg64.msg_iovlen;
+               user_msg.msg_iov = msg64.msg_iov;
+               user_msg.msg_namelen = msg64.msg_namelen;
+               user_msg.msg_name = msg64.msg_name;
+       } else {
+               user_msg.msg_flags = msg32.msg_flags;
+               user_msg.msg_controllen = msg32.msg_controllen;
+               user_msg.msg_control = msg32.msg_control;
+               user_msg.msg_iovlen = msg32.msg_iovlen;
+               user_msg.msg_iov = msg32.msg_iov;
+               user_msg.msg_namelen = msg32.msg_namelen;
+               user_msg.msg_name = msg32.msg_name;
        }
 
        if (user_msg.msg_iovlen <= 0 || user_msg.msg_iovlen > UIO_MAXIOV) {
@@ -1410,8 +1491,9 @@ recvmsg_nocancel(struct proc *p, struct recvmsg_nocancel_args *uap, register_t *
        }
        uiov = user_msg.msg_iov;
        user_msg.msg_iov = CAST_USER_ADDR_T(iovp);
-       error = copyin(uiov, (caddr_t)iovp,
-           (user_msg.msg_iovlen * size_of_iovec));
+       error = copyin_user_iovec_array(uiov,
+               IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32,
+               user_msg.msg_iovlen, iovp);
        if (error)
                goto done;
 
@@ -1421,18 +1503,22 @@ recvmsg_nocancel(struct proc *p, struct recvmsg_nocancel_args *uap, register_t *
        error = recvit(p, uap->s, &user_msg, auio, 0, retval);
        if (!error) {
                user_msg.msg_iov = uiov;
-               /* only need to copy if user process is not 64-bit */
-               if (!IS_64BIT_PROCESS(p)) {
-                       // LP64todo - do all these change?  if not, then no need to copy all of them!
-                       msg.msg_flags = user_msg.msg_flags;
-                       msg.msg_controllen = user_msg.msg_controllen;
-                       msg.msg_control =
-                           CAST_DOWN(caddr_t, user_msg.msg_control);
-                       msg.msg_iovlen = user_msg.msg_iovlen;
-                       msg.msg_iov = (struct iovec *)
-                           CAST_DOWN(caddr_t, user_msg.msg_iov);
-                       msg.msg_namelen = user_msg.msg_namelen;
-                       msg.msg_name = CAST_DOWN(caddr_t, user_msg.msg_name);
+               if (IS_64BIT_PROCESS(p)) {
+                       msg64.msg_flags = user_msg.msg_flags;
+                       msg64.msg_controllen = user_msg.msg_controllen;
+                       msg64.msg_control = user_msg.msg_control;
+                       msg64.msg_iovlen = user_msg.msg_iovlen;
+                       msg64.msg_iov = user_msg.msg_iov;
+                       msg64.msg_namelen = user_msg.msg_namelen;
+                       msg64.msg_name = user_msg.msg_name;
+               } else {
+                       msg32.msg_flags = user_msg.msg_flags;
+                       msg32.msg_controllen = user_msg.msg_controllen;
+                       msg32.msg_control = user_msg.msg_control;
+                       msg32.msg_iovlen = user_msg.msg_iovlen;
+                       msg32.msg_iov = user_msg.msg_iov;
+                       msg32.msg_namelen = user_msg.msg_namelen;
+                       msg32.msg_name = user_msg.msg_name;
                }
                error = copyout(msghdrp, uap->msg, size_of_msghdr);
        }
@@ -1467,7 +1553,7 @@ done:
 /* ARGSUSED */
 int
 shutdown(__unused struct proc *p, struct shutdown_args *uap,
-    __unused register_t *retval)
+    __unused int32_t *retval)
 {
        struct socket *so;
        int error;
@@ -1504,7 +1590,7 @@ out:
 /* ARGSUSED */
 int
 setsockopt(struct proc *p, struct setsockopt_args *uap,
-    __unused register_t *retval)
+    __unused int32_t *retval)
 {
        struct socket *so;
        struct sockopt sopt;
@@ -1556,7 +1642,7 @@ out:
  */
 int
 getsockopt(struct proc *p, struct getsockopt_args  *uap,
-    __unused register_t *retval)
+    __unused int32_t *retval)
 {
        int             error;
        socklen_t       valsize;
@@ -1620,7 +1706,7 @@ out:
 /* ARGSUSED */
 int
 getsockname(__unused struct proc *p, struct getsockname_args *uap,
-    __unused register_t *retval)
+    __unused int32_t *retval)
 {
        struct socket *so;
        struct sockaddr *sa;
@@ -1642,28 +1728,9 @@ getsockname(__unused struct proc *p, struct getsockname_args *uap,
        socket_lock(so, 1);
        error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
        if (error == 0) {
-               struct socket_filter_entry *filter;
-               int     filtered = 0;
-               for (filter = so->so_filt; filter && error == 0;
-                   filter = filter->sfe_next_onsocket) {
-                       if (filter->sfe_filter->sf_filter.sf_getsockname) {
-                               if (!filtered) {
-                                       filtered = 1;
-                                       sflt_use(so);
-                                       socket_unlock(so, 0);
-                               }
-                               error = filter->sfe_filter->sf_filter.
-                                   sf_getsockname(filter->sfe_cookie, so, &sa);
-                       }
-               }
-
+               error = sflt_getsockname(so, &sa);
                if (error == EJUSTRETURN)
                        error = 0;
-
-               if (filtered) {
-                       socket_lock(so, 0);
-                       sflt_unuse(so);
-               }
        }
        socket_unlock(so, 1);
        if (error)
@@ -1707,7 +1774,7 @@ out:
 /* ARGSUSED */
 int
 getpeername(__unused struct proc *p, struct getpeername_args *uap,
-    __unused register_t *retval)
+    __unused int32_t *retval)
 {
        struct socket *so;
        struct sockaddr *sa;
@@ -1746,28 +1813,9 @@ getpeername(__unused struct proc *p, struct getpeername_args *uap,
        sa = 0;
        error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
        if (error == 0) {
-               struct socket_filter_entry *filter;
-               int     filtered = 0;
-               for (filter = so->so_filt; filter && error == 0;
-                   filter = filter->sfe_next_onsocket) {
-                       if (filter->sfe_filter->sf_filter.sf_getpeername) {
-                               if (!filtered) {
-                                       filtered = 1;
-                                       sflt_use(so);
-                                       socket_unlock(so, 0);
-                               }
-                               error = filter->sfe_filter->sf_filter.
-                                   sf_getpeername(filter->sfe_cookie, so, &sa);
-                       }
-               }
-
+               error = sflt_getpeername(so, &sa);
                if (error == EJUSTRETURN)
                        error = 0;
-
-               if (filtered) {
-                       socket_lock(so, 0);
-                       sflt_unuse(so);
-               }
        }
        socket_unlock(so, 1);
        if (error)
@@ -1799,22 +1847,31 @@ sockargs(struct mbuf **mp, user_addr_t data, int buflen, int type)
        struct mbuf *m;
        int error;
 
-       if ((u_int)buflen > MLEN) {
-               if (type == MT_SONAME && (u_int)buflen <= 112)
-                       buflen = MLEN;          /* unix domain compat. hack */
-               else if ((u_int)buflen > MCLBYTES)
+       int alloc_buflen = buflen;
+#ifdef __LP64__
+       /* The fd's in the buffer must expand to be pointers, thus we need twice as much space */
+       if(type == MT_CONTROL)
+               alloc_buflen = ((buflen - sizeof(struct cmsghdr))*2) + sizeof(struct cmsghdr);
+#endif
+       if ((u_int)alloc_buflen > MLEN) {
+               if (type == MT_SONAME && (u_int)alloc_buflen <= 112)
+                       alloc_buflen = MLEN;            /* unix domain compat. hack */
+               else if ((u_int)alloc_buflen > MCLBYTES)
                        return (EINVAL);
        }
        m = m_get(M_WAIT, type);
        if (m == NULL)
                return (ENOBUFS);
-       if ((u_int)buflen > MLEN) {
+       if ((u_int)alloc_buflen > MLEN) {
                MCLGET(m, M_WAIT);
                if ((m->m_flags & M_EXT) == 0) {
                        m_free(m);
                        return (ENOBUFS);
                }
        }
+       /* K64: We still copyin the original buflen because it gets expanded later
+        * and we lie about the size of the mbuf because it only affects unp_* functions
+        */
        m->m_len = buflen;
        error = copyin(data, mtod(m, caddr_t), (u_int)buflen);
        if (error) {
@@ -1840,7 +1897,7 @@ sockargs(struct mbuf **mp, user_addr_t data, int buflen, int type)
  */
 static int
 getsockaddr(struct socket *so, struct sockaddr **namp, user_addr_t uaddr,
-    size_t len)
+    size_t len, boolean_t translate_unspec)
 {
        struct sockaddr *sa;
        int error;
@@ -1865,7 +1922,7 @@ getsockaddr(struct socket *so, struct sockaddr **namp, user_addr_t uaddr,
                 * sockets we leave it unchanged and let the lower layer
                 * handle it.
                 */
-               if (sa->sa_family == AF_UNSPEC &&
+               if (translate_unspec && sa->sa_family == AF_UNSPEC &&
                    INP_CHECK_SOCKAF(so, AF_INET) &&
                    len == sizeof (struct sockaddr_in))
                        sa->sa_family = AF_INET;
@@ -1878,7 +1935,7 @@ getsockaddr(struct socket *so, struct sockaddr **namp, user_addr_t uaddr,
 
 static int
 getsockaddr_s(struct socket *so, struct sockaddr_storage *ss,
-    user_addr_t uaddr, size_t len)
+    user_addr_t uaddr, size_t len, boolean_t translate_unspec)
 {
        int error;
 
@@ -1902,7 +1959,7 @@ getsockaddr_s(struct socket *so, struct sockaddr_storage *ss,
                 * sockets we leave it unchanged and let the lower layer
                 * handle it.
                 */
-               if (ss->ss_family == AF_UNSPEC &&
+               if (translate_unspec && ss->ss_family == AF_UNSPEC &&
                    INP_CHECK_SOCKAF(so, AF_INET) &&
                    len == sizeof (struct sockaddr_in))
                        ss->ss_family = AF_INET;
@@ -1918,7 +1975,7 @@ SYSCTL_DECL(_kern_ipc);
 
 #define        SFUIOBUFS 64
 static int sendfileuiobufs = SFUIOBUFS;
-SYSCTL_INT(_kern_ipc, OID_AUTO, sendfileuiobufs, CTLFLAG_RW, &sendfileuiobufs,
+SYSCTL_INT(_kern_ipc, OID_AUTO, sendfileuiobufs, CTLFLAG_RW | CTLFLAG_LOCKED, &sendfileuiobufs,
     0, "");
 
 /* Macros to compute the number of mbufs needed depending on cluster size */
@@ -1961,13 +2018,13 @@ alloc_sendpkt(int how, size_t pktlen, unsigned int *maxchunks,
         * use mbuf_allocpacket().  The logic below is similar to sosend().
         */
        *m = NULL;
-       if (pktlen > NBPG && jumbocl) {
+       if (pktlen > MBIGCLBYTES && jumbocl) {
                needed = MIN(SENDFILE_MAX_16K, HOWMANY_16K(pktlen));
                *m = m_getpackets_internal(&needed, 1, how, 0, M16KCLBYTES);
        }
        if (*m == NULL) {
                needed = MIN(SENDFILE_MAX_4K, HOWMANY_4K(pktlen));
-               *m = m_getpackets_internal(&needed, 1, how, 0, NBPG);
+               *m = m_getpackets_internal(&needed, 1, how, 0, MBIGCLBYTES);
        }
 
        /*
@@ -1978,7 +2035,7 @@ alloc_sendpkt(int how, size_t pktlen, unsigned int *maxchunks,
         */
        if (*m == NULL) {
                needed = 1;
-               *m = m_getpackets_internal(&needed, 1, M_WAIT, 1, NBPG);
+               *m = m_getpackets_internal(&needed, 1, M_WAIT, 1, MBIGCLBYTES);
        }
        if (*m == NULL)
                panic("%s: blocking allocation returned NULL\n", __func__);
@@ -2004,18 +2061,22 @@ sendfile(struct proc *p, struct sendfile_args *uap, __unused int *retval)
        struct socket *so;
        struct writev_nocancel_args nuap;
        user_ssize_t writev_retval;
-       struct sf_hdtr hdtr;
        struct user_sf_hdtr user_hdtr;
+       struct user32_sf_hdtr user32_hdtr;
+       struct user64_sf_hdtr user64_hdtr;
        off_t off, xfsize;
        off_t nbytes = 0, sbytes = 0;
        int error = 0;
        size_t sizeof_hdtr;
-       size_t size_of_iovec;
        off_t file_size;
        struct vfs_context context = *vfs_context_current();
 
        KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE | DBG_FUNC_START), uap->s,
            0, 0, 0, 0);
+
+       AUDIT_ARG(fd, uap->fd);
+       AUDIT_ARG(value32, uap->s);
+
        /*
         * Do argument checking. Must be a regular file in, stream
         * type and connected socket out, positive offset.
@@ -2085,23 +2146,25 @@ sendfile(struct proc *p, struct sendfile_args *uap, __unused int *retval)
 
                bzero(&user_hdtr, sizeof (user_hdtr));
                if (IS_64BIT_PROCESS(p)) {
-                       hdtrp = (caddr_t)&user_hdtr;
-                       sizeof_hdtr = sizeof (user_hdtr);
-                       size_of_iovec = sizeof (struct user_iovec);
+                       hdtrp = (caddr_t)&user64_hdtr;
+                       sizeof_hdtr = sizeof (user64_hdtr);
                } else {
-                       hdtrp = (caddr_t)&hdtr;
-                       sizeof_hdtr = sizeof (hdtr);
-                       size_of_iovec = sizeof (struct iovec);
+                       hdtrp = (caddr_t)&user32_hdtr;
+                       sizeof_hdtr = sizeof (user32_hdtr);
                }
                error = copyin(uap->hdtr, hdtrp, sizeof_hdtr);
                if (error)
                        goto done2;
-               /*  need to copy if user process is not 64-bit */
-               if (!IS_64BIT_PROCESS(p)) {
-                       user_hdtr.headers = CAST_USER_ADDR_T(hdtr.headers);
-                       user_hdtr.hdr_cnt = hdtr.hdr_cnt;
-                       user_hdtr.trailers = CAST_USER_ADDR_T(hdtr.trailers);
-                       user_hdtr.trl_cnt = hdtr.trl_cnt;
+               if (IS_64BIT_PROCESS(p)) {
+                       user_hdtr.headers = user64_hdtr.headers;
+                       user_hdtr.hdr_cnt = user64_hdtr.hdr_cnt;
+                       user_hdtr.trailers = user64_hdtr.trailers;
+                       user_hdtr.trl_cnt = user64_hdtr.trl_cnt;
+               } else {
+                       user_hdtr.headers = user32_hdtr.headers;
+                       user_hdtr.hdr_cnt = user32_hdtr.hdr_cnt;
+                       user_hdtr.trailers = user32_hdtr.trailers;
+                       user_hdtr.trl_cnt = user32_hdtr.trl_cnt;
                }
 
                /*
@@ -2196,7 +2259,7 @@ sendfile(struct proc *p, struct sendfile_args *uap, __unused int *retval)
                socket_unlock(so, 0);
                alloc_sendpkt(M_WAIT, xfsize, &nbufs, &m0, jumbocl);
                pktlen = mbuf_pkt_maxlen(m0);
-               if (pktlen < xfsize)
+               if (pktlen < (size_t)xfsize)
                        xfsize = pktlen;
 
                auio = uio_createwithbuffer(nbufs, off, UIO_SYSSPACE,
@@ -2210,11 +2273,11 @@ sendfile(struct proc *p, struct sendfile_args *uap, __unused int *retval)
                }
 
                for (i = 0, m = m0, uiolen = 0;
-                   i < nbufs && m != NULL && uiolen < xfsize;
+                   i < nbufs && m != NULL && uiolen < (size_t)xfsize;
                    i++, m = mbuf_next(m)) {
                        size_t mlen = mbuf_maxlen(m);
 
-                       if (mlen + uiolen > xfsize)
+                       if (mlen + uiolen > (size_t)xfsize)
                                mlen = xfsize - uiolen;
                        mbuf_setlen(m, mlen);
                        uio_addiov(auio, CAST_USER_ADDR_T(mbuf_datastart(m)),
@@ -2224,7 +2287,7 @@ sendfile(struct proc *p, struct sendfile_args *uap, __unused int *retval)
 
                if (xfsize != uio_resid(auio))
                        printf("sendfile: xfsize: %lld != uio_resid(auio): "
-                           "%lld\n", xfsize, uio_resid(auio));
+                               "%lld\n", xfsize, (long long)uio_resid(auio));
 
                KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE_READ | DBG_FUNC_START),
                    uap->s, (unsigned int)((xfsize >> 32) & 0x0ffffffff),
@@ -2257,7 +2320,7 @@ sendfile(struct proc *p, struct sendfile_args *uap, __unused int *retval)
                    i++, m = mbuf_next(m)) {
                        size_t mlen = mbuf_maxlen(m);
 
-                       if (rlen + mlen > xfsize)
+                       if (rlen + mlen > (size_t)xfsize)
                                mlen = xfsize - rlen;
                        mbuf_setlen(m, mlen);
 
@@ -2314,53 +2377,20 @@ retry_space:
                        }
                        goto retry_space;
                }
+               
+               struct mbuf *control = NULL;
                {
                        /*
                         * Socket filter processing
                         */
-                       struct socket_filter_entry *filter;
-                       int filtered = 0;
-                       struct mbuf *control = NULL;
-                       boolean_t recursive = (so->so_send_filt_thread != NULL);
 
-                       error = 0;
-                       for (filter = so->so_filt; filter && (error == 0);
-                           filter = filter->sfe_next_onsocket) {
-                               if (filter->sfe_filter->sf_filter.sf_data_out) {
-                                       if (filtered == 0) {
-                                               filtered = 1;
-                                               so->so_send_filt_thread =
-                                                   current_thread();
-                                               sflt_use(so);
-                                               socket_unlock(so, 0);
-                                       }
-                                       error = filter->sfe_filter->sf_filter.
-                                           sf_data_out(filter->sfe_cookie, so,
-                                           NULL, &m0, &control, 0);
-                               }
-                       }
-
-                       if (filtered) {
-                               /*
-                                * At this point, we've run at least one filter.
-                                * The socket is unlocked as is the socket
-                                * buffer.  Clear the recorded filter thread
-                                * only when we are outside of a filter's
-                                * context.  This allows for a filter to issue
-                                * multiple inject calls from its sf_data_out
-                                * callback routine.
-                                */
-                               socket_lock(so, 0);
-                               sflt_unuse(so);
-                               if (!recursive)
-                                       so->so_send_filt_thread = 0;
-                               if (error) {
-                                       if (error == EJUSTRETURN) {
-                                               error = 0;
-                                               continue;
-                                       }
-                                       goto done3;
+                       error = sflt_data_out(so, NULL, &m0, &control, 0);
+                       if (error) {
+                               if (error == EJUSTRETURN) {
+                                       error = 0;
+                                       continue;
                                }
+                               goto done3;
                        }
                        /*
                         * End Socket filter processing
@@ -2369,7 +2399,7 @@ retry_space:
                KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE_SEND | DBG_FUNC_START),
                    uap->s, 0, 0, 0, 0);
                error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m0,
-                   0, 0, p);
+                   0, control, p);
                KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE_SEND | DBG_FUNC_START),
                    uap->s, 0, 0, 0, 0);
                if (error) {