]> git.saurik.com Git - apple/xnu.git/commitdiff
xnu-4903.241.1.tar.gz macos-10143 v4903.241.1
authorApple <opensource@apple.com>
Mon, 17 Jun 2019 20:57:32 +0000 (20:57 +0000)
committerApple <opensource@apple.com>
Mon, 17 Jun 2019 20:57:32 +0000 (20:57 +0000)
20 files changed:
bsd/kern/kern_event.c
bsd/kern/ubc_subr.c
bsd/net/if_ports_used.c
bsd/netinet/flow_divert.c
bsd/netkey/key.c
bsd/security/audit/audit.h
bsd/security/audit/audit_arg.c
bsd/security/audit/audit_bsm.c
bsd/vfs/vfs_syscalls.c
libsyscall/Libsyscall.xcodeproj/project.pbxproj
libsyscall/mach/mach/mach_right.h
libsyscall/mach/mach/mach_right_private.h [new file with mode: 0644]
libsyscall/xcodescripts/mach_install_mig.sh
osfmk/arm64/kpc.c
osfmk/ipc/ipc_kmsg.c
osfmk/ipc/mach_kernelrpc.c
osfmk/kern/ipc_host.c
osfmk/kern/ipc_tt.c
osfmk/kern/task.c
osfmk/vm/vm_map.c

index df25f3112263dfa04f443cbb54913a9c5bcc78f0..ecffc8db733f40f94d7e8a2f4773ae9da3744f31 100644 (file)
@@ -5986,9 +5986,11 @@ kqueue_threadreq_initiate(struct kqueue *kq, struct kqrequest *kqr,
         * Provide the pthread kext a pointer to a workq_threadreq_s structure for
         * its use until a corresponding kqueue_threadreq_bind callback.
         */
         * Provide the pthread kext a pointer to a workq_threadreq_s structure for
         * its use until a corresponding kqueue_threadreq_bind callback.
         */
+#if 0 // 45129862
        if ((kq->kq_state & KQ_WORKLOOP) && current_proc() == kq->kq_p) {
                flags |= WORKQ_THREADREQ_SET_AST_ON_FAILURE;
        }
        if ((kq->kq_state & KQ_WORKLOOP) && current_proc() == kq->kq_p) {
                flags |= WORKQ_THREADREQ_SET_AST_ON_FAILURE;
        }
+#endif
        if (qos == KQWQ_QOS_MANAGER) {
                qos = WORKQ_THREAD_QOS_MANAGER;
        }
        if (qos == KQWQ_QOS_MANAGER) {
                qos = WORKQ_THREAD_QOS_MANAGER;
        }
@@ -6062,9 +6064,11 @@ kqueue_threadreq_modify(struct kqueue *kq, struct kqrequest *kqr, kq_index_t qos
        kq_req_held(kq);
 
        int flags = 0;
        kq_req_held(kq);
 
        int flags = 0;
+#if 0 // 45129862
        if ((kq->kq_state & KQ_WORKLOOP) && kq->kq_p == current_proc()) {
                flags |= WORKQ_THREADREQ_SET_AST_ON_FAILURE;
        }
        if ((kq->kq_state & KQ_WORKLOOP) && kq->kq_p == current_proc()) {
                flags |= WORKQ_THREADREQ_SET_AST_ON_FAILURE;
        }
+#endif
        workq_kern_threadreq_modify(kq->kq_p, kqr, qos, flags);
 }
 
        workq_kern_threadreq_modify(kq->kq_p, kqr, qos, flags);
 }
 
index 6f09debf794c7940d9068cc7e85761ebfb1d6724..abf7e6f53f043934065e9d8fe59a1dae56b7b3b4 100644 (file)
@@ -1128,7 +1128,7 @@ errno_t ubc_setsize_ex(struct vnode *vp, off_t nsize, ubc_setsize_opts_t opts)
                 * zero the tail of this page if it's currently
                 * present in the cache
                 */
                 * zero the tail of this page if it's currently
                 * present in the cache
                 */
-               kret = ubc_create_upl_kernel(vp, lastpg, PAGE_SIZE, &upl, &pl, UPL_SET_LITE, VM_KERN_MEMORY_FILE);
+               kret = ubc_create_upl_kernel(vp, lastpg, PAGE_SIZE, &upl, &pl, UPL_SET_LITE | UPL_WILL_MODIFY, VM_KERN_MEMORY_FILE);
 
                if (kret != KERN_SUCCESS)
                        panic("ubc_setsize: ubc_create_upl (error = %d)\n", kret);
 
                if (kret != KERN_SUCCESS)
                        panic("ubc_setsize: ubc_create_upl (error = %d)\n", kret);
index 643df3b2d5de1787e424c8b716c6393b2778ca66..c78a690a14c8af99db8673805cce12590cc92d8e 100644 (file)
@@ -72,6 +72,7 @@ SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, list,
 
 static int use_test_wakeuuid = 0;
 static uuid_t test_wakeuuid;
 
 static int use_test_wakeuuid = 0;
 static uuid_t test_wakeuuid;
+static uuid_string_t test_wakeuuid_str;
 
 #if (DEVELOPMENT || DEBUG)
 SYSCTL_INT(_net_link_generic_system_port_used, OID_AUTO, use_test_wakeuuid,
 
 #if (DEVELOPMENT || DEBUG)
 SYSCTL_INT(_net_link_generic_system_port_used, OID_AUTO, use_test_wakeuuid,
@@ -88,6 +89,11 @@ SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, clear_test_wakeuuid,
     CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
     sysctl_clear_test_wakeuuid, "S,uuid_t", "");
 
     CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
     sysctl_clear_test_wakeuuid, "S,uuid_t", "");
 
+int sysctl_test_wakeuuid_str SYSCTL_HANDLER_ARGS;
+SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, test_wakeuuid_str,
+    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
+    sysctl_test_wakeuuid_str, "A", "");
+
 SYSCTL_OPAQUE(_net_link_generic_system_port_used, OID_AUTO, test_wakeuuid,
     CTLFLAG_RD|CTLFLAG_LOCKED,
     test_wakeuuid, sizeof(uuid_t), "S,uuid_t", "");
 SYSCTL_OPAQUE(_net_link_generic_system_port_used, OID_AUTO, test_wakeuuid,
     CTLFLAG_RD|CTLFLAG_LOCKED,
     test_wakeuuid, sizeof(uuid_t), "S,uuid_t", "");
@@ -209,12 +215,17 @@ net_port_entry_list_clear(void)
 }
 
 static bool
 }
 
 static bool
-get_test_wake_uuid(uuid_t wakeuuid)
+get_test_wake_uuid(uuid_string_t wakeuuid_str, size_t len)
 {
        if (__improbable(use_test_wakeuuid)) {
                if (!uuid_is_null(test_wakeuuid)) {
 {
        if (__improbable(use_test_wakeuuid)) {
                if (!uuid_is_null(test_wakeuuid)) {
-                       if (wakeuuid != NULL) {
-                               uuid_copy(wakeuuid, test_wakeuuid);
+                       if (wakeuuid_str != NULL && len != 0) {
+                               uuid_unparse(test_wakeuuid, wakeuuid_str);
+                       }
+                       return (true);
+               } else if (strlen(test_wakeuuid_str) != 0) {
+                       if (wakeuuid_str != NULL && len != 0) {
+                               strlcpy(wakeuuid_str, test_wakeuuid_str, len);
                        }
                        return (true);
                } else {
                        }
                        return (true);
                } else {
@@ -232,7 +243,7 @@ is_wakeuuid_set(void)
         * IOPMCopySleepWakeUUIDKey() tells if SleepWakeUUID is currently set
         * That means we are currently in a sleep/wake cycle
         */
         * IOPMCopySleepWakeUUIDKey() tells if SleepWakeUUID is currently set
         * That means we are currently in a sleep/wake cycle
         */
-       return (get_test_wake_uuid(NULL) || IOPMCopySleepWakeUUIDKey(NULL, 0));
+       return (get_test_wake_uuid(NULL, 0) || IOPMCopySleepWakeUUIDKey(NULL, 0));
 }
 
 void
 }
 
 void
@@ -241,16 +252,25 @@ if_ports_used_update_wakeuuid(struct ifnet *ifp)
        uuid_t wakeuuid;
        bool wakeuuid_is_set = false;
        bool updated = false;
        uuid_t wakeuuid;
        bool wakeuuid_is_set = false;
        bool updated = false;
+       uuid_string_t wakeuuid_str;
+
+       uuid_clear(wakeuuid);
 
        if (__improbable(use_test_wakeuuid)) {
 
        if (__improbable(use_test_wakeuuid)) {
-               wakeuuid_is_set = get_test_wake_uuid(wakeuuid);
+               wakeuuid_is_set = get_test_wake_uuid(wakeuuid_str,
+                   sizeof(wakeuuid_str));
        } else {
        } else {
-               uuid_string_t wakeuuid_str;
 
                wakeuuid_is_set = IOPMCopySleepWakeUUIDKey(wakeuuid_str,
                    sizeof(wakeuuid_str));
 
                wakeuuid_is_set = IOPMCopySleepWakeUUIDKey(wakeuuid_str,
                    sizeof(wakeuuid_str));
-               if (wakeuuid_is_set) {
-                       uuid_parse(wakeuuid_str, wakeuuid);
+       }
+
+       if (wakeuuid_is_set) {
+               if (uuid_parse(wakeuuid_str, wakeuuid) != 0) {
+                       os_log(OS_LOG_DEFAULT,
+                           "%s: IOPMCopySleepWakeUUIDKey got bad value %s\n",
+                           __func__, wakeuuid_str);
+                       wakeuuid_is_set = false;
                }
        }
 
                }
        }
 
@@ -446,6 +466,7 @@ sysctl_clear_test_wakeuuid SYSCTL_HANDLER_ARGS
        }
        if (req->newptr != USER_ADDR_NULL) {
                uuid_clear(test_wakeuuid);
        }
        if (req->newptr != USER_ADDR_NULL) {
                uuid_clear(test_wakeuuid);
+               test_wakeuuid_str[0] = 0;
        }
        error = SYSCTL_OUT(req, test_wakeuuid,
            MIN(sizeof(uuid_t), req->oldlen));
        }
        error = SYSCTL_OUT(req, test_wakeuuid,
            MIN(sizeof(uuid_t), req->oldlen));
@@ -453,6 +474,25 @@ sysctl_clear_test_wakeuuid SYSCTL_HANDLER_ARGS
        return (error);
 }
 
        return (error);
 }
 
