From 527f99514973766e9c0382a4d8550dfb00f54939 Mon Sep 17 00:00:00 2001 From: Apple Date: Sun, 4 Feb 2018 14:01:56 +0000 Subject: [PATCH] xnu-4570.41.2.tar.gz --- bsd/kern/kern_credential.c | 6 +- bsd/kern/kern_cs.c | 38 ++++-- bsd/kern/kern_exec.c | 120 +++++++----------- bsd/kern/kern_exit.c | 4 +- bsd/kern/kern_mman.c | 2 +- bsd/kern/kern_ntptime.c | 12 +- bsd/kern/kern_persona.c | 12 +- bsd/kern/kern_proc.c | 87 ++++++++++++- bsd/kern/kern_resource.c | 2 +- bsd/kern/kern_sig.c | 7 +- bsd/kern/mach_loader.c | 45 +++---- bsd/kern/policy_check.c | 4 +- bsd/kern/sys_coalition.c | 2 +- bsd/kern/sys_persona.c | 4 +- bsd/kern/uipc_socket.c | 2 +- bsd/kern/uipc_syscalls.c | 2 +- bsd/net/if.c | 16 ++- bsd/net/if_llreach.c | 2 +- bsd/net/necp_client.c | 6 +- bsd/net/pf_ioctl.c | 2 +- bsd/net/rtsock.c | 24 ++-- bsd/netinet/in_mcast.c | 6 +- bsd/netinet/in_tclass.c | 4 +- bsd/netinet/ip_fw2.c | 6 +- bsd/netinet/mptcp_usrreq.c | 2 +- bsd/netinet/tcp_usrreq.c | 7 +- bsd/netinet/udp_usrreq.c | 3 +- bsd/netinet6/in6_mcast.c | 4 +- bsd/nfs/nfs_subs.c | 4 + bsd/nfs/nfs_vfsops.c | 4 +- bsd/sys/persona.h | 4 +- bsd/sys/proc.h | 4 + bsd/vfs/vfs_cluster.c | 2 +- bsd/vfs/vfs_subr.c | 10 +- bsd/vfs/vfs_syscalls.c | 4 +- config/MACFramework.exports | 2 + config/MASTER | 5 + config/MASTER.x86_64 | 2 +- config/MasterVersion | 2 +- iokit/IOKit/IOUserClient.h | 5 +- iokit/Kernel/IOUserClient.cpp | 22 +++- libsyscall/wrappers/spawn/posix_spawn.c | 2 +- osfmk/kern/clock.c | 2 +- osfmk/kern/clock_oldops.c | 2 +- osfmk/kern/task.c | 19 +++ osfmk/kern/task.h | 7 + security/mac_base.c | 6 + security/mac_framework.h | 8 +- security/mac_policy.h | 25 +++- security/mac_vfs.c | 19 +++ .../tests/darwintests/socket_bind_35243417.c | 116 +++++++++++++++++ tools/tests/personas/persona_mgr.c | 8 +- 52 files changed, 506 insertions(+), 209 deletions(-) create mode 100644 tools/tests/darwintests/socket_bind_35243417.c diff --git a/bsd/kern/kern_credential.c b/bsd/kern/kern_credential.c index bac6af26f..c433affea 100644 --- a/bsd/kern/kern_credential.c +++ b/bsd/kern/kern_credential.c @@ -593,7 +593,7 @@ identitysvc(__unused struct proc *p, struct identitysvc_args *uap, __unused int3 int opcode = uap->opcode; user_addr_t message = uap->message; struct kauth_resolver_work *workp; - struct kauth_cache_sizes sz_arg; + struct kauth_cache_sizes sz_arg = {}; int error; pid_t new_id; @@ -5657,7 +5657,7 @@ sysctl_dump_creds( __unused struct sysctl_oid *oidp, __unused void *arg1, __unus return 0; } - MALLOC( cred_listp, debug_ucred *, req->oldlen, M_TEMP, M_WAITOK ); + MALLOC( cred_listp, debug_ucred *, req->oldlen, M_TEMP, M_WAITOK | M_ZERO); if ( cred_listp == NULL ) { return (ENOMEM); } @@ -5756,7 +5756,7 @@ sysctl_dump_cred_backtraces( __unused struct sysctl_oid *oidp, __unused void *ar return (ENOMEM); } - MALLOC( bt_bufp, cred_debug_buffer *, req->oldlen, M_TEMP, M_WAITOK ); + MALLOC( bt_bufp, cred_debug_buffer *, req->oldlen, M_TEMP, M_WAITOK | M_ZERO); if ( bt_bufp == NULL ) { return (ENOMEM); } diff --git a/bsd/kern/kern_cs.c b/bsd/kern/kern_cs.c index 7a3d22baf..0bf850955 100644 --- a/bsd/kern/kern_cs.c +++ b/bsd/kern/kern_cs.c @@ -325,7 +325,7 @@ cs_system_require_lv(void) /* * Function: csblob_get_base_offset * - * Description: This function returns the base offset into the Mach-O binary + * Description: This function returns the base offset into the (possibly universal) binary * for a given blob. */ @@ -413,11 +413,15 @@ csproc_get_blob(struct proc *p) if (NULL == p->p_textvp) return NULL; + if ((p->p_csflags & CS_SIGNED) == 0) { + return NULL; + } + return ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff); } /* - * Function: csproc_get_blob + * Function: csvnode_get_blob * * Description: This function returns the cs_blob * for the vnode vp @@ -579,7 +583,9 @@ csproc_get_platform_binary(struct proc *p) int csproc_get_platform_path(struct proc *p) { - struct cs_blob *csblob = csproc_get_blob(p); + struct cs_blob *csblob; + + csblob = csproc_get_blob(p); return (csblob == NULL) ? 0 : csblob->csb_platform_path; } @@ -858,6 +864,10 @@ cs_entitlements_blob_get(proc_t p, void **out_start, size_t *out_length) *out_start = NULL; *out_length = 0; + if ((p->p_csflags & CS_SIGNED) == 0) { + return 0; + } + if (NULL == p->p_textvp) return EINVAL; @@ -878,6 +888,10 @@ cs_identity_get(proc_t p) { struct cs_blob *csblob; + if ((p->p_csflags & CS_SIGNED) == 0) { + return NULL; + } + if (NULL == p->p_textvp) return NULL; @@ -887,15 +901,13 @@ cs_identity_get(proc_t p) return csblob_get_identity(csblob); } - -/* Retrieve the codesign blob for a process. - * Returns: - * EINVAL no text vnode associated with the process - * 0 no error occurred +/* + * DO NOT USE THIS FUNCTION! + * Use the properly guarded csproc_get_blob instead. * - * On success, out_start and out_length will point to the - * cms blob if found; or will be set to NULL/zero - * if there were no blob. + * This is currently here to allow detached signatures to work + * properly. The only user of this function is also checking + * for CS_VALID. */ int @@ -927,6 +939,10 @@ cs_get_cdhash(struct proc *p) { struct cs_blob *csblob; + if ((p->p_csflags & CS_SIGNED) == 0) { + return NULL; + } + if (NULL == p->p_textvp) return NULL; diff --git a/bsd/kern/kern_exec.c b/bsd/kern/kern_exec.c index 3ccb12119..90334a790 100644 --- a/bsd/kern/kern_exec.c +++ b/bsd/kern/kern_exec.c @@ -2082,7 +2082,7 @@ static int spawn_validate_persona(struct _posix_spawn_persona_info *px_persona) } } if (px_persona->pspi_flags & POSIX_SPAWN_PERSONA_GROUPS) { - int ngroups = 0; + unsigned ngroups = 0; gid_t groups[NGROUPS_MAX]; if (persona_get_groups(persona, &ngroups, groups, @@ -2090,7 +2090,7 @@ static int spawn_validate_persona(struct _posix_spawn_persona_info *px_persona) error = EINVAL; goto out; } - if (ngroups != (int)px_persona->pspi_ngroups) { + if (ngroups != px_persona->pspi_ngroups) { error = EINVAL; goto out; } @@ -5469,67 +5469,6 @@ static void cdhash_to_string(char str[CS_CDHASH_STRING_SIZE], uint8_t const * co str[CS_CDHASH_STRING_SIZE - 1] = 0; } -/* - * If the process is not signed or if it contains entitlements, we - * need to communicate through the task_access_port to taskgated. - * - * taskgated will provide a detached code signature if present, and - * will enforce any restrictions on entitlements. - */ - -static boolean_t -taskgated_required(proc_t p, boolean_t *require_success) -{ - size_t length; - void *blob; - int error; - - if (cs_debug > 2) - csvnode_print_debug(p->p_textvp); - -#if !CONFIG_EMBEDDED - const int can_skip_taskgated = csproc_get_platform_binary(p) && !csproc_get_platform_path(p); -#else - const int can_skip_taskgated = csproc_get_platform_binary(p); -#endif - if (can_skip_taskgated) { - if (cs_debug) printf("taskgated not required for: %s\n", p->p_name); - *require_success = FALSE; - return FALSE; - } - - if ((p->p_csflags & CS_VALID) == 0) { - *require_success = FALSE; - return TRUE; - } - - error = cs_entitlements_blob_get(p, &blob, &length); - if (error == 0 && blob != NULL) { -#if !CONFIG_EMBEDDED - /* - * fatal on the desktop when entitlements are present, - * unless we started in single-user mode - */ - if ((boothowto & RB_SINGLE) == 0) - *require_success = TRUE; - /* - * Allow initproc to run without causing taskgated to launch - */ - if (p == initproc) { - *require_success = FALSE; - return FALSE; - } - -#endif - if (cs_debug) printf("taskgated required for: %s\n", p->p_name); - - return TRUE; - } - - *require_success = FALSE; - return FALSE; -} - /* * __EXEC_WAITING_ON_TASKGATED_CODE_SIGNATURE_UPCALL__ * @@ -5550,7 +5489,7 @@ check_for_signature(proc_t p, struct image_params *imgp) kern_return_t kr = KERN_FAILURE; int error = EACCES; boolean_t unexpected_failure = FALSE; - unsigned char hash[CS_CDHASH_LEN]; + struct cs_blob *csb; boolean_t require_success = FALSE; int spawn = (imgp->ip_flags & IMGPF_SPAWN); int vfexec = (imgp->ip_flags & IMGPF_VFORK_EXEC); @@ -5592,12 +5531,17 @@ check_for_signature(proc_t p, struct image_params *imgp) goto done; } - /* check if callout to taskgated is needed */ - if (!taskgated_required(p, &require_success)) { + /* If the code signature came through the image activation path, we skip the + * taskgated / externally attached path. */ + if (imgp->ip_csflags & CS_SIGNED) { error = 0; goto done; } + /* The rest of the code is for signatures that either already have been externally + * attached (likely, but not necessarily by a previous run through the taskgated + * path), or that will now be attached by taskgated. */ + kr = task_get_task_access_port(p->task, &port); if (KERN_SUCCESS != kr || !IPC_PORT_VALID(port)) { error = 0; @@ -5642,14 +5586,42 @@ check_for_signature(proc_t p, struct image_params *imgp) /* Only do this if exec_resettextvp() did not fail */ if (p->p_textvp != NULLVP) { - /* - * If there's a new code directory, mark this process - * as signed. - */ - if (0 == ubc_cs_getcdhash(p->p_textvp, p->p_textoff, hash)) { - proc_lock(p); - p->p_csflags |= CS_VALID; - proc_unlock(p); + csb = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff); + + if (csb != NULL) { + /* As the enforcement we can do here is very limited, we only allow things that + * are the only reason why this code path still exists: + * Adhoc signed non-platform binaries without special cs_flags and without any + * entitlements (unrestricted ones still pass AMFI). */ + if ( + /* Revalidate the blob if necessary through bumped generation count. */ + (ubc_cs_generation_check(p->p_textvp) == 0 || + ubc_cs_blob_revalidate(p->p_textvp, csb, imgp, 0) == 0) && + /* Only CS_ADHOC, no CS_KILL, CS_HARD etc. */ + (csb->csb_flags & CS_ALLOWED_MACHO) == CS_ADHOC && + /* If it has a CMS blob, it's not adhoc. The CS_ADHOC flag can lie. */ + csblob_find_blob_bytes((const uint8_t *)csb->csb_mem_kaddr, csb->csb_mem_size, + CSSLOT_SIGNATURESLOT, + CSMAGIC_BLOBWRAPPER) == NULL && + /* It could still be in a trust cache (unlikely with CS_ADHOC), or a magic path. */ + csb->csb_platform_binary == 0 && + /* No entitlements, not even unrestricted ones. */ + csb->csb_entitlements_blob == NULL) { + + proc_lock(p); + p->p_csflags |= CS_SIGNED | CS_VALID; + proc_unlock(p); + + } else { + uint8_t cdhash[CS_CDHASH_LEN]; + char cdhash_string[CS_CDHASH_STRING_SIZE]; + proc_getcdhash(p, cdhash); + cdhash_to_string(cdhash_string, cdhash); + printf("ignoring detached code signature on '%s' with cdhash '%s' " + "because it is invalid, or not a simple adhoc signature.\n", + p->p_name, cdhash_string); + } + } } diff --git a/bsd/kern/kern_exit.c b/bsd/kern/kern_exit.c index fdbee03d1..f5ee01dc1 100644 --- a/bsd/kern/kern_exit.c +++ b/bsd/kern/kern_exit.c @@ -1791,14 +1791,14 @@ loop1: error = ENOMEM; } else { if (IS_64BIT_PROCESS(q)) { - struct user64_rusage my_rusage; + struct user64_rusage my_rusage = {}; munge_user64_rusage(&p->p_ru->ru, &my_rusage); error = copyout((caddr_t)&my_rusage, uap->rusage, sizeof (my_rusage)); } else { - struct user32_rusage my_rusage; + struct user32_rusage my_rusage = {}; munge_user32_rusage(&p->p_ru->ru, &my_rusage); error = copyout((caddr_t)&my_rusage, uap->rusage, diff --git a/bsd/kern/kern_mman.c b/bsd/kern/kern_mman.c index adb144567..1c6979473 100644 --- a/bsd/kern/kern_mman.c +++ b/bsd/kern/kern_mman.c @@ -1047,7 +1047,7 @@ mincore(__unused proc_t p, struct mincore_args *uap, __unused int32_t *retval) req_vec_size_pages = (end - addr) >> PAGE_SHIFT; cur_vec_size_pages = MIN(req_vec_size_pages, (int)(MAX_PAGE_RANGE_QUERY >> PAGE_SHIFT)); - kernel_vec = (void*) _MALLOC(cur_vec_size_pages * sizeof(char), M_TEMP, M_WAITOK); + kernel_vec = (void*) _MALLOC(cur_vec_size_pages * sizeof(char), M_TEMP, M_WAITOK | M_ZERO); if (kernel_vec == NULL) { return (ENOMEM); diff --git a/bsd/kern/kern_ntptime.c b/bsd/kern/kern_ntptime.c index ccbfece8d..915f4c4b7 100644 --- a/bsd/kern/kern_ntptime.c +++ b/bsd/kern/kern_ntptime.c @@ -267,7 +267,7 @@ ntp_gettime(struct proc *p, struct ntp_gettime_args *uap, __unused int32_t *retv NTP_UNLOCK(enable); if (IS_64BIT_PROCESS(p)) { - struct user64_ntptimeval user_ntv; + struct user64_ntptimeval user_ntv = {}; user_ntv.time.tv_sec = ntv.time.tv_sec; user_ntv.time.tv_nsec = ntv.time.tv_nsec; user_ntv.maxerror = ntv.maxerror; @@ -276,7 +276,7 @@ ntp_gettime(struct proc *p, struct ntp_gettime_args *uap, __unused int32_t *retv user_ntv.time_state = ntv.time_state; error = copyout(&user_ntv, uap->ntvp, sizeof(user_ntv)); } else { - struct user32_ntptimeval user_ntv; + struct user32_ntptimeval user_ntv = {}; user_ntv.time.tv_sec = ntv.time.tv_sec; user_ntv.time.tv_nsec = ntv.time.tv_nsec; user_ntv.maxerror = ntv.maxerror; @@ -439,7 +439,7 @@ ntp_adjtime(struct proc *p, struct ntp_adjtime_args *uap, __unused int32_t *retv * returned only by ntp_gettime(); */ if (IS_64BIT_PROCESS(p)) { - struct user64_timex user_ntv; + struct user64_timex user_ntv = {}; if (time_status & STA_NANO) user_ntv.offset = L_GINT(time_offset); @@ -463,7 +463,7 @@ ntp_adjtime(struct proc *p, struct ntp_adjtime_args *uap, __unused int32_t *retv } else{ - struct user32_timex user_ntv; + struct user32_timex user_ntv = {}; if (time_status & STA_NANO) user_ntv.offset = L_GINT(time_offset); @@ -712,12 +712,12 @@ adjtime(struct proc *p, struct adjtime_args *uap, __unused int32_t *retval) if (uap->olddelta) { if (IS_64BIT_PROCESS(p)) { - struct user64_timeval user_atv; + struct user64_timeval user_atv = {}; user_atv.tv_sec = atv.tv_sec; user_atv.tv_usec = atv.tv_usec; error = copyout(&user_atv, uap->olddelta, sizeof(user_atv)); } else { - struct user32_timeval user_atv; + struct user32_timeval user_atv = {}; user_atv.tv_sec = atv.tv_sec; user_atv.tv_usec = atv.tv_usec; error = copyout(&user_atv, uap->olddelta, sizeof(user_atv)); diff --git a/bsd/kern/kern_persona.c b/bsd/kern/kern_persona.c index 5638b792c..7d641675d 100644 --- a/bsd/kern/kern_persona.c +++ b/bsd/kern/kern_persona.c @@ -998,7 +998,7 @@ gid_t persona_get_gid(struct persona *persona) return gid; } -int persona_set_groups(struct persona *persona, gid_t *groups, int ngroups, uid_t gmuid) +int persona_set_groups(struct persona *persona, gid_t *groups, unsigned ngroups, uid_t gmuid) { int ret = 0; kauth_cred_t my_cred, new_cred; @@ -1020,7 +1020,7 @@ int persona_set_groups(struct persona *persona, gid_t *groups, int ngroups, uid_ my_cred = persona->pna_cred; kauth_cred_ref(my_cred); - new_cred = kauth_cred_setgroups(my_cred, groups, ngroups, gmuid); + new_cred = kauth_cred_setgroups(my_cred, groups, (int)ngroups, gmuid); if (new_cred != my_cred) persona->pna_cred = new_cred; kauth_cred_unref(&my_cred); @@ -1030,17 +1030,19 @@ out_unlock: return ret; } -int persona_get_groups(struct persona *persona, int *ngroups, gid_t *groups, int groups_sz) +int persona_get_groups(struct persona *persona, unsigned *ngroups, gid_t *groups, unsigned groups_sz) { int ret = EINVAL; - if (!persona || !persona->pna_cred || !groups || !ngroups) + if (!persona || !persona->pna_cred || !groups || !ngroups || groups_sz > NGROUPS) return EINVAL; *ngroups = groups_sz; persona_lock(persona); if (persona_valid(persona)) { - kauth_cred_getgroups(persona->pna_cred, groups, ngroups); + int kauth_ngroups = (int)groups_sz; + kauth_cred_getgroups(persona->pna_cred, groups, &kauth_ngroups); + *ngroups = (unsigned)kauth_ngroups; ret = 0; } persona_unlock(persona); diff --git a/bsd/kern/kern_proc.c b/bsd/kern/kern_proc.c index 83bd75cd2..249d8c355 100644 --- a/bsd/kern/kern_proc.c +++ b/bsd/kern/kern_proc.c @@ -112,6 +112,10 @@ #include #include +#ifdef CONFIG_32BIT_TELEMETRY +#include +#endif /* CONFIG_32BIT_TELEMETRY */ + #if CONFIG_CSR #include #endif @@ -126,6 +130,10 @@ #include +#ifdef CONFIG_32BIT_TELEMETRY +#define MAX_32BIT_EXEC_SIG_SIZE 160 +#endif /* CONFIG_32BIT_TELEMETRY */ + /* * Structure associated with user cacheing. */ @@ -1155,7 +1163,7 @@ proc_getexecutablevnode(proc_t p) if (vnode_getwithref(tvp) == 0) { return tvp; } - } + } return NULLVP; } @@ -3431,3 +3439,80 @@ proc_get_uthread_uu_threadlist(void * uthread_v) uthread_t uth = (uthread_t)uthread_v; return (uth != NULL) ? uth->uu_threadlist : NULL; } + +#ifdef CONFIG_32BIT_TELEMETRY +void +proc_log_32bit_telemetry(proc_t p) +{ + /* Gather info */ + char signature_buf[MAX_32BIT_EXEC_SIG_SIZE] = { 0 }; + char * signature_cur_end = &signature_buf[0]; + char * signature_buf_end = &signature_buf[MAX_32BIT_EXEC_SIG_SIZE - 1]; + int bytes_printed = 0; + + const char * teamid = NULL; + const char * identity = NULL; + struct cs_blob * csblob = NULL; + + proc_list_lock(); + + /* + * Get proc name and parent proc name; if the parent execs, we'll get a + * garbled name. + */ + bytes_printed = snprintf(signature_cur_end, + signature_buf_end - signature_cur_end, + "%s,%s,", p->p_name, + (p->p_pptr ? p->p_pptr->p_name : "")); + + if (bytes_printed > 0) { + signature_cur_end += bytes_printed; + } + + proc_list_unlock(); + + /* Get developer info. */ + vnode_t v = proc_getexecutablevnode(p); + + if (v) { + csblob = csvnode_get_blob(v, 0); + + if (csblob) { + teamid = csblob_get_teamid(csblob); + identity = csblob_get_identity(csblob); + } + } + + if (teamid == NULL) { + teamid = ""; + } + + if (identity == NULL) { + identity = ""; + } + + bytes_printed = snprintf(signature_cur_end, + signature_buf_end - signature_cur_end, + "%s,%s", teamid, identity); + + if (bytes_printed > 0) { + signature_cur_end += bytes_printed; + } + + if (v) { + vnode_put(v); + } + + /* + * We may want to rate limit here, although the SUMMARIZE key should + * help us aggregate events in userspace. + */ + + /* Emit log */ + kern_asl_msg(LOG_DEBUG, "messagetracer", 3, + /* 0 */ "com.apple.message.domain", "com.apple.kernel.32bit_exec", + /* 1 */ "com.apple.message.signature", signature_buf, + /* 2 */ "com.apple.message.summarize", "YES", + NULL); +} +#endif /* CONFIG_32BIT_TELEMETRY */ diff --git a/bsd/kern/kern_resource.c b/bsd/kern/kern_resource.c index 7bc8466bc..780159263 100644 --- a/bsd/kern/kern_resource.c +++ b/bsd/kern/kern_resource.c @@ -1144,7 +1144,7 @@ out: int getrlimit(struct proc *p, struct getrlimit_args *uap, __unused int32_t *retval) { - struct rlimit lim; + struct rlimit lim = {}; /* * Take out flag now in case we need to use it to trigger variant diff --git a/bsd/kern/kern_sig.c b/bsd/kern/kern_sig.c index ca7b6c584..d390ded07 100644 --- a/bsd/kern/kern_sig.c +++ b/bsd/kern/kern_sig.c @@ -3440,11 +3440,16 @@ bsd_ast(thread_t thread) } proc_unlock(p); +#ifdef CONFIG_32BIT_TELEMETRY + if (task_consume_32bit_log_flag(p->task)) { + proc_log_32bit_telemetry(p); + } +#endif /* CONFIG_32BIT_TELEMETRY */ + if (!bsd_init_done) { bsd_init_done = 1; bsdinit_task(); } - } /* ptrace set runnable */ diff --git a/bsd/kern/mach_loader.c b/bsd/kern/mach_loader.c index 43f1a78b0..f84a814cb 100644 --- a/bsd/kern/mach_loader.c +++ b/bsd/kern/mach_loader.c @@ -65,6 +65,7 @@ #include #include +#include #include #include #include @@ -520,6 +521,19 @@ load_machfile( task_rollup_accounting_info(get_threadtask(thread), task); } *mapp = map; + +#ifdef CONFIG_32BIT_TELEMETRY + if (!result->is64bit) { + /* + * This may not need to be an AST; we merely need to ensure that + * we gather telemetry at the point where all of the information + * that we want has been added to the process. + */ + task_set_32bit_log_flag(get_threadtask(thread)); + act_set_astbsd(thread); + } +#endif /* CONFIG_32BIT_TELEMETRY */ + return(LOAD_SUCCESS); } @@ -1121,34 +1135,9 @@ parse_machfile( break; } - if (ret == LOAD_SUCCESS) { - if (! got_code_signatures) { - if (cs_enforcement(NULL)) { - ret = LOAD_FAILURE; - } else { -#if !CONFIG_EMBEDDED - /* - * No embedded signatures: look for detached by taskgated, - * this is only done on OSX, on embedded platforms we expect everything - * to be have embedded signatures. - */ - struct cs_blob *blob; - - blob = ubc_cs_blob_get(vp, -1, file_offset); - if (blob != NULL) { - unsigned int cs_flag_data = blob->csb_flags; - if(0 != ubc_cs_generation_check(vp)) { - if (0 != ubc_cs_blob_revalidate(vp, blob, imgp, 0)) { - /* clear out the flag data if revalidation fails */ - cs_flag_data = 0; - result->csflags &= ~CS_VALID; - } - } - /* get flags to be applied to the process */ - result->csflags |= cs_flag_data; - } -#endif - } + if (ret == LOAD_SUCCESS) { + if(!got_code_signatures && cs_enforcement(NULL)) { + ret = LOAD_FAILURE; } /* Make sure if we need dyld, we got it */ diff --git a/bsd/kern/policy_check.c b/bsd/kern/policy_check.c index 85a92f5fe..75b2bb722 100644 --- a/bsd/kern/policy_check.c +++ b/bsd/kern/policy_check.c @@ -119,7 +119,7 @@ common_hook(void) return rv; } -#if (MAC_POLICY_OPS_VERSION != 52) +#if (MAC_POLICY_OPS_VERSION != 53) # error "struct mac_policy_ops doesn't match definition in mac_policy.h" #endif /* @@ -281,10 +281,10 @@ const static struct mac_policy_ops policy_ops = { CHECK_SET_HOOK(exc_action_label_init) CHECK_SET_HOOK(exc_action_label_update) + CHECK_SET_HOOK(vnode_check_trigger_resolve) .mpo_reserved1 = (mpo_reserved_hook_t *)common_hook, .mpo_reserved2 = (mpo_reserved_hook_t *)common_hook, .mpo_reserved3 = (mpo_reserved_hook_t *)common_hook, - .mpo_reserved4 = (mpo_reserved_hook_t *)common_hook, CHECK_SET_HOOK(skywalk_flow_check_connect) CHECK_SET_HOOK(skywalk_flow_check_listen) diff --git a/bsd/kern/sys_coalition.c b/bsd/kern/sys_coalition.c index 5cb3daa6b..fec4bfa44 100644 --- a/bsd/kern/sys_coalition.c +++ b/bsd/kern/sys_coalition.c @@ -216,7 +216,7 @@ static int __attribute__ ((noinline)) coalition_info_resource_usage(coalition_t coal, user_addr_t buffer, user_size_t bufsize) { kern_return_t kr; - struct coalition_resource_usage cru; + struct coalition_resource_usage cru = {}; kr = coalition_resource_usage_internal(coal, &cru); diff --git a/bsd/kern/sys_persona.c b/bsd/kern/sys_persona.c index 3272922f7..792043d8d 100644 --- a/bsd/kern/sys_persona.c +++ b/bsd/kern/sys_persona.c @@ -215,7 +215,7 @@ static int kpersona_info_syscall(user_addr_t idp, user_addr_t infop) kinfo.persona_id = persona->pna_id; kinfo.persona_type = persona->pna_type; kinfo.persona_gid = persona_get_gid(persona); - int ngroups = 0; + unsigned ngroups = 0; persona_get_groups(persona, &ngroups, kinfo.persona_groups, NGROUPS); kinfo.persona_ngroups = ngroups; kinfo.persona_gmuid = persona_get_gmuid(persona); @@ -257,7 +257,7 @@ static int kpersona_pidinfo_syscall(user_addr_t idp, user_addr_t infop) kinfo.persona_id = persona->pna_id; kinfo.persona_type = persona->pna_type; kinfo.persona_gid = persona_get_gid(persona); - int ngroups = 0; + unsigned ngroups = 0; persona_get_groups(persona, &ngroups, kinfo.persona_groups, NGROUPS); kinfo.persona_ngroups = ngroups; kinfo.persona_gmuid = persona_get_gmuid(persona); diff --git a/bsd/kern/uipc_socket.c b/bsd/kern/uipc_socket.c index 1c5af8cf3..7d744eff9 100644 --- a/bsd/kern/uipc_socket.c +++ b/bsd/kern/uipc_socket.c @@ -5661,7 +5661,7 @@ integer: goto integer; case SO_NP_EXTENSIONS: { - struct so_np_extensions sonpx; + struct so_np_extensions sonpx = {}; sonpx.npx_flags = (so->so_flags & SOF_NPX_SETOPTSHUT) ? SONPX_SETOPTSHUT : 0; diff --git a/bsd/kern/uipc_syscalls.c b/bsd/kern/uipc_syscalls.c index f51596c37..eb2c9fa6a 100644 --- a/bsd/kern/uipc_syscalls.c +++ b/bsd/kern/uipc_syscalls.c @@ -1735,7 +1735,7 @@ copyout_control(struct proc *p, struct mbuf *m, user_addr_t control, * different size for 32 bits and 64 bits processes */ if (cp->cmsg_level == SOL_SOCKET && cp->cmsg_type == SCM_TIMESTAMP) { - unsigned char tmp_buffer[CMSG_SPACE(sizeof(struct user64_timeval))]; + unsigned char tmp_buffer[CMSG_SPACE(sizeof(struct user64_timeval))] = {}; struct cmsghdr *tmp_cp = (struct cmsghdr *)(void *)tmp_buffer; int tmp_space; struct timeval *tv = (struct timeval *)(void *)CMSG_DATA(cp); diff --git a/bsd/net/if.c b/bsd/net/if.c index 6b00d6cad..acd1ac75c 100644 --- a/bsd/net/if.c +++ b/bsd/net/if.c @@ -2190,12 +2190,11 @@ ifioctl_iforder(u_long cmd, caddr_t data) case SIOCGIFORDER: { /* struct if_order */ struct if_order *ifo = (struct if_order *)(void *)data; - - u_int32_t ordered_count = if_ordered_count; + u_int32_t ordered_count = *((volatile u_int32_t *)&if_ordered_count); if (ifo->ifo_count == 0 || ordered_count == 0) { - ifo->ifo_count = ordered_count; + ifo->ifo_count = 0; } else if (ifo->ifo_ordered_indices != USER_ADDR_NULL) { u_int32_t count_to_copy = MIN(ordered_count, ifo->ifo_count); @@ -2203,7 +2202,7 @@ ifioctl_iforder(u_long cmd, caddr_t data) struct ifnet *ifp = NULL; u_int32_t cursor = 0; - ordered_indices = _MALLOC(length, M_NECP, M_WAITOK); + ordered_indices = _MALLOC(length, M_NECP, M_WAITOK | M_ZERO); if (ordered_indices == NULL) { error = ENOMEM; break; @@ -2211,7 +2210,8 @@ ifioctl_iforder(u_long cmd, caddr_t data) ifnet_head_lock_shared(); TAILQ_FOREACH(ifp, &ifnet_ordered_head, if_ordered_link) { - if (cursor >= count_to_copy) { + if (cursor >= count_to_copy || + cursor >= if_ordered_count) { break; } ordered_indices[cursor] = ifp->if_index; @@ -2219,7 +2219,11 @@ ifioctl_iforder(u_long cmd, caddr_t data) } ifnet_head_done(); - ifo->ifo_count = count_to_copy; + /* We might have parsed less than the original length + * because the list could have changed. + */ + length = cursor * sizeof(u_int32_t); + ifo->ifo_count = cursor; error = copyout(ordered_indices, ifo->ifo_ordered_indices, length); } else { diff --git a/bsd/net/if_llreach.c b/bsd/net/if_llreach.c index 764e72bd8..29a449936 100644 --- a/bsd/net/if_llreach.c +++ b/bsd/net/if_llreach.c @@ -626,7 +626,7 @@ sysctl_llreach_ifinfo SYSCTL_HANDLER_ARGS unsigned int namelen; uint32_t ifindex; struct if_llreach *lr; - struct if_llreach_info lri; + struct if_llreach_info lri = {}; struct ifnet *ifp; name = (int *)arg1; diff --git a/bsd/net/necp_client.c b/bsd/net/necp_client.c index 1588ac177..83666005b 100644 --- a/bsd/net/necp_client.c +++ b/bsd/net/necp_client.c @@ -3500,7 +3500,7 @@ necp_client_copy_internal(struct necp_client *client, bool client_is_observed, s LIST_FOREACH(flow, &client->flow_list, flow_chain) { if (flow->nexus || (flow->socket && flow->assigned)) { // Write TLV headers - struct necp_client_nexus_flow_header header; + struct necp_client_nexus_flow_header header = {}; u_int32_t length = 0; u_int32_t flags = 0; u_int8_t tfo_cookie_len = 0; @@ -3603,7 +3603,7 @@ necp_client_copy_internal(struct necp_client *client, bool client_is_observed, s /* Read the protocol event and reset it */ if (flow->has_protoctl_event) { - struct necp_client_flow_protoctl_event_header protoctl_event_header; + struct necp_client_flow_protoctl_event_header protoctl_event_header = {}; type = NECP_CLIENT_RESULT_PROTO_CTL_EVENT; length = sizeof(protoctl_event_header.protoctl_event); @@ -4546,7 +4546,7 @@ necp_match_policy(struct proc *p, struct necp_match_policy_args *uap, int32_t *r { #pragma unused(retval) u_int8_t *parameters = NULL; - struct necp_aggregate_result returned_result; + struct necp_aggregate_result returned_result = {}; int error = 0; if (uap == NULL) { diff --git a/bsd/net/pf_ioctl.c b/bsd/net/pf_ioctl.c index 62a475f9d..977751814 100644 --- a/bsd/net/pf_ioctl.c +++ b/bsd/net/pf_ioctl.c @@ -3395,7 +3395,7 @@ pfioctl_ioc_states(u_long cmd, struct pfioc_states_32 *ps32, break; } - pstore = _MALLOC(sizeof (*pstore), M_TEMP, M_WAITOK); + pstore = _MALLOC(sizeof (*pstore), M_TEMP, M_WAITOK | M_ZERO); if (pstore == NULL) { error = ENOMEM; break; diff --git a/bsd/net/rtsock.c b/bsd/net/rtsock.c index 457eaf4eb..8c4387a47 100644 --- a/bsd/net/rtsock.c +++ b/bsd/net/rtsock.c @@ -461,7 +461,6 @@ route_output(struct mbuf *m, struct socket *so) if (info.rti_info[RTAX_GATEWAY] != NULL && info.rti_info[RTAX_GATEWAY]->sa_family == AF_INET) sin_set_ifscope(info.rti_info[RTAX_GATEWAY], IFSCOPE_NONE); - switch (rtm->rtm_type) { case RTM_ADD: if (info.rti_info[RTAX_GATEWAY] == NULL) @@ -583,24 +582,23 @@ report: len = rt_msg2(rtm->rtm_type, &info, NULL, NULL, &cred); if (ifa2 != NULL) IFA_UNLOCK(ifa2); - if (len > rtm->rtm_msglen) { - struct rt_msghdr *new_rtm; - R_Malloc(new_rtm, struct rt_msghdr *, len); - if (new_rtm == NULL) { - RT_UNLOCK(rt); - if (ifa2 != NULL) - IFA_REMREF(ifa2); - senderr(ENOBUFS); - } - Bcopy(rtm, new_rtm, rtm->rtm_msglen); - R_Free(rtm); rtm = new_rtm; + struct rt_msghdr *out_rtm; + R_Malloc(out_rtm, struct rt_msghdr *, len); + if (out_rtm == NULL) { + RT_UNLOCK(rt); + if (ifa2 != NULL) + IFA_REMREF(ifa2); + senderr(ENOBUFS); } + Bcopy(rtm, out_rtm, sizeof(struct rt_msghdr)); if (ifa2 != NULL) IFA_LOCK(ifa2); - (void) rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, + (void) rt_msg2(out_rtm->rtm_type, &info, (caddr_t)out_rtm, NULL, &cred); if (ifa2 != NULL) IFA_UNLOCK(ifa2); + R_Free(rtm); + rtm = out_rtm; rtm->rtm_flags = rt->rt_flags; rt_getmetrics(rt, &rtm->rtm_rmx); rtm->rtm_addrs = info.rti_addrs; diff --git a/bsd/netinet/in_mcast.c b/bsd/netinet/in_mcast.c index 3d8ca9699..d772cc806 100644 --- a/bsd/netinet/in_mcast.c +++ b/bsd/netinet/in_mcast.c @@ -1697,7 +1697,7 @@ inp_findmoptions(struct inpcb *inp) static int inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt) { - struct __msfilterreq64 msfr, msfr64; + struct __msfilterreq64 msfr = {}, msfr64; struct __msfilterreq32 msfr32; struct sockaddr_in *gsa; struct ifnet *ifp; @@ -2719,7 +2719,7 @@ inp_set_multicast_if(struct inpcb *inp, struct sockopt *sopt) static int inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt) { - struct __msfilterreq64 msfr, msfr64; + struct __msfilterreq64 msfr = {}, msfr64; struct __msfilterreq32 msfr32; struct sockaddr_in *gsa; struct ifnet *ifp; @@ -3126,7 +3126,7 @@ sysctl_ip_mcast_filters SYSCTL_HANDLER_ARGS { #pragma unused(oidp) - struct in_addr src, group; + struct in_addr src = {}, group; struct ifnet *ifp; struct in_multi *inm; struct in_multistep step; diff --git a/bsd/netinet/in_tclass.c b/bsd/netinet/in_tclass.c index 5d627e551..81595da9b 100644 --- a/bsd/netinet/in_tclass.c +++ b/bsd/netinet/in_tclass.c @@ -1546,7 +1546,7 @@ sysctl_default_netsvctype_to_dscp_map SYSCTL_HANDLER_ARGS const size_t max_netsvctype_to_dscp_map_len = _NET_SERVICE_TYPE_COUNT * sizeof(struct netsvctype_dscp_map); size_t len; - struct netsvctype_dscp_map netsvctype_dscp_map[_NET_SERVICE_TYPE_COUNT]; + struct netsvctype_dscp_map netsvctype_dscp_map[_NET_SERVICE_TYPE_COUNT] = {}; size_t count; if (req->oldptr == USER_ADDR_NULL) { @@ -1748,7 +1748,7 @@ sysctl_dscp_to_wifi_ac_map SYSCTL_HANDLER_ARGS #pragma unused(oidp, arg1, arg2) int error = 0; size_t len = DSCP_ARRAY_SIZE * sizeof(struct netsvctype_dscp_map); - struct netsvctype_dscp_map netsvctype_dscp_map[DSCP_ARRAY_SIZE]; + struct netsvctype_dscp_map netsvctype_dscp_map[DSCP_ARRAY_SIZE] = {}; struct dcsp_msc_map dcsp_msc_map[DSCP_ARRAY_SIZE]; size_t count; u_int32_t i; diff --git a/bsd/netinet/ip_fw2.c b/bsd/netinet/ip_fw2.c index 6694975b7..3d69b2029 100644 --- a/bsd/netinet/ip_fw2.c +++ b/bsd/netinet/ip_fw2.c @@ -3792,21 +3792,21 @@ ipfw_ctl(struct sockopt *sopt) if (!error && sopt->sopt_dir == SOPT_GET) { /* convert back if necessary and copyout */ if (api_version == IP_FW_VERSION_0) { - struct ip_old_fw rule_vers0; + struct ip_old_fw rule_vers0 = {}; ipfw_convert_from_latest(rule, &rule_vers0, api_version, is64user); sopt->sopt_valsize = sizeof(struct ip_old_fw); error = sooptcopyout(sopt, &rule_vers0, sizeof(struct ip_old_fw)); } else if (api_version == IP_FW_VERSION_1) { - struct ip_fw_compat rule_vers1; + struct ip_fw_compat rule_vers1 = {}; ipfw_convert_from_latest(rule, &rule_vers1, api_version, is64user); sopt->sopt_valsize = sizeof(struct ip_fw_compat); error = sooptcopyout(sopt, &rule_vers1, sizeof(struct ip_fw_compat)); } else { char *userrule; - userrule = _MALLOC(savedsopt_valsize, M_TEMP, M_WAITOK); + userrule = _MALLOC(savedsopt_valsize, M_TEMP, M_WAITOK | M_ZERO); if ( userrule == NULL ) userrule = (char*)rule; if (proc_is64bit(sopt->sopt_p)){ diff --git a/bsd/netinet/mptcp_usrreq.c b/bsd/netinet/mptcp_usrreq.c index 1a5589901..fb199c658 100644 --- a/bsd/netinet/mptcp_usrreq.c +++ b/bsd/netinet/mptcp_usrreq.c @@ -1539,7 +1539,7 @@ out: static int mptcp_getopt(struct mptses *mpte, struct sockopt *sopt) { - int error = 0, optval; + int error = 0, optval = 0; VERIFY(sopt->sopt_dir == SOPT_GET); mpte_lock_assert_held(mpte); /* same as MP socket lock */ diff --git a/bsd/netinet/tcp_usrreq.c b/bsd/netinet/tcp_usrreq.c index 9d8fa7efb..3c368cb52 100644 --- a/bsd/netinet/tcp_usrreq.c +++ b/bsd/netinet/tcp_usrreq.c @@ -1765,7 +1765,7 @@ __private_extern__ int tcp_sysctl_info(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) { int error; - struct tcp_info ti; + struct tcp_info ti = {}; struct info_tuple itpl; #if !CONFIG_EMBEDDED proc_t caller = PROC_NULL; @@ -1883,11 +1883,10 @@ tcp_getconninfo(struct socket *so, struct conninfo_tcp *tcp_ci) int tcp_ctloutput(struct socket *so, struct sockopt *sopt) { - int error, opt, optval; + int error = 0, opt = 0, optval = 0; struct inpcb *inp; struct tcpcb *tp; - error = 0; inp = sotoinpcb(so); if (inp == NULL) { return (ECONNRESET); @@ -2490,7 +2489,7 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt) goto done; } case TCP_MEASURE_BW_BURST: { - struct tcp_measure_bw_burst out; + struct tcp_measure_bw_burst out = {}; if ((tp->t_flagsext & TF_MEASURESNDBW) == 0 || tp->t_bwmeas == NULL) { error = EINVAL; diff --git a/bsd/netinet/udp_usrreq.c b/bsd/netinet/udp_usrreq.c index 044486ec5..0c4945e79 100644 --- a/bsd/netinet/udp_usrreq.c +++ b/bsd/netinet/udp_usrreq.c @@ -923,7 +923,7 @@ udp_ctlinput(int cmd, struct sockaddr *sa, void *vip, __unused struct ifnet * if int udp_ctloutput(struct socket *so, struct sockopt *sopt) { - int error, optval; + int error = 0, optval = 0; struct inpcb *inp; /* Allow at this level */ @@ -931,7 +931,6 @@ udp_ctloutput(struct socket *so, struct sockopt *sopt) !(sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_FLUSH)) return (ip_ctloutput(so, sopt)); - error = 0; inp = sotoinpcb(so); switch (sopt->sopt_dir) { diff --git a/bsd/netinet6/in6_mcast.c b/bsd/netinet6/in6_mcast.c index 778bafa8d..3bd00c8a2 100644 --- a/bsd/netinet6/in6_mcast.c +++ b/bsd/netinet6/in6_mcast.c @@ -1619,7 +1619,7 @@ in6p_findmoptions(struct inpcb *inp) static int in6p_get_source_filters(struct inpcb *inp, struct sockopt *sopt) { - struct __msfilterreq64 msfr, msfr64; + struct __msfilterreq64 msfr = {}, msfr64; struct __msfilterreq32 msfr32; struct sockaddr_in6 *gsa; struct ifnet *ifp; @@ -2650,7 +2650,7 @@ in6p_set_multicast_if(struct inpcb *inp, struct sockopt *sopt) static int in6p_set_source_filters(struct inpcb *inp, struct sockopt *sopt) { - struct __msfilterreq64 msfr, msfr64; + struct __msfilterreq64 msfr = {}, msfr64; struct __msfilterreq32 msfr32; struct sockaddr_in6 *gsa; struct ifnet *ifp; diff --git a/bsd/nfs/nfs_subs.c b/bsd/nfs/nfs_subs.c index 266710149..ff5ae70b6 100644 --- a/bsd/nfs/nfs_subs.c +++ b/bsd/nfs/nfs_subs.c @@ -3272,6 +3272,10 @@ nfsrv_export_lookup(struct nfs_export *nx, mbuf_t nam) /* Lookup in the export list first. */ if (nam != NULL) { saddr = mbuf_data(nam); + if (saddr->sa_family > AF_MAX) { + /* Bogus sockaddr? Don't match anything. */ + return (NULL); + } rnh = nx->nx_rtable[saddr->sa_family]; if (rnh != NULL) { no = (struct nfs_netopt *) diff --git a/bsd/nfs/nfs_vfsops.c b/bsd/nfs/nfs_vfsops.c index 67b9befc0..89f6ca956 100644 --- a/bsd/nfs/nfs_vfsops.c +++ b/bsd/nfs/nfs_vfsops.c @@ -5464,10 +5464,10 @@ nfs_vfs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp, struct nfs_exportfs *nxfs; struct nfs_export *nx; struct nfs_active_user_list *ulist; - struct nfs_export_stat_desc stat_desc; + struct nfs_export_stat_desc stat_desc = {}; struct nfs_export_stat_rec statrec; struct nfs_user_stat_node *unode, *unode_next; - struct nfs_user_stat_desc ustat_desc; + struct nfs_user_stat_desc ustat_desc = {}; struct nfs_user_stat_user_rec ustat_rec; struct nfs_user_stat_path_rec upath_rec; uint bytes_avail, bytes_total, recs_copied; diff --git a/bsd/sys/persona.h b/bsd/sys/persona.h index f1efd66d4..0744283f2 100644 --- a/bsd/sys/persona.h +++ b/bsd/sys/persona.h @@ -354,8 +354,8 @@ uid_t persona_get_uid(struct persona *persona); int persona_set_gid(struct persona *persona, gid_t gid); gid_t persona_get_gid(struct persona *persona); -int persona_set_groups(struct persona *persona, gid_t *groups, int ngroups, uid_t gmuid); -int persona_get_groups(struct persona *persona, int *ngroups, gid_t *groups, int groups_sz); +int persona_set_groups(struct persona *persona, gid_t *groups, unsigned ngroups, uid_t gmuid); +int persona_get_groups(struct persona *persona, unsigned *ngroups, gid_t *groups, unsigned groups_sz); uid_t persona_get_gmuid(struct persona *persona); diff --git a/bsd/sys/proc.h b/bsd/sys/proc.h index 7878ff644..f275e9f92 100644 --- a/bsd/sys/proc.h +++ b/bsd/sys/proc.h @@ -364,6 +364,10 @@ extern uint64_t proc_did_throttle(proc_t); extern void proc_coalitionids(proc_t, uint64_t [COALITION_NUM_TYPES]); +#ifdef CONFIG_32BIT_TELEMETRY +extern void proc_log_32bit_telemetry(proc_t p); +#endif /* CONFIG_32BIT_TELEMETRY */ + #endif /* XNU_KERNEL_PRIVATE*/ #ifdef KERNEL_PRIVATE diff --git a/bsd/vfs/vfs_cluster.c b/bsd/vfs/vfs_cluster.c index df1e9569f..32fc807ff 100644 --- a/bsd/vfs/vfs_cluster.c +++ b/bsd/vfs/vfs_cluster.c @@ -3323,7 +3323,7 @@ cluster_write_copy(vnode_t vp, struct uio *uio, u_int32_t io_req_size, off_t old io_size += start_offset; - if ((upl_f_offset + io_size) >= newEOF && (u_int)io_size < upl_size) { + if (newEOF >= oldEOF && (upl_f_offset + io_size) >= newEOF && (u_int)io_size < upl_size) { /* * if we're extending the file with this write * we'll zero fill the rest of the page so that diff --git a/bsd/vfs/vfs_subr.c b/bsd/vfs/vfs_subr.c index 5acfa82d4..dc434d049 100644 --- a/bsd/vfs/vfs_subr.c +++ b/bsd/vfs/vfs_subr.c @@ -3492,7 +3492,7 @@ again: if (space < req->oldlen) return (ENOMEM); - MALLOC(fsidlst, fsid_t *, req->oldlen, M_TEMP, M_WAITOK); + MALLOC(fsidlst, fsid_t *, req->oldlen, M_TEMP, M_WAITOK | M_ZERO); if (fsidlst == NULL) { return (ENOMEM); } @@ -3861,7 +3861,7 @@ sysctl_vfs_generic_conf SYSCTL_HANDLER_ARGS { int *name, namelen; struct vfstable *vfsp; - struct vfsconf vfsc; + struct vfsconf vfsc = {}; (void)oidp; name = arg1; @@ -9503,6 +9503,12 @@ vnode_trigger_resolve(vnode_t vp, struct nameidata *ndp, vfs_context_t ctx) lck_mtx_unlock(&rp->vr_lock); +#if CONFIG_MACF + int rv = mac_vnode_check_trigger_resolve(ctx, vp, &ndp->ni_cnd); + if (rv != 0) + return rv; +#endif + /* * XXX * assumes that resolver will not access this trigger vnode (otherwise the kernel will deadlock) diff --git a/bsd/vfs/vfs_syscalls.c b/bsd/vfs/vfs_syscalls.c index 2571c94d5..b2209d58d 100644 --- a/bsd/vfs/vfs_syscalls.c +++ b/bsd/vfs/vfs_syscalls.c @@ -5500,13 +5500,13 @@ fstatat_internal(vfs_context_t ctx, user_addr_t path, user_addr_t ub, union { struct stat sb; struct stat64 sb64; - } source; + } source = {}; union { struct user64_stat user64_sb; struct user32_stat user32_sb; struct user64_stat64 user64_sb64; struct user32_stat64 user32_sb64; - } dest; + } dest = {}; caddr_t sbp; int error, my_size; kauth_filesec_t fsec; diff --git a/config/MACFramework.exports b/config/MACFramework.exports index 6c190be01..67b209861 100644 --- a/config/MACFramework.exports +++ b/config/MACFramework.exports @@ -16,6 +16,8 @@ _mac_iokit_check_nvram_delete _mac_iokit_check_nvram_get _mac_iokit_check_nvram_set +_mac_vnode_check_trigger_resolve + _sbuf_cat _sbuf_data _sbuf_delete diff --git a/config/MASTER b/config/MASTER index 2fa158923..d4561e50d 100644 --- a/config/MASTER +++ b/config/MASTER @@ -735,3 +735,8 @@ options CONFIG_REQUIRES_U32_MUNGING # incoming U32 argument structures must be # options COPYOUT_SHIM # Shim for copyout memory analysis via kext # + +# +# Telemetry for 32-bit process launch +# +options CONFIG_32BIT_TELEMETRY # # diff --git a/config/MASTER.x86_64 b/config/MASTER.x86_64 index 0c8b7a4e5..1a934777d 100644 --- a/config/MASTER.x86_64 +++ b/config/MASTER.x86_64 @@ -20,7 +20,7 @@ # KERNEL_RELEASE = [ KERNEL_BASE ] # KERNEL_DEV = [ KERNEL_BASE development mach_assert config_xnupost proc_ref_debug os_reason_debug ] # KERNEL_DEBUG = [ KERNEL_BASE debug mach_assert config_xnupost config_ltable_stats config_ltable_debug config_waitq_stats config_waitq_debug ] -# BSD_BASE = [ mach_bsd sysv_sem sysv_msg sysv_shm config_imageboot config_workqueue psynch config_proc_uuid_policy config_coredump pgo ] +# BSD_BASE = [ mach_bsd sysv_sem sysv_msg sysv_shm config_imageboot config_workqueue psynch config_proc_uuid_policy config_coredump pgo config_32bit_telemetry ] # BSD_RELEASE = [ BSD_BASE ] # BSD_DEV = [ BSD_BASE config_vnguard ] # BSD_DEBUG = [ BSD_BASE config_vnguard ] diff --git a/config/MasterVersion b/config/MasterVersion index db6ac0645..7efb2c146 100644 --- a/config/MasterVersion +++ b/config/MasterVersion @@ -1,4 +1,4 @@ -17.3.0 +17.4.0 # The first line of this file contains the master version number for the kernel. # All other instances of the kernel version in xnu are derived from this file. diff --git a/iokit/IOKit/IOUserClient.h b/iokit/IOKit/IOUserClient.h index cce1695b9..2aa05be08 100644 --- a/iokit/IOKit/IOUserClient.h +++ b/iokit/IOKit/IOUserClient.h @@ -209,10 +209,11 @@ public: UInt8 __reservedA[1]; volatile SInt32 __ipc; queue_head_t owners; + IOLock * lock; #if __LP64__ - void * __reserved[5]; -#else void * __reserved[4]; +#else + void * __reserved[3]; #endif #else /* XNU_KERNEL_PRIVATE */ diff --git a/iokit/Kernel/IOUserClient.cpp b/iokit/Kernel/IOUserClient.cpp index 6a3fc814b..ad83881ca 100644 --- a/iokit/Kernel/IOUserClient.cpp +++ b/iokit/Kernel/IOUserClient.cpp @@ -605,7 +605,9 @@ iokit_client_died( io_object_t obj, ipc_port_t /* port */, if( (client = OSDynamicCast( IOUserClient, obj ))) { IOStatisticsClientCall(); + IOLockLock(client->lock); client->clientDied(); + IOLockUnlock(client->lock); } } else if( IKOT_IOKIT_OBJECT == type) @@ -1544,6 +1546,7 @@ iokit_task_terminate(task_t task) void IOUserClient::free() { if( mappings) mappings->release(); + if (lock) IOLockFree(lock); IOStatisticsUnregisterCounter(); @@ -3465,6 +3468,7 @@ kern_return_t is_io_service_open_extended( client->sharedInstance = (0 != client->getProperty(kIOUserClientSharedInstanceKey)); client->closed = false; + client->lock = IOLockAlloc(); disallowAccess = (crossEndian && (kOSBooleanTrue != service->getProperty(kIOUserClientCrossEndianCompatibleKey)) @@ -3516,7 +3520,9 @@ kern_return_t is_io_service_close( if (client->sharedInstance || OSCompareAndSwap8(0, 1, &client->closed)) { + IOLockLock(client->lock); client->clientClose(); + IOLockUnlock(client->lock); } else { @@ -3552,11 +3558,15 @@ kern_return_t is_io_connect_set_notification_port( mach_port_t port, uint32_t reference) { + kern_return_t ret; CHECK( IOUserClient, connection, client ); IOStatisticsClientCall(); - return( client->registerNotificationPort( port, notification_type, - (io_user_reference_t) reference )); + IOLockLock(client->lock); + ret = client->registerNotificationPort( port, notification_type, + (io_user_reference_t) reference ); + IOLockUnlock(client->lock); + return (ret); } /* Routine io_connect_set_notification_port */ @@ -3566,11 +3576,15 @@ kern_return_t is_io_connect_set_notification_port_64( mach_port_t port, io_user_reference_t reference) { + kern_return_t ret; CHECK( IOUserClient, connection, client ); IOStatisticsClientCall(); - return( client->registerNotificationPort( port, notification_type, - reference )); + IOLockLock(client->lock); + ret = client->registerNotificationPort( port, notification_type, + reference ); + IOLockUnlock(client->lock); + return (ret); } /* Routine io_connect_map_memory_into_task */ diff --git a/libsyscall/wrappers/spawn/posix_spawn.c b/libsyscall/wrappers/spawn/posix_spawn.c index 1334f4c3d..3a149790c 100644 --- a/libsyscall/wrappers/spawn/posix_spawn.c +++ b/libsyscall/wrappers/spawn/posix_spawn.c @@ -1730,7 +1730,7 @@ posix_spawnattr_set_persona_groups_np(const posix_spawnattr_t * __restrict attr, if (gidarray == NULL) return EINVAL; - if (ngroups > NGROUPS) + if (ngroups > NGROUPS || ngroups < 0) return EINVAL; psattr = *(_posix_spawnattr_t *)attr; diff --git a/osfmk/kern/clock.c b/osfmk/kern/clock.c index d601291b6..9bd9f3b0e 100644 --- a/osfmk/kern/clock.c +++ b/osfmk/kern/clock.c @@ -400,7 +400,7 @@ mach_timebase_info_trap( struct mach_timebase_info_trap_args *args) { mach_vm_address_t out_info_addr = args->info; - mach_timebase_info_data_t info; + mach_timebase_info_data_t info = {}; clock_timebase_info(&info); diff --git a/osfmk/kern/clock_oldops.c b/osfmk/kern/clock_oldops.c index 28da75b50..bc7357560 100644 --- a/osfmk/kern/clock_oldops.c +++ b/osfmk/kern/clock_oldops.c @@ -499,7 +499,7 @@ clock_sleep_trap( int sleep_nsec = args->sleep_nsec; mach_vm_address_t wakeup_time_addr = args->wakeup_time; clock_t clock; - mach_timespec_t swtime; + mach_timespec_t swtime = {}; kern_return_t rvalue; /* diff --git a/osfmk/kern/task.c b/osfmk/kern/task.c index d58d29cdb..cb3a359b5 100644 --- a/osfmk/kern/task.c +++ b/osfmk/kern/task.c @@ -500,6 +500,25 @@ task_wait_to_return(void) thread_bootstrap_return(); } +#ifdef CONFIG_32BIT_TELEMETRY +boolean_t +task_consume_32bit_log_flag(task_t task) +{ + if ((task->t_procflags & TPF_LOG_32BIT_TELEMETRY) != 0) { + task->t_procflags &= ~TPF_LOG_32BIT_TELEMETRY; + return TRUE; + } else { + return FALSE; + } +} + +void +task_set_32bit_log_flag(task_t task) +{ + task->t_procflags |= TPF_LOG_32BIT_TELEMETRY; +} +#endif /* CONFIG_32BIT_TELEMETRY */ + boolean_t task_is_exec_copy(task_t task) { diff --git a/osfmk/kern/task.h b/osfmk/kern/task.h index 847120f95..352c50450 100644 --- a/osfmk/kern/task.h +++ b/osfmk/kern/task.h @@ -288,6 +288,9 @@ struct task { #define TPF_NONE 0 #define TPF_DID_EXEC 0x00000001 /* task has been execed to a new task */ #define TPF_EXEC_COPY 0x00000002 /* task is the new copy of an exec */ +#ifdef CONFIG_32BIT_TELEMETRY +#define TPF_LOG_32BIT_TELEMETRY 0x00000004 /* task should log identifying information */ +#endif #define task_did_exec_internal(task) \ (((task)->t_procflags & TPF_DID_EXEC) != 0) @@ -742,6 +745,10 @@ extern void task_set_did_exec_flag(task_t task); extern void task_clear_exec_copy_flag(task_t task); extern boolean_t task_is_exec_copy(task_t); extern boolean_t task_did_exec(task_t task); +#ifdef CONFIG_32BIT_TELEMETRY +extern boolean_t task_consume_32bit_log_flag(task_t task); +extern void task_set_32bit_log_flag(task_t task); +#endif /* CONFIG_32BIT_TELEMETRY */ extern boolean_t task_is_active(task_t task); extern boolean_t task_is_halting(task_t task); extern void task_clear_return_wait(task_t task); diff --git a/security/mac_base.c b/security/mac_base.c index ec5955df8..2bd03b8eb 100644 --- a/security/mac_base.c +++ b/security/mac_base.c @@ -2026,4 +2026,10 @@ int mac_iokit_check_nvram_set(kauth_cred_t cred __unused, const char *name __unu return 0; } +int mac_vnode_check_trigger_resolve(vfs_context_t ctx __unused, struct vnode *dvp __unused, struct componentname *cnp __unused); +int mac_vnode_check_trigger_resolve(vfs_context_t ctx __unused, struct vnode *dvp __unused, struct componentname *cnp __unused) +{ + return 0; +} + #endif /* !MAC */ diff --git a/security/mac_framework.h b/security/mac_framework.h index b5560a320..81a4839c8 100644 --- a/security/mac_framework.h +++ b/security/mac_framework.h @@ -534,11 +534,13 @@ int mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, int mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp, struct timespec atime, struct timespec mtime); int mac_vnode_check_signature(struct vnode *vp, - struct cs_blob *cs_blob, struct image_params *imgp, - unsigned int *cs_flags, unsigned int *signer_type, - int flags); + struct cs_blob *cs_blob, struct image_params *imgp, + unsigned int *cs_flags, unsigned int *signer_type, + int flags); int mac_vnode_check_stat(vfs_context_t ctx, kauth_cred_t file_cred, struct vnode *vp); +int mac_vnode_check_trigger_resolve(vfs_context_t ctx, struct vnode *dvp, + struct componentname *cnp); int mac_vnode_check_truncate(vfs_context_t ctx, kauth_cred_t file_cred, struct vnode *vp); int mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp, diff --git a/security/mac_policy.h b/security/mac_policy.h index eedfeab13..e656f8393 100644 --- a/security/mac_policy.h +++ b/security/mac_policy.h @@ -5431,6 +5431,27 @@ typedef int mpo_vnode_check_stat_t( struct vnode *vp, struct label *label ); +/** + @brief Access control check for vnode trigger resolution + @param cred Subject credential + @param dvp Object vnode + @param dlabel Policy label for dvp + @param cnp Component name that triggered resolution + + Determine whether the subject identified by the credential can trigger + resolution of the passed name (cnp) in the passed directory vnode + via an external trigger resolver. + + @return Return 0 if access is granted, otherwise an appropriate value for + errno should be returned. Suggested failure: EACCES for label mismatch or + EPERM for lack of privilege. +*/ +typedef int mpo_vnode_check_trigger_resolve_t( + kauth_cred_t cred, + struct vnode *dvp, + struct label *dlabel, + struct componentname *cnp +); /** @brief Access control check for truncate/ftruncate @param active_cred Subject credential @@ -6301,7 +6322,7 @@ typedef void mpo_reserved_hook_t(void); * Please note that this should be kept in sync with the check assumptions * policy in bsd/kern/policy_check.c (policy_ops struct). */ -#define MAC_POLICY_OPS_VERSION 52 /* inc when new reserved slots are taken */ +#define MAC_POLICY_OPS_VERSION 53 /* inc when new reserved slots are taken */ struct mac_policy_ops { mpo_audit_check_postselect_t *mpo_audit_check_postselect; mpo_audit_check_preselect_t *mpo_audit_check_preselect; @@ -6453,10 +6474,10 @@ struct mac_policy_ops { mpo_exc_action_label_init_t *mpo_exc_action_label_init; mpo_exc_action_label_update_t *mpo_exc_action_label_update; + mpo_vnode_check_trigger_resolve_t *mpo_vnode_check_trigger_resolve; mpo_reserved_hook_t *mpo_reserved1; mpo_reserved_hook_t *mpo_reserved2; mpo_reserved_hook_t *mpo_reserved3; - mpo_reserved_hook_t *mpo_reserved4; mpo_skywalk_flow_check_connect_t *mpo_skywalk_flow_check_connect; mpo_skywalk_flow_check_listen_t *mpo_skywalk_flow_check_listen; diff --git a/security/mac_vfs.c b/security/mac_vfs.c index 0d55a1c27..9c9b36c66 100644 --- a/security/mac_vfs.c +++ b/security/mac_vfs.c @@ -1699,6 +1699,25 @@ mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred, return (error); } +int +mac_vnode_check_trigger_resolve(vfs_context_t ctx, struct vnode *dvp, + struct componentname *cnp) +{ + kauth_cred_t cred; + int error; + +#if SECURITY_MAC_CHECK_ENFORCE + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) + return 0; +#endif + cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) + return (0); + MAC_CHECK(vnode_check_trigger_resolve, cred, dvp, dvp->v_label, cnp); + return (error); +} + int mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred, struct vnode *vp) diff --git a/tools/tests/darwintests/socket_bind_35243417.c b/tools/tests/darwintests/socket_bind_35243417.c new file mode 100644 index 000000000..de5eed5d5 --- /dev/null +++ b/tools/tests/darwintests/socket_bind_35243417.c @@ -0,0 +1,116 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int +sockv6_open(void) +{ + int s; + + s = socket(AF_INET6, SOCK_DGRAM, 0); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(s, "socket(AF_INET6, SOCK_DGRAM, 0)"); + return (s); +} + +static int +sockv6_bind(int s, in_port_t port) +{ + struct sockaddr_in6 sin6; + + bzero(&sin6, sizeof(sin6)); + sin6.sin6_len = sizeof(sin6); + sin6.sin6_family = AF_INET6; + sin6.sin6_port = port; + return (bind(s, (const struct sockaddr *)&sin6, sizeof(sin6))); +} + +static void +sockv6_set_v6only(int s) +{ + int on = 1; + int ret; + + ret = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(ret, "setsockopt(%d, IPV6_ONLY)", s); +} + +static bool +alloc_and_bind_ports(in_port_t port_start, in_port_t port_end, + int bind_attempts) +{ + int bound_count = 0; + bool success = true; + + for (in_port_t i = port_start; success && i <= port_end; i++) { + int s6 = -1; + int s6_other = -1; + int ret; + + s6 = sockv6_open(); + sockv6_set_v6only(s6); + if (sockv6_bind(s6, i) != 0) { + /* find the next available port */ + goto loop_done; + } + s6_other = sockv6_open(); + ret = sockv6_bind(s6_other, i); + T_WITH_ERRNO; + T_QUIET; + T_ASSERT_TRUE(ret != 0, "socket %d bind %d", s6_other, i); + /* + * After bind fails, try binding to a different port. + * For non-root user, this will panic without the fix for + * . + */ + if (sockv6_bind(s6_other, i + 1) == 0) { + bound_count++; + if (bound_count >= bind_attempts) { + break; + } + } + loop_done: + if (s6 >= 0) { + close(s6); + } + if (s6_other >= 0) { + close(s6_other); + } + } + T_ASSERT_TRUE(bound_count == bind_attempts, + "number of successful binds %d (out of %d)", + bound_count, bind_attempts); + return (success); +} + + +T_DECL(socket_bind_35243417, + "bind IPv6 only UDP socket, then bind IPv6 socket.", + T_META_ASROOT(false), + T_META_CHECK_LEAKS(false)) +{ +#if TARGET_OS_WATCH + T_SKIP("socket_bind_35243417 can't run on watch."); +#else + alloc_and_bind_ports(1, 65534, 10); +#endif +} + +T_DECL(socket_bind_35243417_root, + "bind IPv6 only UDP socket, then bind IPv6 socket.", + T_META_ASROOT(true)) +{ +#if TARGET_OS_WATCH + T_SKIP("socket_bind_35243417_root can't run on watch."); +#else + alloc_and_bind_ports(1, 65534, 10); +#endif +} diff --git a/tools/tests/personas/persona_mgr.c b/tools/tests/personas/persona_mgr.c index f6776c873..5da9f5bff 100644 --- a/tools/tests/personas/persona_mgr.c +++ b/tools/tests/personas/persona_mgr.c @@ -219,8 +219,10 @@ int main(int argc, char **argv) break; case 'u': ret = atoi(optarg); - if (ret <= 0) - err("Invalid UID: %s", optarg); + /* allow invalid / -1 as a wildcard for lookup */ + if (ret < 0 && persona_op != PERSONA_OP_LOOKUP) { + err("Invalid UID:%s (%d)", optarg, ret); + } uid = (uid_t)ret; break; case 'g': @@ -255,7 +257,7 @@ int main(int argc, char **argv) } } - if (uid == (uid_t)-1) + if (uid == (uid_t)-1 && persona_op != PERSONA_OP_LOOKUP) uid = kinfo.persona_id; if (kinfo.persona_gmuid && kinfo.persona_ngroups == 0) { -- 2.45.2