X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..5eebf7385fedb1517b66b53c28e5aa6bb0a2be50:/bsd/kern/mach_process.c diff --git a/bsd/kern/mach_process.c b/bsd/kern/mach_process.c index 284e21a88..8c0567ea1 100644 --- a/bsd/kern/mach_process.c +++ b/bsd/kern/mach_process.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -59,12 +59,6 @@ * * from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93 */ -/* - * HISTORY - * - * 10-Jun-97 Umesh Vaishampayan (umeshv@apple.com) - * Ported to PPC. Cleaned up the architecture specific code. - */ #include #include @@ -77,9 +71,12 @@ #include #include #include +#include #include +#include + #include #include #include @@ -89,7 +86,8 @@ #define CLR(t, f) (t) &= ~(f) #define ISSET(t, f) ((t) & (f)) -void psignal_lock __P((struct proc *, int, int, int)); +void psignal_lock __P((struct proc *, int, int)); + /* * sys-trace system call. */ @@ -99,6 +97,7 @@ struct ptrace_args { caddr_t addr; int data; }; + int ptrace(p, uap, retval) struct proc *p; @@ -109,7 +108,6 @@ ptrace(p, uap, retval) vm_offset_t start_addr, end_addr, kern_addr, offset; vm_size_t size; - boolean_t change_protection; task_t task; thread_t thread; thread_act_t th_act; @@ -117,14 +115,40 @@ ptrace(p, uap, retval) int *locr0; int error = 0; #if defined(ppc) - struct ppc_saved_state statep; + struct ppc_thread_state64 statep; #elif defined(i386) struct i386_saved_state statep; #else #error architecture not supported #endif unsigned long state_count; + int tr_sigexc = 0; + AUDIT_ARG(cmd, uap->req); + AUDIT_ARG(pid, uap->pid); + AUDIT_ARG(addr, uap->addr); + AUDIT_ARG(value, uap->data); + + if (uap->req == PT_DENY_ATTACH) { + if (ISSET(p->p_flag, P_TRACED)) { + exit1(p, W_EXITCODE(ENOTSUP, 0), retval); + /* drop funnel before we return */ + thread_funnel_set(kernel_flock, FALSE); + thread_exception_return(); + /* NOTREACHED */ + } + SET(p->p_flag, P_NOATTACH); + + return(0); + } + + if (uap->req == PT_FORCEQUOTA) { + if (is_suser()) { + SET(t->p_flag, P_FORCEQUOTA); + return (0); + } else + return (EPERM); + } /* * Intercept and deal with "please trace me" request. @@ -135,6 +159,13 @@ ptrace(p, uap, retval) t->p_oppid = t->p_pptr->p_pid; return(0); } + if (uap->req == PT_SIGEXC) { + if (ISSET(p->p_flag, P_TRACED)) { + SET(p->p_flag, P_SIGEXC); + return(0); + } else + return(EINVAL); + } /* * Locate victim, and make sure it is traceable. @@ -143,6 +174,8 @@ ptrace(p, uap, retval) return (ESRCH); + AUDIT_ARG(process, t); + /* We do not want ptrace to do anything with kernel, init * and mach_init */ @@ -150,6 +183,10 @@ ptrace(p, uap, retval) return (EPERM); task = t->task; + if (uap->req == PT_ATTACHEXC) { + uap->req = PT_ATTACH; + tr_sigexc = 1; + } if (uap->req == PT_ATTACH) { /* @@ -174,7 +211,17 @@ ptrace(p, uap, retval) (error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error); + if ((p->p_flag & P_TRACED) && isinferior(p, t)) + return(EPERM); + + if (ISSET(t->p_flag, P_NOATTACH)) { + psignal(p, SIGSEGV); + return (EBUSY); + } SET(t->p_flag, P_TRACED); + if (tr_sigexc) + SET(t->p_flag, P_SIGEXC); + t->p_oppid = t->p_pptr->p_pid; if (t->p_pptr != p) proc_reparent(t, p); @@ -224,6 +271,7 @@ ptrace(p, uap, retval) t->p_oppid = 0; CLR(t->p_flag, P_TRACED); + CLR(t->p_flag, P_SIGEXC); goto resume; case PT_KILL: @@ -231,24 +279,24 @@ ptrace(p, uap, retval) * Tell child process to kill itself after it * is resumed by adding NSIG to p_cursig. [see issig] */ - psignal_lock(t, SIGKILL, 0, 1); + psignal_lock(t, SIGKILL, 0); goto resume; case PT_STEP: /* single step the child */ case PT_CONTINUE: /* continue the child */ th_act = (thread_act_t)get_firstthread(task); - if (th_act == THREAD_NULL) + if (th_act == THR_ACT_NULL) goto errorLabel; ut = (uthread_t)get_bsdthread_info(th_act); locr0 = ut->uu_ar0; #if defined(i386) state_count = i386_NEW_THREAD_STATE_COUNT; - if (act_machine_get_state(th_act, i386_NEW_THREAD_STATE, &statep, &state_count) != KERN_SUCCESS) { + if (thread_getstatus(th_act, i386_NEW_THREAD_STATE, &statep, &state_count) != KERN_SUCCESS) { goto errorLabel; } #elif defined(ppc) - state_count = PPC_THREAD_STATE_COUNT; - if (act_machine_get_state(th_act, PPC_THREAD_STATE, &statep, &state_count) != KERN_SUCCESS) { + state_count = PPC_THREAD_STATE64_COUNT; + if (thread_getstatus(th_act, PPC_THREAD_STATE64, &statep, &state_count) != KERN_SUCCESS) { goto errorLabel; } #else @@ -262,9 +310,9 @@ ptrace(p, uap, retval) if (!ALIGNED((int)uap->addr, sizeof(int))) return (ERESTART); - statep.srr0 = (int)uap->addr; - state_count = PPC_THREAD_STATE_COUNT; - if (act_machine_set_state(th_act, PPC_THREAD_STATE, &statep, &state_count) != KERN_SUCCESS) { + statep.srr0 = (uint64_t)((uint32_t)uap->addr); + state_count = PPC_THREAD_STATE64_COUNT; + if (thread_setstatus(th_act, PPC_THREAD_STATE64, &statep, &state_count) != KERN_SUCCESS) { goto errorLabel; } #undef ALIGNED @@ -277,11 +325,11 @@ ptrace(p, uap, retval) goto errorLabel; if (uap->data != 0) { - psignal_lock(t, uap->data, 0, 1); + psignal_lock(t, uap->data, 0); } #if defined(ppc) - state_count = PPC_THREAD_STATE_COUNT; - if (act_machine_get_state(th_act, PPC_THREAD_STATE, &statep, &state_count) != KERN_SUCCESS) { + state_count = PPC_THREAD_STATE64_COUNT; + if (thread_getstatus(th_act, PPC_THREAD_STATE64, &statep, &state_count) != KERN_SUCCESS) { goto errorLabel; } #endif @@ -305,8 +353,8 @@ ptrace(p, uap, retval) #endif } #if defined (ppc) - state_count = PPC_THREAD_STATE_COUNT; - if (act_machine_set_state(th_act, PPC_THREAD_STATE, &statep, &state_count) != KERN_SUCCESS) { + state_count = PPC_THREAD_STATE64_COUNT; + if (thread_setstatus(th_act, PPC_THREAD_STATE64, &statep, &state_count) != KERN_SUCCESS) { goto errorLabel; } #endif @@ -315,14 +363,33 @@ ptrace(p, uap, retval) t->p_stat = SRUN; if (t->sigwait) { wakeup((caddr_t)&(t->sigwait)); - task_release(task); + if ((t->p_flag & P_SIGEXC) == 0) + task_release(task); } break; + case PT_THUPDATE: { + thread_act_t target_act; + + if ((unsigned)uap->data >= NSIG) + goto errorLabel; + th_act = (thread_act_t)port_name_to_act((void *)uap->addr); + if (th_act == THR_ACT_NULL) + return (ESRCH); + ut = (uthread_t)get_bsdthread_info(th_act); + if (uap->data) + ut->uu_siglist |= sigmask(uap->data); + t->p_xstat = uap->data; + t->p_stat = SRUN; + act_deallocate(th_act); + return(0); + } + break; +errorLabel: default: - errorLabel: return(EINVAL); } + return(0); }