+int
+sysctl_test_wakeuuid_str SYSCTL_HANDLER_ARGS
+{
+#pragma unused(oidp, arg1, arg2)
+       int error = 0;
+       int changed;
+
+       if (kauth_cred_issuser(kauth_cred_get()) == 0) {
+               return (EPERM);
+       }
+       error = sysctl_io_string(req, test_wakeuuid_str, sizeof(test_wakeuuid_str), 1, &changed);
+       if (changed) {
+               os_log_info(OS_LOG_DEFAULT, "%s: test_wakeuuid_str %s",
+                   __func__, test_wakeuuid_str);
+       }
+
+       return (error);
+}
+
 #endif /* (DEVELOPMENT || DEBUG) */
 
 int
 #endif /* (DEVELOPMENT || DEBUG) */
 
 int
index b6d668440758a0bc7f7d0eb10b938b71704bffa4..c3bc7930cd23061355fd8c48ad1a0f277e38df2f 100644 (file)
@@ -1913,18 +1913,20 @@ flow_divert_handle_close(struct flow_divert_pcb *fd_cb, mbuf_t packet, int offse
 static mbuf_t
 flow_divert_get_control_mbuf(struct flow_divert_pcb *fd_cb)
 {
 static mbuf_t
 flow_divert_get_control_mbuf(struct flow_divert_pcb *fd_cb)
 {
-       struct inpcb *inp = sotoinpcb(fd_cb->so);
-       if (inp->inp_vflag & INP_IPV4 && inp->inp_flags & INP_RECVDSTADDR) {
-               struct sockaddr_in *sin = (struct sockaddr_in *)(void *)fd_cb->local_address;
-
-               return sbcreatecontrol((caddr_t) &sin->sin_addr, sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
-       } else if (inp->inp_vflag & INP_IPV6 && (inp->inp_flags & IN6P_PKTINFO) != 0) {
-               struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(void *)fd_cb->local_address;
-               struct in6_pktinfo pi6;
-
-               bcopy(&sin6->sin6_addr, &pi6.ipi6_addr, sizeof (struct in6_addr));
-               pi6.ipi6_ifindex = 0;
-               return sbcreatecontrol((caddr_t)&pi6, sizeof (struct in6_pktinfo), IPV6_PKTINFO, IPPROTO_IPV6);
+       if (fd_cb->local_address != NULL) {
+               struct inpcb *inp = sotoinpcb(fd_cb->so);
+               if (inp->inp_vflag & INP_IPV4 && inp->inp_flags & INP_RECVDSTADDR) {
+                       struct sockaddr_in *sin = (struct sockaddr_in *)(void *)fd_cb->local_address;
+
+                       return sbcreatecontrol((caddr_t) &sin->sin_addr, sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
+               } else if (inp->inp_vflag & INP_IPV6 && (inp->inp_flags & IN6P_PKTINFO) != 0) {
+                       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(void *)fd_cb->local_address;
+                       struct in6_pktinfo pi6;
+
+                       bcopy(&sin6->sin6_addr, &pi6.ipi6_addr, sizeof (struct in6_addr));
+                       pi6.ipi6_ifindex = 0;
+                       return sbcreatecontrol((caddr_t)&pi6, sizeof (struct in6_pktinfo), IPV6_PKTINFO, IPPROTO_IPV6);
+               }
        }
        return (NULL);
 }
        }
        return (NULL);
 }
index f373441d06af49b7a008b0a933660f71d06041a3..1e4b998110f07f9943fc4fa515cabcd554e25d6e 100644 (file)
@@ -7898,6 +7898,7 @@ static int
 key_getsastatbyspi (struct sastat *stat_arg,
                                        u_int32_t      max_stat_arg,
                                        struct sastat *stat_res,
 key_getsastatbyspi (struct sastat *stat_arg,
                                        u_int32_t      max_stat_arg,
                                        struct sastat *stat_res,
+                                       u_int32_t      stat_res_size,
                                        u_int32_t     *max_stat_res)
 {
        int cur, found = 0;
                                        u_int32_t     *max_stat_res)
 {
        int cur, found = 0;
@@ -7907,8 +7908,11 @@ key_getsastatbyspi (struct sastat *stat_arg,
            max_stat_res == NULL) {
                return -1;
        }
            max_stat_res == NULL) {
                return -1;
        }
+
+       u_int32_t max_stats = stat_res_size / (sizeof(struct sastat));
+       max_stats = ((max_stat_arg <= max_stats) ? max_stat_arg : max_stats);
        
        
-       for (cur = 0; cur < max_stat_arg; cur++) {
+       for (cur = 0; cur < max_stats; cur++) {
                if (key_getsastatbyspi_one(stat_arg[cur].spi,
                                                                   &stat_res[found]) == 0) {
                        found++;
                if (key_getsastatbyspi_one(stat_arg[cur].spi,
                                                                   &stat_res[found]) == 0) {
                        found++;
@@ -9863,6 +9867,15 @@ key_validate_ext(
                                return EINVAL;
                        break;
        }
                                return EINVAL;
                        break;
        }
+
+       /* check key bits length */
+       if (ext->sadb_ext_type == SADB_EXT_KEY_AUTH ||
+           ext->sadb_ext_type == SADB_EXT_KEY_ENCRYPT) {
+               struct sadb_key *key = (struct sadb_key *)(uintptr_t)ext;
+               if (len < (sizeof(struct sadb_key) + _KEYLEN(key))) {
+                       return EINVAL;
+               }
+       }
        
        return 0;
 }
        
        return 0;
 }
@@ -10168,6 +10181,7 @@ key_getsastat (struct socket *so,
        if (key_getsastatbyspi((struct sastat *)(sa_stats_arg + 1),
                                                   arg_count,
                                                   sa_stats_sav,
        if (key_getsastatbyspi((struct sastat *)(sa_stats_arg + 1),
                                                   arg_count,
                                                   sa_stats_sav,
+                                                  bufsize,
                                                   &res_count)) {
                printf("%s: Error finding SAs.\n", __FUNCTION__);
                error = ENOENT;
                                                   &res_count)) {
                printf("%s: Error finding SAs.\n", __FUNCTION__);
                error = ENOENT;
index 6a60b36c6fabca79f5114a682ac55dd4a2a5036a..08766aa000b5a4179844c322516313139e7219a0 100644 (file)
@@ -220,6 +220,8 @@ void         audit_arg_auditinfo_addr(struct kaudit_record *ar,
                struct auditinfo_addr *au_info);
 void    audit_arg_upath(struct kaudit_record *ar, struct vnode *cwd_vp,
                char *upath, u_int64_t flags);
                struct auditinfo_addr *au_info);
 void    audit_arg_upath(struct kaudit_record *ar, struct vnode *cwd_vp,
                char *upath, u_int64_t flags);
+void    audit_arg_kpath(struct kaudit_record *ar,
+               char *kpath, u_int64_t flags);
 void    audit_arg_vnpath(struct kaudit_record *ar, struct vnode *vp,
                u_int64_t flags);
 void    audit_arg_vnpath_withref(struct kaudit_record *ar, struct vnode *vp,
 void    audit_arg_vnpath(struct kaudit_record *ar, struct vnode *vp,
                u_int64_t flags);
 void    audit_arg_vnpath_withref(struct kaudit_record *ar, struct vnode *vp,
@@ -317,6 +319,8 @@ extern au_event_t sys_au_event[];
 
 #endif /* AUDIT_USE_BUILTIN_EXPECT */
 
 
 #endif /* AUDIT_USE_BUILTIN_EXPECT */
 
+#define AUDIT_RECORD_EXISTS() (AUDIT_ENABLED() && AUDIT_AUDITING(AUDIT_RECORD()))
+
 /*
  * Define a macro to wrap the audit_arg_* calls by checking the global
  * audit_enabled flag before performing the actual call.
 /*
  * Define a macro to wrap the audit_arg_* calls by checking the global
  * audit_enabled flag before performing the actual call.
index 950d1f49ff4d50140b42a83ba49c0ce93ea2f257..919b3dc685b430fd76600309bc65980cc115236b 100644 (file)
@@ -696,6 +696,31 @@ audit_arg_upath(struct kaudit_record *ar, struct vnode *cwd_vp, char *upath, u_i
        }
 }
 
        }
 }
 
+void
+audit_arg_kpath(struct kaudit_record *ar, char *kpath, u_int64_t flag)
+{
+       char **pathp;
+
+       KASSERT(kpath != NULL, ("audit_arg_kpath: kpath == NULL"));
+       KASSERT((flag == ARG_KPATH1) || (flag == ARG_KPATH2),
+           ("audit_arg_kpath: flag %llu", (unsigned long long)flag));
+       KASSERT((flag != ARG_KPATH1) || (flag != ARG_KPATH2),
+           ("audit_arg_kpath: flag %llu", (unsigned long long)flag));
+
+       if (flag == ARG_KPATH1)
+               pathp = &ar->k_ar.ar_arg_kpath1;
+       else
+               pathp = &ar->k_ar.ar_arg_kpath2;
+
+       if (*pathp == NULL)
+               *pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK);
+       else
+               return;
+
+       strlcpy(*pathp, kpath, MAXPATHLEN);
+       ARG_SET_VALID(ar, flag);
+}
+
 /*
  * Function to save the path and vnode attr information into the audit
  * record.
 /*
  * Function to save the path and vnode attr information into the audit
  * record.
index 60c8dbf149a3453a746cd819161c69c6e16dbf33..876833e4b862fcd9843af3bb0a88782539a7cdd2 100644 (file)
@@ -227,6 +227,13 @@ kau_free(struct au_record *rec)
        }                                                               \
 } while (0)
 
        }                                                               \
 } while (0)
 
+#define KPATH2_TOKENS do {                                             \
+       if (ARG_IS_VALID(kar, ARG_KPATH2)) {                            \
+               tok = au_to_path(ar->ar_arg_kpath2);                    \
+               kau_write(rec, tok);                                    \
+       }                                                               \
+} while (0)
+
 #define        VNODE1_TOKENS do {                                              \
        if (ARG_IS_VALID(kar, ARG_KPATH1)) {                            \
                tok = au_to_path(ar->ar_arg_kpath1);                    \
 #define        VNODE1_TOKENS do {                                              \
        if (ARG_IS_VALID(kar, ARG_KPATH1)) {                            \
                tok = au_to_path(ar->ar_arg_kpath1);                    \
@@ -1188,6 +1195,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
        case AUE_RENAME:
                UPATH1_VNODE1_TOKENS;
                UPATH2_TOKENS;
        case AUE_RENAME:
                UPATH1_VNODE1_TOKENS;
                UPATH2_TOKENS;
+               KPATH2_TOKENS;
                break;
 
        case AUE_MKDIR_EXTENDED:
                break;
 
        case AUE_MKDIR_EXTENDED:
index 767d352c6993af8969b2a1f37520912eee24e5a7..4e24c8489976e4450c21a541fb8ace87ba2bb3a0 100644 (file)
@@ -4375,7 +4375,7 @@ linkat_internal(vfs_context_t ctx, int fd1, user_addr_t path, int fd2,
 #if CONFIG_FSE
        fse_info finfo;
 #endif
 #if CONFIG_FSE
        fse_info finfo;
 #endif
-       int need_event, has_listeners;
+       int need_event, has_listeners, need_kpath2;
        char *target_path = NULL;
        int truncated=0;
 
        char *target_path = NULL;
        int truncated=0;
 
@@ -4471,7 +4471,14 @@ linkat_internal(vfs_context_t ctx, int fd1, user_addr_t path, int fd2,
 #endif
        has_listeners = kauth_authorize_fileop_has_listeners();
 
 #endif
        has_listeners = kauth_authorize_fileop_has_listeners();
 
-       if (need_event || has_listeners) {
+       need_kpath2 = 0;
+#if CONFIG_AUDIT
+       if (AUDIT_RECORD_EXISTS()) {
+               need_kpath2 = 1;
+       }
+#endif
+
+       if (need_event || has_listeners || need_kpath2) {
                char *link_to_path = NULL;
                int len, link_name_len;
 
                char *link_to_path = NULL;
                int len, link_name_len;
 
@@ -4484,6 +4491,8 @@ linkat_internal(vfs_context_t ctx, int fd1, user_addr_t path, int fd2,
 
                len = safe_getpath(dvp, nd.ni_cnd.cn_nameptr, target_path, MAXPATHLEN, &truncated);
 
 
                len = safe_getpath(dvp, nd.ni_cnd.cn_nameptr, target_path, MAXPATHLEN, &truncated);
 
+               AUDIT_ARG(kpath, target_path, ARG_KPATH2);
+
                if (has_listeners) {
                        /* build the path to file we are linking to */
                        GET_PATH(link_to_path);
                if (has_listeners) {
                        /* build the path to file we are linking to */
                        GET_PATH(link_to_path);
@@ -7317,6 +7326,8 @@ renameat_internal(vfs_context_t ctx, int fromfd, user_addr_t from,
        int retry_count;
        int mntrename;
        int need_event;
        int retry_count;
        int mntrename;
        int need_event;
+       int need_kpath2;
+       int has_listeners;
        const char *oname = NULL;
        char *from_name = NULL, *to_name = NULL;
        int from_len=0, to_len=0;
        const char *oname = NULL;
        char *from_name = NULL, *to_name = NULL;
        int from_len=0, to_len=0;
@@ -7439,7 +7450,16 @@ continue_lookup:
        need_event = 0;
 #endif /* CONFIG_FSE */
 
        need_event = 0;
 #endif /* CONFIG_FSE */
 
-       if (need_event || kauth_authorize_fileop_has_listeners()) {
+       has_listeners = kauth_authorize_fileop_has_listeners();
+
+       need_kpath2 = 0;
+#if CONFIG_AUDIT
+       if (AUDIT_RECORD_EXISTS()) {
+               need_kpath2 = 1;
+       }
+#endif
+
+       if (need_event || has_listeners) {
                if (from_name == NULL) {
                        GET_PATH(from_name);
                        if (from_name == NULL) {
                if (from_name == NULL) {
                        GET_PATH(from_name);
                        if (from_name == NULL) {
@@ -7449,7 +7469,9 @@ continue_lookup:
                }
 
                from_len = safe_getpath(fdvp, fromnd->ni_cnd.cn_nameptr, from_name, MAXPATHLEN, &from_truncated);
                }
 
                from_len = safe_getpath(fdvp, fromnd->ni_cnd.cn_nameptr, from_name, MAXPATHLEN, &from_truncated);
+       }
 
 
+       if (need_event || need_kpath2 || has_listeners) {
                if (to_name == NULL) {
                        GET_PATH(to_name);
                        if (to_name == NULL) {
                if (to_name == NULL) {
                        GET_PATH(to_name);
                        if (to_name == NULL) {
@@ -7459,6 +7481,9 @@ continue_lookup:
                }
 
                to_len = safe_getpath(tdvp, tond->ni_cnd.cn_nameptr, to_name, MAXPATHLEN, &to_truncated);
                }
 
                to_len = safe_getpath(tdvp, tond->ni_cnd.cn_nameptr, to_name, MAXPATHLEN, &to_truncated);
+               if (to_name && need_kpath2) {
+                       AUDIT_ARG(kpath, to_name, ARG_KPATH2);
+               }
        }
        if (!fvp) {
                /*
        }
        if (!fvp) {
                /*
index e138202c11b626cff410c44dbc4e8da90636168d..c5f769437330ba2d20a4319367794779a414fa9e 100644 (file)
                E214BDC81C2E358300CEE8A3 /* clonefile.c in Sources */ = {isa = PBXBuildFile; fileRef = E214BDC71C2E34E200CEE8A3 /* clonefile.c */; };
                E2A0F3341C3B17D100A11F8A /* fs_snapshot.c in Sources */ = {isa = PBXBuildFile; fileRef = E2A0F3331C3B17D100A11F8A /* fs_snapshot.c */; };
                E4216C311822D404006F2632 /* mach_voucher.defs in Sources */ = {isa = PBXBuildFile; fileRef = E4216C301822D404006F2632 /* mach_voucher.defs */; };
                E214BDC81C2E358300CEE8A3 /* clonefile.c in Sources */ = {isa = PBXBuildFile; fileRef = E214BDC71C2E34E200CEE8A3 /* clonefile.c */; };
                E2A0F3341C3B17D100A11F8A /* fs_snapshot.c in Sources */ = {isa = PBXBuildFile; fileRef = E2A0F3331C3B17D100A11F8A /* fs_snapshot.c */; };
                E4216C311822D404006F2632 /* mach_voucher.defs in Sources */ = {isa = PBXBuildFile; fileRef = E4216C301822D404006F2632 /* mach_voucher.defs */; };
+               E4512B8C21AFDF1600673F73 /* mach_right_private.h in Headers */ = {isa = PBXBuildFile; fileRef = E4512B8B21AFDF1500673F73 /* mach_right_private.h */; };
+               E4512B8D21AFDF1600673F73 /* mach_right_private.h in Headers */ = {isa = PBXBuildFile; fileRef = E4512B8B21AFDF1500673F73 /* mach_right_private.h */; };
                E453AF351700FD3C00F2C94C /* getiopolicy_np.c in Sources */ = {isa = PBXBuildFile; fileRef = E453AF341700FD3C00F2C94C /* getiopolicy_np.c */; };
                E453AF3617013CBF00F2C94C /* libproc.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D45C2B16F868ED0002AF25 /* libproc.h */; settings = {ATTRIBUTES = (Public, ); }; };
                E453AF3717013CC200F2C94C /* libproc_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D45C2C16F868ED0002AF25 /* libproc_internal.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E453AF351700FD3C00F2C94C /* getiopolicy_np.c in Sources */ = {isa = PBXBuildFile; fileRef = E453AF341700FD3C00F2C94C /* getiopolicy_np.c */; };
                E453AF3617013CBF00F2C94C /* libproc.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D45C2B16F868ED0002AF25 /* libproc.h */; settings = {ATTRIBUTES = (Public, ); }; };
                E453AF3717013CC200F2C94C /* libproc_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D45C2C16F868ED0002AF25 /* libproc_internal.h */; settings = {ATTRIBUTES = (Private, ); }; };
                40DF0F731E5CD7B30035A864 /* cpu_copy_in_cksum_gen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cpu_copy_in_cksum_gen.c; path = skywalk/cpu_copy_in_cksum_gen.c; sourceTree = "<group>"; };
                435F3CA91B06B7BA005ED9EF /* work_interval.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = work_interval.c; sourceTree = "<group>"; };
                467DAFD3157E8AF200CE68F0 /* guarded_open_np.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = guarded_open_np.c; sourceTree = "<group>"; };
                40DF0F731E5CD7B30035A864 /* cpu_copy_in_cksum_gen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cpu_copy_in_cksum_gen.c; path = skywalk/cpu_copy_in_cksum_gen.c; sourceTree = "<group>"; };
                435F3CA91B06B7BA005ED9EF /* work_interval.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = work_interval.c; sourceTree = "<group>"; };
                467DAFD3157E8AF200CE68F0 /* guarded_open_np.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = guarded_open_np.c; sourceTree = "<group>"; };
-               4BCDD8AE20741A4700FA37A3 /* mach_right.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mach_right.h; sourceTree = "<group>"; };
+               4BCDD8AE20741A4700FA37A3 /* mach_right.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_right.h; sourceTree = "<group>"; };
                4BCDD8B120741C2F00FA37A3 /* mach_right.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mach_right.c; sourceTree = "<group>"; };
                4BDD5F1B1891AB2F004BF300 /* mach_approximate_time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach_approximate_time.c; sourceTree = "<group>"; };
                4BDD5F1C1891AB2F004BF300 /* mach_approximate_time.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = mach_approximate_time.s; sourceTree = "<group>"; };
                4BCDD8B120741C2F00FA37A3 /* mach_right.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mach_right.c; sourceTree = "<group>"; };
                4BDD5F1B1891AB2F004BF300 /* mach_approximate_time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach_approximate_time.c; sourceTree = "<group>"; };
                4BDD5F1C1891AB2F004BF300 /* mach_approximate_time.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = mach_approximate_time.s; sourceTree = "<group>"; };
                E214BDC71C2E34E200CEE8A3 /* clonefile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = clonefile.c; sourceTree = "<group>"; };
                E2A0F3331C3B17D100A11F8A /* fs_snapshot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fs_snapshot.c; sourceTree = "<group>"; };
                E4216C301822D404006F2632 /* mach_voucher.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = mach_voucher.defs; sourceTree = "<group>"; };
                E214BDC71C2E34E200CEE8A3 /* clonefile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = clonefile.c; sourceTree = "<group>"; };
                E2A0F3331C3B17D100A11F8A /* fs_snapshot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fs_snapshot.c; sourceTree = "<group>"; };
                E4216C301822D404006F2632 /* mach_voucher.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = mach_voucher.defs; sourceTree = "<group>"; };
+               E4512B8B21AFDF1500673F73 /* mach_right_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_right_private.h; sourceTree = "<group>"; };
                E453AF341700FD3C00F2C94C /* getiopolicy_np.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = getiopolicy_np.c; sourceTree = "<group>"; };
                E4D45C2116F856900002AF25 /* __commpage_gettimeofday.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = __commpage_gettimeofday.c; sourceTree = "<group>"; };
                E4D45C2316F856900002AF25 /* mach_absolute_time.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = mach_absolute_time.s; sourceTree = "<group>"; };
                E453AF341700FD3C00F2C94C /* getiopolicy_np.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = getiopolicy_np.c; sourceTree = "<group>"; };
                E4D45C2116F856900002AF25 /* __commpage_gettimeofday.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = __commpage_gettimeofday.c; sourceTree = "<group>"; };
                E4D45C2316F856900002AF25 /* mach_absolute_time.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = mach_absolute_time.s; sourceTree = "<group>"; };
                                C9D9BCDD114B00600000D8B9 /* mach_interface.h */,
                                9C6DA3D120A3D09F0090330B /* mach_sync_ipc.h */,
                                4BCDD8AE20741A4700FA37A3 /* mach_right.h */,
                                C9D9BCDD114B00600000D8B9 /* mach_interface.h */,
                                9C6DA3D120A3D09F0090330B /* mach_sync_ipc.h */,
                                4BCDD8AE20741A4700FA37A3 /* mach_right.h */,
+                               E4512B8B21AFDF1500673F73 /* mach_right_private.h */,
                                C9D9BCDF114B00600000D8B9 /* port_obj.h */,
                                C9D9BCE0114B00600000D8B9 /* sync.h */,
                                928336A21B8412C100873B90 /* thread_state.h */,
                                C9D9BCDF114B00600000D8B9 /* port_obj.h */,
                                C9D9BCE0114B00600000D8B9 /* sync.h */,
                                928336A21B8412C100873B90 /* thread_state.h */,
                        buildActionMask = 2147483647;
                        files = (
                                C6D3EFB616542C510052CF30 /* errorlib.h in Headers */,
                        buildActionMask = 2147483647;
                        files = (
                                C6D3EFB616542C510052CF30 /* errorlib.h in Headers */,
+                               E4512B8D21AFDF1600673F73 /* mach_right_private.h in Headers */,
                                C6D3EFB716542C510052CF30 /* externs.h in Headers */,
                                C6AB38DB174202C10036DD9F /* gethostuuid.h in Headers */,
                                C6D3EFB816542C510052CF30 /* errorlib.h in Headers */,
                                C6D3EFB716542C510052CF30 /* externs.h in Headers */,
                                C6AB38DB174202C10036DD9F /* gethostuuid.h in Headers */,
                                C6D3EFB816542C510052CF30 /* errorlib.h in Headers */,
                                24B028F511FF5C3500CA64A9 /* _libkernel_init.h in Headers */,
                                A59CB95616669EFB00B064B3 /* stack_logging_internal.h in Headers */,
                                E4D45C3F16FB20D30002AF25 /* spawn.h in Headers */,
                                24B028F511FF5C3500CA64A9 /* _libkernel_init.h in Headers */,
                                A59CB95616669EFB00B064B3 /* stack_logging_internal.h in Headers */,
                                E4D45C3F16FB20D30002AF25 /* spawn.h in Headers */,
+                               E4512B8C21AFDF1600673F73 /* mach_right_private.h in Headers */,
                                9C6DA3D220A3D09F0090330B /* mach_sync_ipc.h in Headers */,
                                E4D45C4016FB20DC0002AF25 /* spawn_private.h in Headers */,
                                E4D45C2F16F868ED0002AF25 /* libproc.h in Headers */,
                                9C6DA3D220A3D09F0090330B /* mach_sync_ipc.h in Headers */,
                                E4D45C4016FB20DC0002AF25 /* spawn_private.h in Headers */,
                                E4D45C2F16F868ED0002AF25 /* libproc.h in Headers */,
index 2a7522ee83546ad8bbe5413aa8375101096f3d6f..8f449e5f9749ee20d7c9b07cc358e43fb18cf1ac 100644 (file)
 #ifndef __MACH_RIGHT_H
 #define __MACH_RIGHT_H
 
 #ifndef __MACH_RIGHT_H
 #define __MACH_RIGHT_H
 
-#include <os/base.h>
-#include <mach/mach.h>
-#include <mach/port.h>
-#include <mach/mach_port.h>
 #include <sys/cdefs.h>
 #include <sys/cdefs.h>
-#include <stdbool.h>
 
 
-__BEGIN_DECLS;
-
-/*!
- * @typedef mach_right_recv_t
- * A type representing the receive right to a Mach port.
- */
-typedef struct _mach_right_recv {
-       mach_port_t mrr_name;
-} mach_right_recv_t;
-
-/*!
- * @const MACH_RIGHT_RECV_NULL
- * A convenience initializer for a receive right object.
- */
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-#define MACH_RIGHT_RECV_NULL ((mach_right_recv_t){MACH_PORT_NULL})
-#elif defined(__cplusplus) && __cplusplus >= 201103L
-#define MACH_RIGHT_RECV_NULL (mach_right_recv_t{MACH_PORT_NULL})
-#elif defined(__cplusplus)
-#define MACH_RIGHT_RECV_NULL \
-               (mach_right_recv_t((mach_right_recv_t){MACH_PORT_NULL}))
-#else
-#define MACH_RIGHT_RECV_NULL {MACH_PORT_NULL}
+#if __has_include(<mach/mach_right_private.h>)
+#include <mach/mach_right_private.h>
 #endif
 
 #endif
 
-/*!
- * @typedef mach_right_send_t
- * A type representing a send right to a Mach port.
- */
-typedef struct _mach_right_send {
-       mach_port_t mrs_name;
-} mach_right_send_t;
-
-/*!
- * @const MACH_RIGHT_SEND_NULL
- * A convenience initializer for a send right object.
- */
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-#define MACH_RIGHT_SEND_NULL ((mach_right_send_t){MACH_PORT_NULL})
-#elif defined(__cplusplus) && __cplusplus >= 201103L
-#define MACH_RIGHT_SEND_NULL (mach_right_send_t{MACH_PORT_NULL})
-#elif defined(__cplusplus)
-#define MACH_RIGHT_SEND_NULL \
-               (mach_right_send_t((mach_right_send_t){MACH_PORT_NULL}))
-#else
-#define MACH_RIGHT_SEND_NULL {MACH_PORT_NULL}
-#endif
-
-/*!
- * @typedef mach_right_send_once_t
- * A type representing a send-once right to a Mach port.
- */
-typedef struct _mach_right_send_once {
-       mach_port_t mrso_name;
-} mach_right_send_once_t;
-
-/*!
- * @const MACH_RIGHT_SEND_ONCE_NULL
- * A convenience initializer for a send-once right object.
- */
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-#define MACH_RIGHT_SEND_ONCE_NULL ((mach_right_send_once_t){MACH_PORT_NULL})
-#elif defined(__cplusplus) && __cplusplus >= 201103L
-#define MACH_RIGHT_SEND_ONCE_NULL (mach_right_send_once_t{MACH_PORT_NULL})
-#elif defined(__cplusplus)
-#define MACH_RIGHT_SEND_ONCE_NULL \
-               (mach_right_send_once_t((mach_right_send_once_t){MACH_PORT_NULL}))
-#else
-#define MACH_RIGHT_SEND_ONCE_NULL {MACH_PORT_NULL}
-#endif
-
-/*!
- * @function mach_right_recv
- * Wraps a port name as a receive right object.
- *
- * @param pn
- * The port name. If this name is valid but does not represent a receive right,
- * the behavior of mach_right_recv_* implementations is undefined.
- *
- * @result
- * A new receive right object.
- */
-OS_ALWAYS_INLINE OS_WARN_RESULT
-static inline mach_right_recv_t
-mach_right_recv(mach_port_name_t pn)
-{
-       mach_right_recv_t mrr = {pn};
-       return mrr;
-}
-
-/*!
- * @function mach_right_send
- * Wraps a port name as a send right object.
- *
- * @param pn
- * The port name. If this name is valid but does not represent a send right, the
- * behavior of mach_right_send_* implementations is undefined.
- *
- * @result
- * A new send right object.
- */
-OS_ALWAYS_INLINE OS_WARN_RESULT
-static inline mach_right_send_t
-mach_right_send(mach_port_name_t pn)
-{
-       mach_right_send_t mrs = {pn};
-       return mrs;
-}
-
-/*!
- * @function mach_right_send_valid
- * Checks if the given send right object is valid.
- *
- * @param mrs
- * The send right object to check.
- *
- * @result
- * A Boolean indicating whether the right is valid.
- */
-OS_ALWAYS_INLINE OS_WARN_RESULT
-static inline bool
-mach_right_send_valid(mach_right_send_t mrs)
-{
-       return MACH_PORT_VALID(mrs.mrs_name);
-}
-
-/*!
- * @function mach_right_send_once
- * Wraps a port name as a send-once right object.
- *
- * @param pn
- * The port name. If this name is valid but does not represent a send-once
- * right, the behavior of mach_right_send_once_* implementations is undefined.
- *
- * @result
- * A new send-once right object.
- */
-OS_ALWAYS_INLINE OS_WARN_RESULT
-static inline mach_right_send_once_t
-mach_right_send_once(mach_port_name_t pn)
-{
-       mach_right_send_once_t mrso = {pn};
-       return mrso;
-}
-
-/*!
- * @function mach_right_send_once_valid
- * Checks if the given send-once right object is valid.
- *
- * @param mrso
- * The send-once right object to check.
- *
- * @result
- * A Boolean indicating whether the right is valid.
- */
-OS_ALWAYS_INLINE OS_WARN_RESULT
-static inline bool
-mach_right_send_once_valid(mach_right_send_once_t mrso)
-{
-       return MACH_PORT_VALID(mrso.mrso_name);
-}
-
-/*!
- * @typedef mach_right_flags_t
- * Flags influencing the behavior of a constructed Mach port.
- *
- * @const MACH_RIGHT_RECV_INIT
- * No flags set. This value is suitable for initialization purposes.
- *
- * @const MACH_RIGHT_RECV_UNGUARDED
- * The given context should not serve as a guard for the underlying port's
- * destruction.
- */
-OS_ENUM(mach_right_flags, uint64_t,
-       MACH_RIGHT_RECV_FLAG_INIT = 0,
-       MACH_RIGHT_RECV_FLAG_UNGUARDED = (1 << 0),
-);
-
-/*!
- * @function mach_right_recv_construct
- * Allocates a new Mach port and returns the receive right to the caller.
- *
- * @param flags
- * Flags to influence the behavior of the new port.
- *
- * @param sr
- * If non-NULL, will be filled in with the name of a send right which
- * corresponds to the new port. The caller is responsible for disposing of this
- * send right with {@link mach_right_send_release}.
- *
- * @param ctx
- * Context to be associated with the new port. By default, this context must be
- * passed to {@link mach_right_recv_destruct} in order to destroy the underlying
- * port. This requirement may be elided with the
- * {@link MACH_RIGHT_RECV_UNGUARDED} flag.
- *
- * @result
- * A new port handle which refers to the receive right for the newly-created
- * port. The caller is responsible for disposing of this handle with
- * {@link mach_right_recv_destruct}.
- *
- * @discussion
- * The implementation will abort on any failure to allocate a new port object in
- * the kernel. Thus the caller may assert that a new, valid receive right is
- * always returned.
- */
-OS_EXPORT OS_WARN_RESULT
-mach_right_recv_t
-mach_right_recv_construct(mach_right_flags_t flags,
-               mach_right_send_t *_Nullable sr, uintptr_t ctx);
-
-/*!
- * @function mach_right_recv_destruct
- * Closes the port referred to by the given receive right.
- *
- * @param r
- * The receive right for the port to manipulate.
- *
- * @param s
- * A pointer to the send right to dispose of. If NULL is given, no attempt will
- * be made to clean up any send right associated with the port. If the name of
- * the given send right does not match the name of the given receive right, the
- * implementation's behavior is undefined.
- *
- * @param ctx
- * The context which guards the underlying port destruction. If the receive
- * right was created with {@link MACH_RIGHT_RECV_UNGUARDED}, this parameter is
- * ignored.
- *
- * @discussion
- * If a send right is passed, the implementation performs the moral equivalent
- * of
- *
- *     mach_right_recv_destruct(r, MACH_PORT_NULL, ctx);
- *     mach_right_send_release(s);
- *
- * except in a more efficient manner, requiring only one system call.
- *
- * The implementation will abort on any failure to dispose of the port. As such,
- * this routine should only be used on ports that are known to be under the
- * caller's complete control.
- */
-OS_EXPORT
-void
-mach_right_recv_destruct(mach_right_recv_t r, mach_right_send_t *_Nullable s,
-               uintptr_t ctx);
-
-/*!
- * @function mach_right_send_create
- * Creates a send right to the port referenced by the given receive right.
- *
- * @param r
- * The receive right for the port for which to create the send right.
- *
- * @result
- * The name of the new send right. The caller is responsible for disposing of
- * this send right with {@link mach_right_send_release}.
- *
- * This operation will increment the make-send count of the port referenced by
- * the given receive right.
- *
- * @discussion
- * The implementation will abort on any failure to create the send right. As
- * such, this routine should only be used on ports that are known to be under
- * the caller's complete control.
- */
-OS_EXPORT OS_WARN_RESULT
-mach_right_send_t
-mach_right_send_create(mach_right_recv_t r);
-
-/*!
- * @function mach_right_send_retain
- * Increments the user reference count for the given send right.
- *
- * @param s
- * The send right to manipulate.
- *
- * @result
- * If the reference count was successfully incremented, the given port name is
- * returned. If either MACH_PORT_NULL or MACH_PORT_DEAD are given, the given
- * value is returned. If the given send right became a dead name before or
- * during the attempt to retain the send right, MACH_PORT_DEAD is returned.
- *
- * If the implementation encounters any other failure condition, it will abort.
- */
-OS_EXPORT OS_WARN_RESULT
-mach_right_send_t
-mach_right_send_retain(mach_right_send_t s);
-
-/*!
- * @function mach_right_send_release
- * Decrements the user reference count for the given send right.
- *
- * @param s
- * The send right to manipulate.
- *
- * @discussion
- * If the given send right became a dead name before or during the attempt to
- * release it, the implementation will dispose of that dead name.
- *
- * If the implementation encounters any other failure condition, it will abort.
- */
-OS_EXPORT
-void
-mach_right_send_release(mach_right_send_t s);
-
-/*!
- * @function mach_right_send_once_create
- * Creates a send-once right from the given receive right.
- *
- * @param r
- * The receive right for the port for which to create the send-once right.
- *
- * @result
- * The newly-created send-once right.
- *
- * @discussion
- * The implementation will abort on any failure to allocate a new send-once
- * right, and therefore the caller should only provide a receive right which is
- * under its complete control. The caller may assert that a new, valid send-once
- * right is always returned.
- *
- * The returned send-once right will never share a name with the given receive
- * right. A send-once right must be consumed either by using it to send a
- * message or by consuming it with {@link mach_right_send_once_consume}.
- *
- * The returned right does not support retain/release semantics despite the
- * presence of "create" in the name.
- */
-OS_EXPORT OS_WARN_RESULT
-mach_right_send_once_t
-mach_right_send_once_create(mach_right_recv_t r);
-
-/*!
- * @function mach_right_send_once_consume
- * Consumes the given send-once right.
- *
- * @param so
- * The send-once right to manipulate.
- *
- * @discussion
- * If the given send-once right became a dead name before or during the attempt
- * to release it, the implementation will dispose of that dead name.
- *
- * If the implementation encounters any other failure condition, it will abort.
- *
- * This operation will cause a send-once notification to be delivered to the
- * port to which the send-once right refers unless the right is a dead name, in
- * which case there are no side effects.
- */
-OS_EXPORT
-void
-mach_right_send_once_consume(mach_right_send_once_t so);
-
-__END_DECLS;
-
 #endif // __MACH_RIGHT_H
 #endif // __MACH_RIGHT_H
diff --git a/libsyscall/mach/mach/mach_right_private.h b/libsyscall/mach/mach/mach_right_private.h
new file mode 100644 (file)
index 0000000..c8d9a61
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2018 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
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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@
+ */
+#ifndef __MACH_RIGHT_PRIVATE_H
+#define __MACH_RIGHT_PRIVATE_H
+
+#include <os/base.h>
+#include <mach/mach.h>
+#include <mach/port.h>
+#include <mach/mach_port.h>
+#include <sys/cdefs.h>
+#include <stdbool.h>
+
+__BEGIN_DECLS;
+
+/*!
+ * @typedef mach_right_recv_t
+ * A type representing the receive right to a Mach port.
+ */
+typedef struct _mach_right_recv {
+       mach_port_t mrr_name;
+} mach_right_recv_t;
+
+/*!
+ * @const MACH_RIGHT_RECV_NULL
+ * A convenience initializer for a receive right object.
+ */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define MACH_RIGHT_RECV_NULL ((mach_right_recv_t){MACH_PORT_NULL})
+#elif defined(__cplusplus) && __cplusplus >= 201103L
+#define MACH_RIGHT_RECV_NULL (mach_right_recv_t{MACH_PORT_NULL})
+#elif defined(__cplusplus)
+#define MACH_RIGHT_RECV_NULL \
+               (mach_right_recv_t((mach_right_recv_t){MACH_PORT_NULL}))
+#else
+#define MACH_RIGHT_RECV_NULL {MACH_PORT_NULL}
+#endif
+
+/*!
+ * @typedef mach_right_send_t
+ * A type representing a send right to a Mach port.
+ */
+typedef struct _mach_right_send {
+       mach_port_t mrs_name;
+} mach_right_send_t;
+
+/*!
+ * @const MACH_RIGHT_SEND_NULL
+ * A convenience initializer for a send right object.
+ */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define MACH_RIGHT_SEND_NULL ((mach_right_send_t){MACH_PORT_NULL})
+#elif defined(__cplusplus) && __cplusplus >= 201103L
+#define MACH_RIGHT_SEND_NULL (mach_right_send_t{MACH_PORT_NULL})
+#elif defined(__cplusplus)
+#define MACH_RIGHT_SEND_NULL \
+               (mach_right_send_t((mach_right_send_t){MACH_PORT_NULL}))
+#else
+#define MACH_RIGHT_SEND_NULL {MACH_PORT_NULL}
+#endif
+
+/*!
+ * @typedef mach_right_send_once_t
+ * A type representing a send-once right to a Mach port.
+ */
+typedef struct _mach_right_send_once {
+       mach_port_t mrso_name;
+} mach_right_send_once_t;
+
+/*!
+ * @const MACH_RIGHT_SEND_ONCE_NULL
+ * A convenience initializer for a send-once right object.
+ */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define MACH_RIGHT_SEND_ONCE_NULL ((mach_right_send_once_t){MACH_PORT_NULL})
+#elif defined(__cplusplus) && __cplusplus >= 201103L
+#define MACH_RIGHT_SEND_ONCE_NULL (mach_right_send_once_t{MACH_PORT_NULL})
+#elif defined(__cplusplus)
+#define MACH_RIGHT_SEND_ONCE_NULL \
+               (mach_right_send_once_t((mach_right_send_once_t){MACH_PORT_NULL}))
+#else
+#define MACH_RIGHT_SEND_ONCE_NULL {MACH_PORT_NULL}
+#endif
+
+/*!
+ * @function mach_right_recv
+ * Wraps a port name as a receive right object.
+ *
+ * @param pn
+ * The port name. If this name is valid but does not represent a receive right,
+ * the behavior of mach_right_recv_* implementations is undefined.
+ *
+ * @result
+ * A new receive right object.
+ */
+OS_ALWAYS_INLINE OS_WARN_RESULT
+static inline mach_right_recv_t
+mach_right_recv(mach_port_name_t pn)
+{
+       mach_right_recv_t mrr = {pn};
+       return mrr;
+}
+
+/*!
+ * @function mach_right_send
+ * Wraps a port name as a send right object.
+ *
+ * @param pn
+ * The port name. If this name is valid but does not represent a send right, the
+ * behavior of mach_right_send_* implementations is undefined.
+ *
+ * @result
+ * A new send right object.
+ */
+OS_ALWAYS_INLINE OS_WARN_RESULT
+static inline mach_right_send_t
+mach_right_send(mach_port_name_t pn)
+{
+       mach_right_send_t mrs = {pn};
+       return mrs;
+}
+
+/*!
+ * @function mach_right_send_valid
+ * Checks if the given send right object is valid.
+ *
+ * @param mrs
+ * The send right object to check.
+ *
+ * @result
+ * A Boolean indicating whether the right is valid.
+ */
+OS_ALWAYS_INLINE OS_WARN_RESULT
+static inline bool
+mach_right_send_valid(mach_right_send_t mrs)
+{
+       return MACH_PORT_VALID(mrs.mrs_name);
+}
+
+/*!
+ * @function mach_right_send_once
+ * Wraps a port name as a send-once right object.
+ *
+ * @param pn
+ * The port name. If this name is valid but does not represent a send-once
+ * right, the behavior of mach_right_send_once_* implementations is undefined.
+ *
+ * @result
+ * A new send-once right object.
+ */
+OS_ALWAYS_INLINE OS_WARN_RESULT
+static inline mach_right_send_once_t
+mach_right_send_once(mach_port_name_t pn)
+{
+       mach_right_send_once_t mrso = {pn};
+       return mrso;
+}
+
+/*!
+ * @function mach_right_send_once_valid
+ * Checks if the given send-once right object is valid.
+ *
+ * @param mrso
+ * The send-once right object to check.
+ *
+ * @result
+ * A Boolean indicating whether the right is valid.
+ */
+OS_ALWAYS_INLINE OS_WARN_RESULT
+static inline bool
+mach_right_send_once_valid(mach_right_send_once_t mrso)
+{
+       return MACH_PORT_VALID(mrso.mrso_name);
+}
+
+/*!
+ * @typedef mach_right_flags_t
+ * Flags influencing the behavior of a constructed Mach port.
+ *
+ * @const MACH_RIGHT_RECV_INIT
+ * No flags set. This value is suitable for initialization purposes.
+ *
+ * @const MACH_RIGHT_RECV_UNGUARDED
+ * The given context should not serve as a guard for the underlying port's
+ * destruction.
+ */
+OS_ENUM(mach_right_flags, uint64_t,
+       MACH_RIGHT_RECV_FLAG_INIT = 0,
+       MACH_RIGHT_RECV_FLAG_UNGUARDED = (1 << 0),
+);
+
+/*!
+ * @function mach_right_recv_construct
+ * Allocates a new Mach port and returns the receive right to the caller.
+ *
+ * @param flags
+ * Flags to influence the behavior of the new port.
+ *
+ * @param sr
+ * If non-NULL, will be filled in with the name of a send right which
+ * corresponds to the new port. The caller is responsible for disposing of this
+ * send right with {@link mach_right_send_release}.
+ *
+ * @param ctx
+ * Context to be associated with the new port. By default, this context must be
+ * passed to {@link mach_right_recv_destruct} in order to destroy the underlying
+ * port. This requirement may be elided with the
+ * {@link MACH_RIGHT_RECV_UNGUARDED} flag.
+ *
+ * @result
+ * A new port handle which refers to the receive right for the newly-created
+ * port. The caller is responsible for disposing of this handle with
+ * {@link mach_right_recv_destruct}.
+ *
+ * @discussion
+ * The implementation will abort on any failure to allocate a new port object in
+ * the kernel. Thus the caller may assert that a new, valid receive right is
+ * always returned.
+ */
+OS_EXPORT OS_WARN_RESULT
+mach_right_recv_t
+mach_right_recv_construct(mach_right_flags_t flags,
+               mach_right_send_t *_Nullable sr, uintptr_t ctx);
+
+/*!
+ * @function mach_right_recv_destruct
+ * Closes the port referred to by the given receive right.
+ *
+ * @param r
+ * The receive right for the port to manipulate.
+ *
+ * @param s
+ * A pointer to the send right to dispose of. If NULL is given, no attempt will
+ * be made to clean up any send right associated with the port. If the name of
+ * the given send right does not match the name of the given receive right, the
+ * implementation's behavior is undefined.
+ *
+ * @param ctx
+ * The context which guards the underlying port destruction. If the receive
+ * right was created with {@link MACH_RIGHT_RECV_UNGUARDED}, this parameter is
+ * ignored.
+ *
+ * @discussion
+ * If a send right is passed, the implementation performs the moral equivalent
+ * of
+ *
+ *     mach_right_recv_destruct(r, MACH_PORT_NULL, ctx);
+ *     mach_right_send_release(s);
+ *
+ * except in a more efficient manner, requiring only one system call.
+ *
+ * The implementation will abort on any failure to dispose of the port. As such,
+ * this routine should only be used on ports that are known to be under the
+ * caller's complete control.
+ */
+OS_EXPORT
+void
+mach_right_recv_destruct(mach_right_recv_t r, mach_right_send_t *_Nullable s,
+               uintptr_t ctx);
+
+/*!
+ * @function mach_right_send_create
+ * Creates a send right to the port referenced by the given receive right.
+ *
+ * @param r
+ * The receive right for the port for which to create the send right.
+ *
+ * @result
+ * The name of the new send right. The caller is responsible for disposing of
+ * this send right with {@link mach_right_send_release}.
+ *
+ * This operation will increment the make-send count of the port referenced by
+ * the given receive right.
+ *
+ * @discussion
+ * The implementation will abort on any failure to create the send right. As
+ * such, this routine should only be used on ports that are known to be under
+ * the caller's complete control.
+ */
+OS_EXPORT OS_WARN_RESULT
+mach_right_send_t
+mach_right_send_create(mach_right_recv_t r);
+
+/*!
+ * @function mach_right_send_retain
+ * Increments the user reference count for the given send right.
+ *
+ * @param s
+ * The send right to manipulate.
+ *
+ * @result
+ * If the reference count was successfully incremented, the given port name is
+ * returned. If either MACH_PORT_NULL or MACH_PORT_DEAD are given, the given
+ * value is returned. If the given send right became a dead name before or
+ * during the attempt to retain the send right, MACH_PORT_DEAD is returned.
+ *
+ * If the implementation encounters any other failure condition, it will abort.
+ */
+OS_EXPORT OS_WARN_RESULT
+mach_right_send_t
+mach_right_send_retain(mach_right_send_t s);
+
+/*!
+ * @function mach_right_send_release
+ * Decrements the user reference count for the given send right.
+ *
+ * @param s
+ * The send right to manipulate.
+ *
+ * @discussion
+ * If the given send right became a dead name before or during the attempt to
+ * release it, the implementation will dispose of that dead name.
+ *
+ * If the implementation encounters any other failure condition, it will abort.
+ */
+OS_EXPORT
+void
+mach_right_send_release(mach_right_send_t s);
+
+/*!
+ * @function mach_right_send_once_create
+ * Creates a send-once right from the given receive right.
+ *
+ * @param r
+ * The receive right for the port for which to create the send-once right.
+ *
+ * @result
+ * The newly-created send-once right.
+ *
+ * @discussion
+ * The implementation will abort on any failure to allocate a new send-once
+ * right, and therefore the caller should only provide a receive right which is
+ * under its complete control. The caller may assert that a new, valid send-once
+ * right is always returned.
+ *
+ * The returned send-once right will never share a name with the given receive
+ * right. A send-once right must be consumed either by using it to send a
+ * message or by consuming it with {@link mach_right_send_once_consume}.
+ *
+ * The returned right does not support retain/release semantics despite the
+ * presence of "create" in the name.
+ */
+OS_EXPORT OS_WARN_RESULT
+mach_right_send_once_t
+mach_right_send_once_create(mach_right_recv_t r);
+
+/*!
+ * @function mach_right_send_once_consume
+ * Consumes the given send-once right.
+ *
+ * @param so
+ * The send-once right to manipulate.
+ *
+ * @discussion
+ * If the given send-once right became a dead name before or during the attempt
+ * to release it, the implementation will dispose of that dead name.
+ *
+ * If the implementation encounters any other failure condition, it will abort.
+ *
+ * This operation will cause a send-once notification to be delivered to the
+ * port to which the send-once right refers unless the right is a dead name, in
+ * which case there are no side effects.
+ */
+OS_EXPORT
+void
+mach_right_send_once_consume(mach_right_send_once_t so);
+
+__END_DECLS;
+
+#endif // __MACH_RIGHT_PRIVATE_H
index cdd598aee7b745712463017cde103c73738d0602..40bbcbf74460e0e4b8317b500bc2402273416acd 100755 (executable)
@@ -122,6 +122,7 @@ MACH_HDRS="mach.h
        thread_state.h"
 
 MACH_PRIVATE_HDRS="port_descriptions.h
        thread_state.h"
 
 MACH_PRIVATE_HDRS="port_descriptions.h
+       mach_right_private.h
        mach_sync_ipc.h"
 
 MIG_FILTERS="watchos_prohibited_mig.txt tvos_prohibited_mig.txt"
        mach_sync_ipc.h"
 
 MIG_FILTERS="watchos_prohibited_mig.txt tvos_prohibited_mig.txt"
index d69c2d270d80050b1bfd22842b300dea918516a8..660df3676bbade780dddf6d660c0654c4517c4a2 100644 (file)
@@ -941,13 +941,19 @@ kpc_reload_counter(uint32_t ctr)
 {
        assert(ctr < (kpc_configurable_count() + kpc_fixed_count()));
 
 {
        assert(ctr < (kpc_configurable_count() + kpc_fixed_count()));
 
-       /* don't reload counters reserved for power management */
-       if (!kpc_controls_counter(ctr))
-               return 0ULL;
-
        uint64_t old = read_counter(ctr);
        uint64_t old = read_counter(ctr);
-       write_counter(ctr, FIXED_RELOAD(ctr));
-       return old & KPC_ARM64_COUNTER_MASK;
+
+       if (kpc_controls_counter(ctr)) {
+               write_counter(ctr, FIXED_RELOAD(ctr));
+               return old & KPC_ARM64_COUNTER_MASK;
+       } else {
+               /*
+                * Unset the overflow bit to clear the condition that drives
+                * PMIs.  The power manager is not interested in handling PMIs.
+                */
+               write_counter(ctr, old & KPC_ARM64_COUNTER_MASK);
+               return 0;
+       }
 }
 
 static uint32_t kpc_reload_sync;
 }
 
 static uint32_t kpc_reload_sync;
index 7955cf45de23d3250d65dab8a6031ad813de394f..b28449560d3c6c23a7ab4ff0f8e1f964fb5eca5e 100644 (file)
@@ -4826,8 +4826,7 @@ ipc_kmsg_add_trailer(ipc_kmsg_t kmsg, ipc_space_t space __unused,
                goto done;
        }
 
                goto done;
        }
 
-       if (MACH_RCV_TRAILER_ELEMENTS(option) >= 
-                       MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV)){
+       if (GET_RCV_ELEMENTS(option) >= MACH_RCV_TRAILER_AV) {
                trailer->msgh_ad = 0;
        }
 
                trailer->msgh_ad = 0;
        }
 
index 05fd050bbb8d743fe69a3fefc990640c3b5c9917..d251ab95cc918134719e08e1c3f5b76fde017838 100644 (file)
@@ -287,6 +287,12 @@ _kernelrpc_mach_port_get_attributes_trap(struct _kernelrpc_mach_port_get_attribu
        const mach_msg_type_number_t max_count = (sizeof(MACH_PORT_INFO_OUT)/sizeof(MACH_PORT_INFO_OUT[0]));
        typeof(MACH_PORT_INFO_OUT[0]) info[max_count];
 
        const mach_msg_type_number_t max_count = (sizeof(MACH_PORT_INFO_OUT)/sizeof(MACH_PORT_INFO_OUT[0]));
        typeof(MACH_PORT_INFO_OUT[0]) info[max_count];
 
+       /*
+        * zero out our stack buffer because not all flavors of
+        * port_get_attributes initialize the whole struct
+        */
+       bzero(info, sizeof(MACH_PORT_INFO_OUT));
+
        if (copyin(CAST_USER_ADDR_T(args->count), &count, sizeof(count))) {
                rv = MACH_SEND_INVALID_DATA;
                goto done;
        if (copyin(CAST_USER_ADDR_T(args->count), &count, sizeof(count))) {
                rv = MACH_SEND_INVALID_DATA;
                goto done;
index 19a9c0a97efba4132a90ea76e38e8159e0923a05..ca296055974d3aea3c6a7bb06c7db274239a966e 100644 (file)
@@ -131,13 +131,18 @@ void ipc_host_init(void)
 
        /* the rest of the special ports will be set up later */
 
 
        /* the rest of the special ports will be set up later */
 
+       bzero(&realhost.exc_actions[0], sizeof(realhost.exc_actions[0]));
        for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
                        realhost.exc_actions[i].port = IP_NULL;
                        /* The mac framework is not yet initialized, so we defer
                         * initializing the labels to later, when they are set
                         * for the first time. */
                        realhost.exc_actions[i].label = NULL;
        for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
                        realhost.exc_actions[i].port = IP_NULL;
                        /* The mac framework is not yet initialized, so we defer
                         * initializing the labels to later, when they are set
                         * for the first time. */
                        realhost.exc_actions[i].label = NULL;
-               }/* for */
+                       /* initialize the entire exception action struct */
+                       realhost.exc_actions[i].behavior = 0;
+                       realhost.exc_actions[i].flavor = 0;
+                       realhost.exc_actions[i].privileged = FALSE;
+       }/* for */
 
        /*
         *      Set up ipc for default processor set.
 
        /*
         *      Set up ipc for default processor set.
index 6fcef9f174728ca8ce224b30d4178e34db68d11f..eefc9e01362f7f6b56b9b2d137d0f23f1accdfbd 100644 (file)
@@ -163,16 +163,23 @@ ipc_task_init(
        task->itk_space = space;
 
 #if CONFIG_MACF
        task->itk_space = space;
 
 #if CONFIG_MACF
+       task->exc_actions[0].label = NULL;
        for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
                mac_exc_associate_action_label(&task->exc_actions[i], mac_exc_create_label());
        }
 #endif
        for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
                mac_exc_associate_action_label(&task->exc_actions[i], mac_exc_create_label());
        }
 #endif
-       
+
+       /* always zero-out the first (unused) array element */
+
+       bzero(&task->exc_actions[0], sizeof(task->exc_actions[0]));
        if (parent == TASK_NULL) {
                ipc_port_t port;
 
                for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
                        task->exc_actions[i].port = IP_NULL;
        if (parent == TASK_NULL) {
                ipc_port_t port;
 
                for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
                        task->exc_actions[i].port = IP_NULL;
+                       task->exc_actions[i].flavor = 0;
+                       task->exc_actions[i].behavior = 0;
+                       task->exc_actions[i].privileged = FALSE;
                }/* for */
                
                kr = host_get_host_port(host_priv_self(), &port);
                }/* for */
                
                kr = host_get_host_port(host_priv_self(), &port);
index c80e30d300b2be3a73867afd091bf97153521d74..792daf7bc24c62b8e285ffdeec2db4431ed9ea9e 100644 (file)
@@ -6003,15 +6003,18 @@ task_set_mach_voucher(
 
 kern_return_t
 task_swap_mach_voucher(
 
 kern_return_t
 task_swap_mach_voucher(
-       task_t                  task,
-       ipc_voucher_t           new_voucher,
-       ipc_voucher_t           *in_out_old_voucher)
+       __unused task_t         task,
+       __unused ipc_voucher_t  new_voucher,
+       ipc_voucher_t          *in_out_old_voucher)
 {
 {
-       if (TASK_NULL == task)
-               return KERN_INVALID_TASK;
-
-       *in_out_old_voucher = new_voucher;
-       return KERN_SUCCESS;
+       /*
+        * Currently this function is only called from a MIG generated
+        * routine which doesn't release the reference on the voucher
+        * addressed by in_out_old_voucher. To avoid leaking this reference,
+        * a call to release it has been added here.
+        */
+       ipc_voucher_release(*in_out_old_voucher);
+       return KERN_NOT_SUPPORTED;
 }
 
 void task_set_gpu_denied(task_t task, boolean_t denied)
 }
 
 void task_set_gpu_denied(task_t task, boolean_t denied)
index ad60f1693598496387fd7198ee02cd27e96ad033..04fbe0ccc1057551ab1fdb89dd879e7f786114ee 100644 (file)
@@ -11197,6 +11197,8 @@ vm_map_copyin_internal(
                    (src_object == VM_OBJECT_NULL ||
                     (src_object->internal &&
                      src_object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC &&
                    (src_object == VM_OBJECT_NULL ||
                     (src_object->internal &&
                      src_object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC &&
+                     src_entry->vme_start <= src_addr &&
+                     src_entry->vme_end >= src_end &&
                      !map_share))) {
                        /*
                         * If we are destroying the source, and the object
                      !map_share))) {
                        /*
                         * If we are destroying the source, and the object
@@ -11205,6 +11207,12 @@ vm_map_copyin_internal(
                         * copy-on-write only if the source is.
                         * We make another reference to the object, because
                         * destroying the source entry will deallocate it.
                         * copy-on-write only if the source is.
                         * We make another reference to the object, because
                         * destroying the source entry will deallocate it.
+                        *
+                        * This memory transfer has to be atomic (to prevent
+                        * the VM object from being shared or copied while
+                        * it's being moved here), so we can only do this
+                        * if we won't have to unlock the VM map, i.e. the
+                        * entire range must be covered by this map entry.
                         */
                        vm_object_reference(src_object);
 
                         */
                        vm_object_reference(src_object);