From b226f5e54a60dc81db17b1260381d7dbfea3cdf1 Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 17 Jun 2019 20:57:32 +0000 Subject: [PATCH] xnu-4903.241.1.tar.gz --- bsd/kern/kern_event.c | 4 + bsd/kern/ubc_subr.c | 2 +- bsd/net/if_ports_used.c | 56 ++- bsd/netinet/flow_divert.c | 26 +- bsd/netkey/key.c | 16 +- bsd/security/audit/audit.h | 4 + bsd/security/audit/audit_arg.c | 25 ++ bsd/security/audit/audit_bsm.c | 8 + bsd/vfs/vfs_syscalls.c | 31 +- .../Libsyscall.xcodeproj/project.pbxproj | 8 +- libsyscall/mach/mach/mach_right.h | 361 +--------------- libsyscall/mach/mach/mach_right_private.h | 394 ++++++++++++++++++ libsyscall/xcodescripts/mach_install_mig.sh | 1 + osfmk/arm64/kpc.c | 18 +- osfmk/ipc/ipc_kmsg.c | 3 +- osfmk/ipc/mach_kernelrpc.c | 6 + osfmk/kern/ipc_host.c | 7 +- osfmk/kern/ipc_tt.c | 9 +- osfmk/kern/task.c | 19 +- osfmk/vm/vm_map.c | 8 + 20 files changed, 603 insertions(+), 403 deletions(-) create mode 100644 libsyscall/mach/mach/mach_right_private.h diff --git a/bsd/kern/kern_event.c b/bsd/kern/kern_event.c index df25f3112..ecffc8db7 100644 --- a/bsd/kern/kern_event.c +++ b/bsd/kern/kern_event.c @@ -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. */ +#if 0 // 45129862 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; } @@ -6062,9 +6064,11 @@ kqueue_threadreq_modify(struct kqueue *kq, struct kqrequest *kqr, kq_index_t qos 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; } +#endif workq_kern_threadreq_modify(kq->kq_p, kqr, qos, flags); } diff --git a/bsd/kern/ubc_subr.c b/bsd/kern/ubc_subr.c index 6f09debf7..abf7e6f53 100644 --- a/bsd/kern/ubc_subr.c +++ b/bsd/kern/ubc_subr.c @@ -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 */ - 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); diff --git a/bsd/net/if_ports_used.c b/bsd/net/if_ports_used.c index 643df3b2d..c78a690a1 100644 --- a/bsd/net/if_ports_used.c +++ b/bsd/net/if_ports_used.c @@ -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 uuid_string_t test_wakeuuid_str; #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", ""); +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", ""); @@ -209,12 +215,17 @@ net_port_entry_list_clear(void) } 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 (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 { @@ -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 */ - return (get_test_wake_uuid(NULL) || IOPMCopySleepWakeUUIDKey(NULL, 0)); + return (get_test_wake_uuid(NULL, 0) || IOPMCopySleepWakeUUIDKey(NULL, 0)); } 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_string_t wakeuuid_str; + + uuid_clear(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 { - uuid_string_t 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); + test_wakeuuid_str[0] = 0; } 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); } +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 diff --git a/bsd/netinet/flow_divert.c b/bsd/netinet/flow_divert.c index b6d668440..c3bc7930c 100644 --- a/bsd/netinet/flow_divert.c +++ b/bsd/netinet/flow_divert.c @@ -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) { - 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); } diff --git a/bsd/netkey/key.c b/bsd/netkey/key.c index f373441d0..1e4b99811 100644 --- a/bsd/netkey/key.c +++ b/bsd/netkey/key.c @@ -7898,6 +7898,7 @@ static int 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; @@ -7907,8 +7908,11 @@ key_getsastatbyspi (struct sastat *stat_arg, 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++; @@ -9863,6 +9867,15 @@ key_validate_ext( 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; } @@ -10168,6 +10181,7 @@ key_getsastat (struct socket *so, 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; diff --git a/bsd/security/audit/audit.h b/bsd/security/audit/audit.h index 6a60b36c6..08766aa00 100644 --- a/bsd/security/audit/audit.h +++ b/bsd/security/audit/audit.h @@ -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); +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, @@ -317,6 +319,8 @@ extern au_event_t sys_au_event[]; #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. diff --git a/bsd/security/audit/audit_arg.c b/bsd/security/audit/audit_arg.c index 950d1f49f..919b3dc68 100644 --- a/bsd/security/audit/audit_arg.c +++ b/bsd/security/audit/audit_arg.c @@ -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. diff --git a/bsd/security/audit/audit_bsm.c b/bsd/security/audit/audit_bsm.c index 60c8dbf14..876833e4b 100644 --- a/bsd/security/audit/audit_bsm.c +++ b/bsd/security/audit/audit_bsm.c @@ -227,6 +227,13 @@ kau_free(struct au_record *rec) } \ } 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); \ @@ -1188,6 +1195,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau) case AUE_RENAME: UPATH1_VNODE1_TOKENS; UPATH2_TOKENS; + KPATH2_TOKENS; break; case AUE_MKDIR_EXTENDED: diff --git a/bsd/vfs/vfs_syscalls.c b/bsd/vfs/vfs_syscalls.c index 767d352c6..4e24c8489 100644 --- a/bsd/vfs/vfs_syscalls.c +++ b/bsd/vfs/vfs_syscalls.c @@ -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 - int need_event, has_listeners; + int need_event, has_listeners, need_kpath2; 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(); - 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; @@ -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); + AUDIT_ARG(kpath, target_path, ARG_KPATH2); + 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 need_kpath2; + int has_listeners; 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 */ - 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) { @@ -7449,7 +7469,9 @@ continue_lookup: } 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) { @@ -7459,6 +7481,9 @@ continue_lookup: } 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) { /* diff --git a/libsyscall/Libsyscall.xcodeproj/project.pbxproj b/libsyscall/Libsyscall.xcodeproj/project.pbxproj index e138202c1..c5f769437 100644 --- a/libsyscall/Libsyscall.xcodeproj/project.pbxproj +++ b/libsyscall/Libsyscall.xcodeproj/project.pbxproj @@ -252,6 +252,8 @@ 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, ); }; }; @@ -513,7 +515,7 @@ 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 = ""; }; 435F3CA91B06B7BA005ED9EF /* work_interval.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = work_interval.c; sourceTree = ""; }; 467DAFD3157E8AF200CE68F0 /* guarded_open_np.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = guarded_open_np.c; sourceTree = ""; }; - 4BCDD8AE20741A4700FA37A3 /* mach_right.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mach_right.h; sourceTree = ""; }; + 4BCDD8AE20741A4700FA37A3 /* mach_right.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_right.h; sourceTree = ""; }; 4BCDD8B120741C2F00FA37A3 /* mach_right.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mach_right.c; sourceTree = ""; }; 4BDD5F1B1891AB2F004BF300 /* mach_approximate_time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach_approximate_time.c; sourceTree = ""; }; 4BDD5F1C1891AB2F004BF300 /* mach_approximate_time.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = mach_approximate_time.s; sourceTree = ""; }; @@ -621,6 +623,7 @@ E214BDC71C2E34E200CEE8A3 /* clonefile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = clonefile.c; sourceTree = ""; }; E2A0F3331C3B17D100A11F8A /* fs_snapshot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fs_snapshot.c; sourceTree = ""; }; E4216C301822D404006F2632 /* mach_voucher.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = mach_voucher.defs; sourceTree = ""; }; + E4512B8B21AFDF1500673F73 /* mach_right_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_right_private.h; sourceTree = ""; }; E453AF341700FD3C00F2C94C /* getiopolicy_np.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = getiopolicy_np.c; sourceTree = ""; }; E4D45C2116F856900002AF25 /* __commpage_gettimeofday.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = __commpage_gettimeofday.c; sourceTree = ""; }; E4D45C2316F856900002AF25 /* mach_absolute_time.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = mach_absolute_time.s; sourceTree = ""; }; @@ -1023,6 +1026,7 @@ 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 */, @@ -1089,6 +1093,7 @@ 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 */, @@ -1151,6 +1156,7 @@ 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 */, diff --git a/libsyscall/mach/mach/mach_right.h b/libsyscall/mach/mach/mach_right.h index 2a7522ee8..8f449e5f9 100644 --- a/libsyscall/mach/mach/mach_right.h +++ b/libsyscall/mach/mach/mach_right.h @@ -28,367 +28,10 @@ #ifndef __MACH_RIGHT_H #define __MACH_RIGHT_H -#include -#include -#include -#include #include -#include -__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() +#include #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 diff --git a/libsyscall/mach/mach/mach_right_private.h b/libsyscall/mach/mach/mach_right_private.h new file mode 100644 index 000000000..c8d9a6195 --- /dev/null +++ b/libsyscall/mach/mach/mach_right_private.h @@ -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 +#include +#include +#include +#include +#include + +__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 diff --git a/libsyscall/xcodescripts/mach_install_mig.sh b/libsyscall/xcodescripts/mach_install_mig.sh index cdd598aee..40bbcbf74 100755 --- a/libsyscall/xcodescripts/mach_install_mig.sh +++ b/libsyscall/xcodescripts/mach_install_mig.sh @@ -122,6 +122,7 @@ MACH_HDRS="mach.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" diff --git a/osfmk/arm64/kpc.c b/osfmk/arm64/kpc.c index d69c2d270..660df3676 100644 --- a/osfmk/arm64/kpc.c +++ b/osfmk/arm64/kpc.c @@ -941,13 +941,19 @@ kpc_reload_counter(uint32_t ctr) { 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); - 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; diff --git a/osfmk/ipc/ipc_kmsg.c b/osfmk/ipc/ipc_kmsg.c index 7955cf45d..b28449560 100644 --- a/osfmk/ipc/ipc_kmsg.c +++ b/osfmk/ipc/ipc_kmsg.c @@ -4826,8 +4826,7 @@ ipc_kmsg_add_trailer(ipc_kmsg_t kmsg, ipc_space_t space __unused, 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; } diff --git a/osfmk/ipc/mach_kernelrpc.c b/osfmk/ipc/mach_kernelrpc.c index 05fd050bb..d251ab95c 100644 --- a/osfmk/ipc/mach_kernelrpc.c +++ b/osfmk/ipc/mach_kernelrpc.c @@ -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]; + /* + * 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; diff --git a/osfmk/kern/ipc_host.c b/osfmk/kern/ipc_host.c index 19a9c0a97..ca2960559 100644 --- a/osfmk/kern/ipc_host.c +++ b/osfmk/kern/ipc_host.c @@ -131,13 +131,18 @@ void ipc_host_init(void) /* 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 */ + /* 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. diff --git a/osfmk/kern/ipc_tt.c b/osfmk/kern/ipc_tt.c index 6fcef9f17..eefc9e013 100644 --- a/osfmk/kern/ipc_tt.c +++ b/osfmk/kern/ipc_tt.c @@ -163,16 +163,23 @@ ipc_task_init( 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 - + + /* 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; + 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); diff --git a/osfmk/kern/task.c b/osfmk/kern/task.c index c80e30d30..792daf7bc 100644 --- a/osfmk/kern/task.c +++ b/osfmk/kern/task.c @@ -6003,15 +6003,18 @@ task_set_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) diff --git a/osfmk/vm/vm_map.c b/osfmk/vm/vm_map.c index ad60f1693..04fbe0ccc 100644 --- a/osfmk/vm/vm_map.c +++ b/osfmk/vm/vm_map.c @@ -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_entry->vme_start <= src_addr && + src_entry->vme_end >= src_end && !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. + * + * 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); -- 2.45.2