Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/sys_process.c
Show First 20 Lines • Show All 682 Lines • ▼ Show 20 Lines | |||||
#define PROC_READ(w, t, a) proc_read_ ## w (t, a) | #define PROC_READ(w, t, a) proc_read_ ## w (t, a) | ||||
#define PROC_WRITE(w, t, a) proc_write_ ## w (t, a) | #define PROC_WRITE(w, t, a) proc_write_ ## w (t, a) | ||||
#endif | #endif | ||||
void | void | ||||
proc_set_traced(struct proc *p, bool stop) | proc_set_traced(struct proc *p, bool stop) | ||||
{ | { | ||||
sx_assert(&proctree_lock, SX_XLOCKED); | sx_assert(&V_proctree_lock, SX_XLOCKED); | ||||
PROC_LOCK_ASSERT(p, MA_OWNED); | PROC_LOCK_ASSERT(p, MA_OWNED); | ||||
p->p_flag |= P_TRACED; | p->p_flag |= P_TRACED; | ||||
if (stop) | if (stop) | ||||
p->p_flag2 |= P2_PTRACE_FSTP; | p->p_flag2 |= P2_PTRACE_FSTP; | ||||
p->p_ptevents = PTRACE_DEFAULT; | p->p_ptevents = PTRACE_DEFAULT; | ||||
p->p_oppid = p->p_pptr->p_pid; | p->p_oppid = p->p_pptr->p_pid; | ||||
} | } | ||||
Show All 28 Lines | #endif | ||||
case PT_TO_SCX: | case PT_TO_SCX: | ||||
case PT_SYSCALL: | case PT_SYSCALL: | ||||
case PT_FOLLOW_FORK: | case PT_FOLLOW_FORK: | ||||
case PT_LWP_EVENTS: | case PT_LWP_EVENTS: | ||||
case PT_GET_EVENT_MASK: | case PT_GET_EVENT_MASK: | ||||
case PT_SET_EVENT_MASK: | case PT_SET_EVENT_MASK: | ||||
case PT_DETACH: | case PT_DETACH: | ||||
case PT_GET_SC_ARGS: | case PT_GET_SC_ARGS: | ||||
sx_xlock(&proctree_lock); | sx_xlock(&V_proctree_lock); | ||||
proctree_locked = 1; | proctree_locked = 1; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
if (req == PT_TRACE_ME) { | if (req == PT_TRACE_ME) { | ||||
p = td->td_proc; | p = td->td_proc; | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
} else { | } else { | ||||
if (pid <= PID_MAX) { | if (pid <= PID_MAX) { | ||||
if ((p = pfind(pid)) == NULL) { | if ((p = pfind(pid)) == NULL) { | ||||
if (proctree_locked) | if (proctree_locked) | ||||
sx_xunlock(&proctree_lock); | sx_xunlock(&V_proctree_lock); | ||||
return (ESRCH); | return (ESRCH); | ||||
} | } | ||||
} else { | } else { | ||||
td2 = tdfind(pid, -1); | td2 = tdfind(pid, -1); | ||||
if (td2 == NULL) { | if (td2 == NULL) { | ||||
if (proctree_locked) | if (proctree_locked) | ||||
sx_xunlock(&proctree_lock); | sx_xunlock(&V_proctree_lock); | ||||
return (ESRCH); | return (ESRCH); | ||||
} | } | ||||
p = td2->td_proc; | p = td2->td_proc; | ||||
tid = pid; | tid = pid; | ||||
pid = p->p_pid; | pid = p->p_pid; | ||||
} | } | ||||
} | } | ||||
AUDIT_ARG_PROCESS(p); | AUDIT_ARG_PROCESS(p); | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | case PT_TRACE_ME: | ||||
/* | /* | ||||
* Always legal, when there is a parent process which | * Always legal, when there is a parent process which | ||||
* could trace us. Otherwise, reject. | * could trace us. Otherwise, reject. | ||||
*/ | */ | ||||
if ((p->p_flag & P_TRACED) != 0) { | if ((p->p_flag & P_TRACED) != 0) { | ||||
error = EBUSY; | error = EBUSY; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
if (p->p_pptr == initproc) { | if (p->p_pptr == V_initproc) { | ||||
error = EPERM; | error = EPERM; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
break; | break; | ||||
case PT_ATTACH: | case PT_ATTACH: | ||||
/* Self */ | /* Self */ | ||||
if (p == td->td_proc) { | if (p == td->td_proc) { | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | case PT_ATTACH: | ||||
*/ | */ | ||||
proc_set_traced(p, true); | proc_set_traced(p, true); | ||||
if (p->p_pptr != td->td_proc) { | if (p->p_pptr != td->td_proc) { | ||||
proc_reparent(p, td->td_proc); | proc_reparent(p, td->td_proc); | ||||
} | } | ||||
CTR2(KTR_PTRACE, "PT_ATTACH: pid %d, oppid %d", p->p_pid, | CTR2(KTR_PTRACE, "PT_ATTACH: pid %d, oppid %d", p->p_pid, | ||||
p->p_oppid); | p->p_oppid); | ||||
sx_xunlock(&proctree_lock); | sx_xunlock(&V_proctree_lock); | ||||
proctree_locked = 0; | proctree_locked = 0; | ||||
MPASS(p->p_xthread == NULL); | MPASS(p->p_xthread == NULL); | ||||
MPASS((p->p_flag & P_STOPPED_TRACE) == 0); | MPASS((p->p_flag & P_STOPPED_TRACE) == 0); | ||||
/* | /* | ||||
* If already stopped due to a stop signal, clear the | * If already stopped due to a stop signal, clear the | ||||
* existing stop before triggering a traced SIGSTOP. | * existing stop before triggering a traced SIGSTOP. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 173 Lines • ▼ Show 20 Lines | case PT_DETACH: | ||||
p->p_flag &= ~(P_TRACED | P_WAITED); | p->p_flag &= ~(P_TRACED | P_WAITED); | ||||
if (p->p_oppid != p->p_pptr->p_pid) { | if (p->p_oppid != p->p_pptr->p_pid) { | ||||
PROC_LOCK(p->p_pptr); | PROC_LOCK(p->p_pptr); | ||||
sigqueue_take(p->p_ksi); | sigqueue_take(p->p_ksi); | ||||
PROC_UNLOCK(p->p_pptr); | PROC_UNLOCK(p->p_pptr); | ||||
pp = proc_realparent(p); | pp = proc_realparent(p); | ||||
proc_reparent(p, pp); | proc_reparent(p, pp); | ||||
if (pp == initproc) | if (pp == V_initproc) | ||||
p->p_sigparent = SIGCHLD; | p->p_sigparent = SIGCHLD; | ||||
CTR3(KTR_PTRACE, | CTR3(KTR_PTRACE, | ||||
"PT_DETACH: pid %d reparented to pid %d, sig %d", | "PT_DETACH: pid %d reparented to pid %d, sig %d", | ||||
p->p_pid, pp->p_pid, data); | p->p_pid, pp->p_pid, data); | ||||
} else | } else | ||||
CTR2(KTR_PTRACE, "PT_DETACH: pid %d, sig %d", | CTR2(KTR_PTRACE, "PT_DETACH: pid %d, sig %d", | ||||
p->p_pid, data); | p->p_pid, data); | ||||
p->p_oppid = 0; | p->p_oppid = 0; | ||||
Show All 12 Lines | case PT_DETACH: | ||||
p->p_flag2 &= ~P2_PTRACE_FSTP; | p->p_flag2 &= ~P2_PTRACE_FSTP; | ||||
} | } | ||||
/* should we send SIGCHLD? */ | /* should we send SIGCHLD? */ | ||||
/* childproc_continued(p); */ | /* childproc_continued(p); */ | ||||
break; | break; | ||||
} | } | ||||
sx_xunlock(&proctree_lock); | sx_xunlock(&V_proctree_lock); | ||||
proctree_locked = 0; | proctree_locked = 0; | ||||
sendsig: | sendsig: | ||||
MPASS(proctree_locked == 0); | MPASS(proctree_locked == 0); | ||||
/* | /* | ||||
* Clear the pending event for the thread that just | * Clear the pending event for the thread that just | ||||
* reported its event (p_xthread). This may not be | * reported its event (p_xthread). This may not be | ||||
▲ Show 20 Lines • Show All 297 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
out: | out: | ||||
/* Drop our hold on this process now that the request has completed. */ | /* Drop our hold on this process now that the request has completed. */ | ||||
_PRELE(p); | _PRELE(p); | ||||
fail: | fail: | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
if (proctree_locked) | if (proctree_locked) | ||||
sx_xunlock(&proctree_lock); | sx_xunlock(&V_proctree_lock); | ||||
return (error); | return (error); | ||||
} | } | ||||
#undef PROC_READ | #undef PROC_READ | ||||
#undef PROC_WRITE | #undef PROC_WRITE | ||||
/* | /* | ||||
* Stop a process because of a debugging event; | * Stop a process because of a debugging event; | ||||
* stay stopped until p->p_step is cleared | * stay stopped until p->p_step is cleared | ||||
Show All 19 Lines |