X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6d2010ae8f7a6078e10b361c6962983bab233e0f..e8c3f78193f1895ea514044358b93b1add9322f3:/bsd/kern/mach_process.c?ds=inline diff --git a/bsd/kern/mach_process.c b/bsd/kern/mach_process.c index 9aba89b96..72d262def 100644 --- a/bsd/kern/mach_process.c +++ b/bsd/kern/mach_process.c @@ -83,6 +83,7 @@ #include #include #include +#include /* cs_allow_invalid() */ #include @@ -92,10 +93,12 @@ #include /* for task_resume() */ #include /* for thread_exception_return() */ -#include /* cs_allow_invalid() */ - #include +#if CONFIG_MACF +#include +#endif + /* XXX ken/bsd_kern.c - prototype should be in common header */ int get_task_userstop(task_t); @@ -129,7 +132,7 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) AUDIT_ARG(value32, uap->data); if (uap->req == PT_DENY_ATTACH) { -#if (DEVELOPMENT || DEBUG) && defined(__arm__) +#if (DEVELOPMENT || DEBUG) && CONFIG_EMBEDDED if (PE_i_can_has_debugger(NULL)) return(0); #endif @@ -139,7 +142,7 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_PROC, BSD_PROC_FRCEXIT) | DBG_FUNC_NONE, p->p_pid, W_EXITCODE(ENOTSUP, 0), 4, 0, 0); exit1(p, W_EXITCODE(ENOTSUP, 0), retval); - /* drop funnel before we return */ + thread_exception_return(); /* NOTREACHED */ } @@ -150,7 +153,7 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) } if (uap->req == PT_FORCEQUOTA) { - if (is_suser()) { + if (kauth_cred_issuser(kauth_cred_get())) { OSBitOrAtomic(P_FORCEQUOTA, &t->p_flag); return (0); } else @@ -161,20 +164,38 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) * Intercept and deal with "please trace me" request. */ if (uap->req == PT_TRACE_ME) { - proc_lock(p); - SET(p->p_lflag, P_LTRACED); - /* Non-attached case, our tracer is our parent. */ - p->p_oppid = p->p_ppid; - /* Check whether child and parent are allowed to run modified - * code (they'll have to) */ - struct proc *pproc=proc_find(p->p_oppid); - proc_unlock(p); - cs_allow_invalid(p); - if(pproc) { +retry_trace_me:; + proc_t pproc = proc_parent(p); + if (pproc == NULL) + return (EINVAL); +#if CONFIG_MACF + /* + * NB: Cannot call kauth_authorize_process(..., KAUTH_PROCESS_CANTRACE, ...) + * since that assumes the process being checked is the current process + * when, in this case, it is the current process's parent. + * Most of the other checks in cantrace() don't apply either. + */ + if ((error = mac_proc_check_debug(pproc, p)) == 0) { +#endif + proc_lock(p); + /* Make sure the process wasn't re-parented. */ + if (p->p_ppid != pproc->p_pid) { + proc_unlock(p); + proc_rele(pproc); + goto retry_trace_me; + } + SET(p->p_lflag, P_LTRACED); + /* Non-attached case, our tracer is our parent. */ + p->p_oppid = p->p_ppid; + proc_unlock(p); + /* Child and parent will have to be able to run modified code. */ + cs_allow_invalid(p); cs_allow_invalid(pproc); - proc_rele(pproc); +#if CONFIG_MACF } - return(0); +#endif + proc_rele(pproc); + return (error); } if (uap->req == PT_SIGEXC) { proc_lock(p); @@ -205,12 +226,22 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) task = t->task; if (uap->req == PT_ATTACHEXC) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" uap->req = PT_ATTACH; tr_sigexc = 1; } if (uap->req == PT_ATTACH) { +#pragma clang diagnostic pop int err; - + +#if CONFIG_EMBEDDED + if (tr_sigexc == 0) { + error = ENOTSUP; + goto out; + } +#endif + if ( kauth_authorize_process(proc_ucred(p), KAUTH_PROCESS_CANTRACE, t, (uintptr_t)&err, 0, 0) == 0 ) { /* it's OK to attach */ @@ -298,11 +329,17 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) proc_unlock(t); pp = proc_find(t->p_oppid); - proc_reparentlocked(t, pp ? pp : initproc, 1, 0); - if (pp != PROC_NULL) + if (pp != PROC_NULL) { + proc_reparentlocked(t, pp, 1, 0); proc_rele(pp); + } else { + /* original parent exited while traced */ + proc_list_lock(); + t->p_listflag |= P_LIST_DEADPARENT; + proc_list_unlock(); + proc_reparentlocked(t, initproc, 1, 0); + } proc_lock(t); - } t->p_oppid = 0; @@ -317,6 +354,11 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) * is resumed by adding NSIG to p_cursig. [see issig] */ proc_unlock(t); +#if CONFIG_MACF + error = mac_proc_check_signal(p, t, SIGKILL); + if (0 != error) + goto resume; +#endif psignal(t, SIGKILL); goto resume; @@ -329,14 +371,10 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) goto out; } + /* force use of Mach SPIs (and task_for_pid security checks) to adjust PC */ if (uap->addr != (user_addr_t)1) { -#if defined(ppc) -#define ALIGNED(addr,size) (((unsigned)(addr)&((size)-1))==0) - if (!ALIGNED((int)uap->addr, sizeof(int))) - return (ERESTART); -#undef ALIGNED -#endif - thread_setentrypoint(th_act, uap->addr); + error = ENOTSUP; + goto out; } if ((unsigned)uap->data >= NSIG) { @@ -345,13 +383,25 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) } if (uap->data != 0) { +#if CONFIG_MACF + error = mac_proc_check_signal(p, t, uap->data); + if (0 != error) + goto out; +#endif psignal(t, uap->data); - } + } if (uap->req == PT_STEP) { /* - * set trace bit + * set trace bit + * we use sending SIGSTOP as a comparable security check. */ +#if CONFIG_MACF + error = mac_proc_check_signal(p, t, SIGSTOP); + if (0 != error) { + goto out; + } +#endif if (thread_setsinglestep(th_act, 1) != KERN_SUCCESS) { error = ENOTSUP; goto out; @@ -359,7 +409,14 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) } else { /* * clear trace bit if on + * we use sending SIGCONT as a comparable security check. */ +#if CONFIG_MACF + error = mac_proc_check_signal(p, t, SIGCONT); + if (0 != error) { + goto out; + } +#endif if (thread_setsinglestep(th_act, 0) != KERN_SUCCESS) { error = ENOTSUP; goto out; @@ -387,8 +444,10 @@ ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval) goto out; } th_act = port_name_to_thread(CAST_MACH_PORT_TO_NAME(uap->addr)); - if (th_act == THREAD_NULL) - return (ESRCH); + if (th_act == THREAD_NULL) { + error = ESRCH; + goto out; + } ut = (uthread_t)get_bsdthread_info(th_act); if (uap->data) ut->uu_siglist |= sigmask(uap->data); @@ -458,5 +517,13 @@ cantrace(proc_t cur_procp, kauth_cred_t creds, proc_t traced_procp, int *errp) *errp = EBUSY; return (0); } + +#if CONFIG_MACF + if ((my_err = mac_proc_check_debug(cur_procp, traced_procp)) != 0) { + *errp = my_err; + return (0); + } +#endif + return(1); }