MFC r303423:
Force SIGSTOP to be the first signal reported after the attach.
This commit is contained in:
parent
ad523ae767
commit
e7752c37e6
@ -347,6 +347,7 @@ the include file
|
||||
.In sys/proc.h :
|
||||
.Bl -column P2_INHERIT_PROTECTED 0x00000001
|
||||
.It Dv "P2_INHERIT_PROTECTED" Ta No "0x00000001" Ta "New children get P_PROTECTED"
|
||||
.It Dv "P2_PTRACE_FSTP" Ta No "0x00000010" Ta "SIGSTOP from PT_ATTACH not yet handled"
|
||||
.El
|
||||
.It Cm label
|
||||
The MAC label of the process.
|
||||
|
@ -520,9 +520,12 @@ exit1(struct thread *td, int rv)
|
||||
*/
|
||||
clear_orphan(q);
|
||||
q->p_flag &= ~(P_TRACED | P_STOPPED_TRACE);
|
||||
q->p_flag2 &= ~P2_PTRACE_FSTP;
|
||||
q->p_ptevents = 0;
|
||||
FOREACH_THREAD_IN_PROC(q, tdt)
|
||||
tdt->td_dbgflags &= ~TDB_SUSPEND;
|
||||
FOREACH_THREAD_IN_PROC(q, tdt) {
|
||||
tdt->td_dbgflags &= ~(TDB_SUSPEND | TDB_XSIG |
|
||||
TDB_FSTP);
|
||||
}
|
||||
kern_psignal(q, SIGKILL);
|
||||
}
|
||||
PROC_UNLOCK(q);
|
||||
|
@ -1063,15 +1063,13 @@ fork_return(struct thread *td, struct trapframe *frame)
|
||||
* parent's children, do it now.
|
||||
*/
|
||||
dbg = p->p_pptr->p_pptr;
|
||||
p->p_flag |= P_TRACED;
|
||||
p->p_ptevents = PTRACE_DEFAULT;
|
||||
p->p_oppid = p->p_pptr->p_pid;
|
||||
proc_set_traced(p);
|
||||
CTR2(KTR_PTRACE,
|
||||
"fork_return: attaching to new child pid %d: oppid %d",
|
||||
p->p_pid, p->p_oppid);
|
||||
proc_reparent(p, dbg);
|
||||
sx_xunlock(&proctree_lock);
|
||||
td->td_dbgflags |= TDB_CHILD | TDB_SCX;
|
||||
td->td_dbgflags |= TDB_CHILD | TDB_SCX | TDB_FSTP;
|
||||
ptracestop(td, SIGSTOP);
|
||||
td->td_dbgflags &= ~(TDB_CHILD | TDB_SCX);
|
||||
} else {
|
||||
|
@ -2499,14 +2499,26 @@ ptracestop(struct thread *td, int sig)
|
||||
PROC_SUNLOCK(p);
|
||||
return (sig);
|
||||
}
|
||||
|
||||
/*
|
||||
* Just make wait() to work, the last stopped thread
|
||||
* will win.
|
||||
* Make wait(2) work. Ensure that right after the
|
||||
* attach, the thread which was decided to become the
|
||||
* leader of attach gets reported to the waiter.
|
||||
* Otherwise, just avoid overwriting another thread's
|
||||
* assignment to p_xthread. If another thread has
|
||||
* already set p_xthread, the current thread will get
|
||||
* a chance to report itself upon the next iteration.
|
||||
*/
|
||||
p->p_xstat = sig;
|
||||
p->p_xthread = td;
|
||||
p->p_flag |= (P_STOPPED_SIG|P_STOPPED_TRACE);
|
||||
sig_suspend_threads(td, p, 0);
|
||||
if ((td->td_dbgflags & TDB_FSTP) != 0 ||
|
||||
((p->p_flag & P2_PTRACE_FSTP) == 0 &&
|
||||
p->p_xthread == NULL)) {
|
||||
p->p_xstat = sig;
|
||||
p->p_xthread = td;
|
||||
td->td_dbgflags &= ~TDB_FSTP;
|
||||
p->p_flag2 &= ~P2_PTRACE_FSTP;
|
||||
p->p_flag |= P_STOPPED_SIG | P_STOPPED_TRACE;
|
||||
sig_suspend_threads(td, p, 0);
|
||||
}
|
||||
if ((td->td_dbgflags & TDB_STOPATFORK) != 0) {
|
||||
td->td_dbgflags &= ~TDB_STOPATFORK;
|
||||
cv_broadcast(&p->p_dbgwait);
|
||||
@ -2657,7 +2669,20 @@ issignal(struct thread *td)
|
||||
SIG_STOPSIGMASK(sigpending);
|
||||
if (SIGISEMPTY(sigpending)) /* no signal to send */
|
||||
return (0);
|
||||
sig = sig_ffs(&sigpending);
|
||||
if ((p->p_flag & (P_TRACED | P_PPTRACE)) == P_TRACED &&
|
||||
(p->p_flag2 & P2_PTRACE_FSTP) != 0 &&
|
||||
SIGISMEMBER(sigpending, SIGSTOP)) {
|
||||
/*
|
||||
* If debugger just attached, always consume
|
||||
* SIGSTOP from ptrace(PT_ATTACH) first, to
|
||||
* execute the debugger attach ritual in
|
||||
* order.
|
||||
*/
|
||||
sig = SIGSTOP;
|
||||
td->td_dbgflags |= TDB_FSTP;
|
||||
} else {
|
||||
sig = sig_ffs(&sigpending);
|
||||
}
|
||||
|
||||
if (p->p_stops & S_SIG) {
|
||||
mtx_unlock(&ps->ps_mtx);
|
||||
@ -2674,7 +2699,7 @@ issignal(struct thread *td)
|
||||
sigqueue_delete(&p->p_sigqueue, sig);
|
||||
continue;
|
||||
}
|
||||
if (p->p_flag & P_TRACED && (p->p_flag & P_PPTRACE) == 0) {
|
||||
if ((p->p_flag & (P_TRACED | P_PPTRACE)) == P_TRACED) {
|
||||
/*
|
||||
* If traced, always stop.
|
||||
* Remove old signal from queue before the stop.
|
||||
@ -2772,6 +2797,8 @@ issignal(struct thread *td)
|
||||
mtx_unlock(&ps->ps_mtx);
|
||||
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
|
||||
&p->p_mtx.lock_object, "Catching SIGSTOP");
|
||||
sigqueue_delete(&td->td_sigqueue, sig);
|
||||
sigqueue_delete(&p->p_sigqueue, sig);
|
||||
p->p_flag |= P_STOPPED_SIG;
|
||||
p->p_xstat = sig;
|
||||
PROC_SLOCK(p);
|
||||
@ -2779,7 +2806,7 @@ issignal(struct thread *td)
|
||||
thread_suspend_switch(td, p);
|
||||
PROC_SUNLOCK(p);
|
||||
mtx_lock(&ps->ps_mtx);
|
||||
break;
|
||||
goto next;
|
||||
} else if (prop & SA_IGNORE) {
|
||||
/*
|
||||
* Except for SIGCONT, shouldn't get here.
|
||||
@ -2810,6 +2837,7 @@ issignal(struct thread *td)
|
||||
}
|
||||
sigqueue_delete(&td->td_sigqueue, sig); /* take the signal! */
|
||||
sigqueue_delete(&p->p_sigqueue, sig);
|
||||
next:;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
@ -648,6 +648,17 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
#define PROC_WRITE(w, t, a) proc_write_ ## w (t, a)
|
||||
#endif
|
||||
|
||||
void
|
||||
proc_set_traced(struct proc *p)
|
||||
{
|
||||
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
p->p_flag |= P_TRACED;
|
||||
p->p_flag2 |= P2_PTRACE_FSTP;
|
||||
p->p_ptevents = PTRACE_DEFAULT;
|
||||
p->p_oppid = p->p_pptr->p_pid;
|
||||
}
|
||||
|
||||
int
|
||||
kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
{
|
||||
@ -856,11 +867,9 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
switch (req) {
|
||||
case PT_TRACE_ME:
|
||||
/* set my trace flag and "owner" so it can read/write me */
|
||||
p->p_flag |= P_TRACED;
|
||||
p->p_ptevents = PTRACE_DEFAULT;
|
||||
proc_set_traced(p);
|
||||
if (p->p_flag & P_PPWAIT)
|
||||
p->p_flag |= P_PPTRACE;
|
||||
p->p_oppid = p->p_pptr->p_pid;
|
||||
CTR1(KTR_PTRACE, "PT_TRACE_ME: pid %d", p->p_pid);
|
||||
break;
|
||||
|
||||
@ -875,9 +884,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
* The old parent is remembered so we can put things back
|
||||
* on a "detach".
|
||||
*/
|
||||
p->p_flag |= P_TRACED;
|
||||
p->p_ptevents = PTRACE_DEFAULT;
|
||||
p->p_oppid = p->p_pptr->p_pid;
|
||||
proc_set_traced(p);
|
||||
if (p->p_pptr != td->td_proc) {
|
||||
proc_reparent(p, td->td_proc);
|
||||
}
|
||||
@ -1045,6 +1052,17 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
p->p_pid, data);
|
||||
p->p_oppid = 0;
|
||||
p->p_ptevents = 0;
|
||||
FOREACH_THREAD_IN_PROC(p, td3) {
|
||||
if ((td3->td_dbgflags & TDB_FSTP) != 0) {
|
||||
sigqueue_delete(&td3->td_sigqueue,
|
||||
SIGSTOP);
|
||||
}
|
||||
td3->td_dbgflags &= ~(TDB_XSIG | TDB_FSTP);
|
||||
}
|
||||
if ((p->p_flag2 & P2_PTRACE_FSTP) != 0) {
|
||||
sigqueue_delete(&p->p_sigqueue, SIGSTOP);
|
||||
p->p_flag2 &= ~P2_PTRACE_FSTP;
|
||||
}
|
||||
|
||||
/* should we send SIGCHLD? */
|
||||
/* childproc_continued(p); */
|
||||
@ -1065,7 +1083,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
|
||||
if (req == PT_DETACH) {
|
||||
FOREACH_THREAD_IN_PROC(p, td3)
|
||||
td3->td_dbgflags &= ~TDB_SUSPEND;
|
||||
td3->td_dbgflags &= ~TDB_SUSPEND;
|
||||
}
|
||||
/*
|
||||
* unsuspend all threads, to not let a thread run,
|
||||
|
@ -398,6 +398,7 @@ do { \
|
||||
#define TDB_CHILD 0x00000100 /* New child indicator for ptrace() */
|
||||
#define TDB_BORN 0x00000200 /* New LWP indicator for ptrace() */
|
||||
#define TDB_EXIT 0x00000400 /* Exiting LWP indicator for ptrace() */
|
||||
#define TDB_FSTP 0x00001000 /* The thread is PT_ATTACH leader */
|
||||
|
||||
/*
|
||||
* "Private" flags kept in td_pflags:
|
||||
@ -678,6 +679,7 @@ struct proc {
|
||||
#define P2_NOTRACE 0x00000002 /* No ptrace(2) attach or coredumps. */
|
||||
#define P2_NOTRACE_EXEC 0x00000004 /* Keep P2_NOPTRACE on exec(2). */
|
||||
#define P2_AST_SU 0x00000008 /* Handles SU ast for kthreads. */
|
||||
#define P2_PTRACE_FSTP 0x00000010 /* SIGSTOP from PT_ATTACH not yet handled. */
|
||||
|
||||
/* Flags protected by proctree_lock, kept in p_treeflags. */
|
||||
#define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */
|
||||
@ -930,6 +932,7 @@ void proc_linkup(struct proc *p, struct thread *td);
|
||||
struct proc *proc_realparent(struct proc *child);
|
||||
void proc_reap(struct thread *td, struct proc *p, int *status, int options);
|
||||
void proc_reparent(struct proc *child, struct proc *newparent);
|
||||
void proc_set_traced(struct proc *p);
|
||||
struct pstats *pstats_alloc(void);
|
||||
void pstats_fork(struct pstats *src, struct pstats *dst);
|
||||
void pstats_free(struct pstats *ps);
|
||||
|
Loading…
x
Reference in New Issue
Block a user