X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6d2010ae8f7a6078e10b361c6962983bab233e0f..bd504ef0e0b883cdd7917b73b3574eb9ce669905:/bsd/kern/kern_proc.c?ds=sidebyside diff --git a/bsd/kern/kern_proc.c b/bsd/kern/kern_proc.c index 042a3a864..6d696b424 100644 --- a/bsd/kern/kern_proc.c +++ b/bsd/kern/kern_proc.c @@ -103,6 +103,7 @@ #include #include /* vm_map_switch_protect() */ #include +#include #if CONFIG_MACF #include @@ -174,6 +175,7 @@ static void pgrp_remove(proc_t p); static void pgrp_replace(proc_t p, struct pgrp *pgrp); static void pgdelete_dropref(struct pgrp *pgrp); extern void pg_rele_dropref(struct pgrp * pgrp); +static int csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaddittoken); struct fixjob_iterargs { struct pgrp * pg; @@ -353,6 +355,23 @@ proc_findinternal(int pid, int locked) return(p); } +proc_t +proc_findthread(thread_t thread) +{ + proc_t p = PROC_NULL; + struct uthread *uth; + + proc_list_lock(); + uth = get_bsdthread_info(thread); + if (uth && (uth->uu_flag & UT_VFORK)) + p = uth->uu_proc; + else + p = (proc_t)(get_bsdthreadtask_info(thread)); + p = proc_ref_locked(p); + proc_list_unlock(); + return(p); +} + int proc_rele(proc_t p) { @@ -733,6 +752,12 @@ proc_suser(proc_t p) return(error); } +task_t +proc_task(proc_t proc) +{ + return (task_t)proc->task; +} + /* * Obtain the first thread in a process * @@ -1686,10 +1711,31 @@ SYSCTL_INT(_kern_lctx, OID_AUTO, max, CTLFLAG_RW | CTLFLAG_LOCKED, &maxlcid, 0, int csops(__unused proc_t p, struct csops_args *uap, __unused int32_t *retval) { - int ops = uap->ops; - pid_t pid = uap->pid; - user_addr_t uaddr = uap->useraddr; - size_t usize = (size_t)CAST_DOWN(size_t, uap->usersize); + return(csops_internal(uap->pid, uap->ops, uap->useraddr, + uap->usersize, USER_ADDR_NULL)); +} + +int +csops_audittoken(__unused proc_t p, struct csops_audittoken_args *uap, __unused int32_t *retval) +{ + if (uap->uaudittoken == USER_ADDR_NULL) + return(EINVAL); + switch (uap->ops) { + case CS_OPS_PIDPATH: + case CS_OPS_ENTITLEMENTS_BLOB: + break; + default: + return(EINVAL); + }; + + return(csops_internal(uap->pid, uap->ops, uap->useraddr, + uap->usersize, uap->uaudittoken)); +} + +static int +csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaudittoken) +{ + size_t usize = (size_t)CAST_DOWN(size_t, usersize); proc_t pt; uint32_t retflags; int vid, forself; @@ -1698,6 +1744,8 @@ csops(__unused proc_t p, struct csops_args *uap, __unused int32_t *retval) off_t toff; char * buf; unsigned char cdhash[SHA1_RESULTLEN]; + audit_token_t token; + unsigned int upid=0, uidversion = 0; forself = error = 0; @@ -1714,15 +1762,37 @@ csops(__unused proc_t p, struct csops_args *uap, __unused int32_t *retval) return(EOVERFLOW); if (kauth_cred_issuser(kauth_cred_get()) != TRUE) return(EPERM); - } else if ((forself == 0) && ((ops != CS_OPS_STATUS) && (ops != CS_OPS_CDHASH) && (ops != CS_OPS_PIDOFFSET) && (kauth_cred_issuser(kauth_cred_get()) != TRUE))) { - return(EPERM); + } else { + switch (ops) { + case CS_OPS_STATUS: + case CS_OPS_CDHASH: + case CS_OPS_PIDOFFSET: + case CS_OPS_ENTITLEMENTS_BLOB: + break; /* unrestricted */ + default: + if (forself == 0 && kauth_cred_issuser(kauth_cred_get()) != TRUE) + return(EPERM); + break; + } } pt = proc_find(pid); if (pt == PROC_NULL) return(ESRCH); - + upid = pt->p_pid; + uidversion = pt->p_idversion; + if (uaudittoken != USER_ADDR_NULL) { + + error = copyin(uaudittoken, &token, sizeof(audit_token_t)); + if (error != 0) + goto out; + /* verify the audit token pid/idversion matches with proc */ + if ((token.val[5] != upid) || (token.val[7] != uidversion)) { + error = ESRCH; + goto out; + } + } switch (ops) { @@ -1833,20 +1903,34 @@ csops(__unused proc_t p, struct csops_args *uap, __unused int32_t *retval) return error; case CS_OPS_ENTITLEMENTS_BLOB: { - char zeros[8] = { 0 }; + char fakeheader[8] = { 0 }; void *start; size_t length; - if (0 != (error = cs_entitlements_blob_get(pt, - &start, &length))) + if ((pt->p_csflags & CS_VALID) == 0) { + error = EINVAL; break; - if (usize < sizeof(zeros) || usize < length) { + } + if (usize < sizeof(fakeheader)) { error = ERANGE; break; } + if (0 != (error = cs_entitlements_blob_get(pt, + &start, &length))) + break; + /* if no entitlement, fill in zero header */ if (NULL == start) { - start = zeros; - length = sizeof(zeros); + start = fakeheader; + length = sizeof(fakeheader); + } else if (usize < length) { + /* ... if input too short, copy out length of entitlement */ + uint32_t length32 = htonl((uint32_t)length); + memcpy(&fakeheader[4], &length32, sizeof(length32)); + + error = copyout(fakeheader, uaddr, sizeof(fakeheader)); + if (error == 0) + error = ERANGE; /* input buffer to short, ERANGE signals that */ + break; } error = copyout(start, uaddr, length); break; @@ -1867,7 +1951,6 @@ out: return(error); } - int proc_iterate(flags, callout, arg, filterfn, filterarg) int flags; @@ -2679,9 +2762,11 @@ cs_invalid_page( if (p->p_csflags & CS_KILL) { p->p_csflags |= CS_KILLED; proc_unlock(p); - printf("CODE SIGNING: cs_invalid_page(0x%llx): " - "p=%d[%s] honoring CS_KILL, final status 0x%x\n", - vaddr, p->p_pid, p->p_comm, p->p_csflags); + if (cs_debug) { + printf("CODE SIGNING: cs_invalid_page(0x%llx): " + "p=%d[%s] honoring CS_KILL, final status 0x%x\n", + vaddr, p->p_pid, p->p_comm, p->p_csflags); + } cs_procs_killed++; psignal(p, SIGKILL); proc_lock(p); @@ -2690,9 +2775,11 @@ cs_invalid_page( /* CS_HARD means fail the mapping operation so the process stays valid. */ if (p->p_csflags & CS_HARD) { proc_unlock(p); - printf("CODE SIGNING: cs_invalid_page(0x%llx): " - "p=%d[%s] honoring CS_HARD\n", - vaddr, p->p_pid, p->p_comm); + if (cs_debug) { + printf("CODE SIGNING: cs_invalid_page(0x%llx): " + "p=%d[%s] honoring CS_HARD\n", + vaddr, p->p_pid, p->p_comm); + } retval = 1; } else { if (p->p_csflags & CS_VALID) {