- Change procfs_control()'s first argument to be a thread pointer instead

of a process pointer.
- Move the p_candebug() at the start of procfs_control() a bit to make
  locking feasible.  We still perform the access check before doing
  anything, we just now perform it after acquiring locks.
- Don't lock the sched_lock for TRACE_WAIT_P() and when checking to see if
  p_stat is SSTOP.  We lock the process while setting p_stat to SSTOP
  so locking the process is sufficient to do a read to see if p_stat is
  SSTOP or not.
This commit is contained in:
John Baldwin 2002-04-13 23:19:13 +00:00
parent ce5aaf4554
commit a92e7c792a

View File

@ -108,23 +108,13 @@ static struct namemap signames[] = {
{ 0 }, { 0 },
}; };
static int procfs_control(struct proc *curp, struct proc *p, int op); static int procfs_control(struct thread *td, struct proc *p, int op);
static int static int
procfs_control(struct proc *curp, struct proc *p, int op) procfs_control(struct thread *td, struct proc *p, int op)
{ {
int error = 0; int error = 0;
/*
* Authorization check: rely on normal debugging protection, except
* allow processes to disengage debugging on a process onto which
* they have previously attached, but no longer have permission to
* debug.
*/
if (op != PROCFS_CTL_DETACH &&
((error = p_candebug(curp, p))))
return (error);
/* /*
* Attach - attaches the target process for debugging * Attach - attaches the target process for debugging
* by the calling process. * by the calling process.
@ -132,13 +122,15 @@ procfs_control(struct proc *curp, struct proc *p, int op)
if (op == PROCFS_CTL_ATTACH) { if (op == PROCFS_CTL_ATTACH) {
sx_xlock(&proctree_lock); sx_xlock(&proctree_lock);
PROC_LOCK(p); PROC_LOCK(p);
if ((error = p_candebug(td->td_proc, p)) != 0)
goto out;
if (p->p_flag & P_TRACED) { if (p->p_flag & P_TRACED) {
error = EBUSY; error = EBUSY;
goto out; goto out;
} }
/* Can't trace yourself! */ /* Can't trace yourself! */
if (p->p_pid == curp->p_pid) { if (p->p_pid == td->td_proc->p_pid) {
error = EINVAL; error = EINVAL;
goto out; goto out;
} }
@ -154,9 +146,9 @@ procfs_control(struct proc *curp, struct proc *p, int op)
p->p_flag |= P_TRACED; p->p_flag |= P_TRACED;
faultin(p); faultin(p);
p->p_xstat = 0; /* XXX ? */ p->p_xstat = 0; /* XXX ? */
if (p->p_pptr != curp) { if (p->p_pptr != td->td_proc) {
p->p_oppid = p->p_pptr->p_pid; p->p_oppid = p->p_pptr->p_pid;
proc_reparent(p, curp); proc_reparent(p, td->td_proc);
} }
psignal(p, SIGSTOP); psignal(p, SIGSTOP);
out: out:
@ -166,7 +158,20 @@ procfs_control(struct proc *curp, struct proc *p, int op)
} }
/* /*
* Target process must be stopped, owned by (curp) and * Authorization check: rely on normal debugging protection, except
* allow processes to disengage debugging on a process onto which
* they have previously attached, but no longer have permission to
* debug.
*/
PROC_LOCK(p);
if (op != PROCFS_CTL_DETACH &&
((error = p_candebug(td->td_proc, p)))) {
PROC_UNLOCK(p);
return (error);
}
/*
* Target process must be stopped, owned by (td) and
* be set up for tracing (P_TRACED flag set). * be set up for tracing (P_TRACED flag set).
* Allow DETACH to take place at any time for sanity. * Allow DETACH to take place at any time for sanity.
* Allow WAIT any time, of course. * Allow WAIT any time, of course.
@ -177,15 +182,10 @@ procfs_control(struct proc *curp, struct proc *p, int op)
break; break;
default: default:
PROC_LOCK(p); if (!TRACE_WAIT_P(td->td_proc, p)) {
mtx_lock_spin(&sched_lock);
if (!TRACE_WAIT_P(curp, p)) {
mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p); PROC_UNLOCK(p);
return (EBUSY); return (EBUSY);
} }
mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p);
} }
@ -201,7 +201,6 @@ procfs_control(struct proc *curp, struct proc *p, int op)
* To continue with a signal, just send * To continue with a signal, just send
* the signal name to the ctl file * the signal name to the ctl file
*/ */
PROC_LOCK(p);
p->p_xstat = 0; p->p_xstat = 0;
switch (op) { switch (op) {
@ -241,7 +240,7 @@ procfs_control(struct proc *curp, struct proc *p, int op)
PROC_UNLOCK(p); PROC_UNLOCK(p);
sx_xunlock(&proctree_lock); sx_xunlock(&proctree_lock);
wakeup((caddr_t) curp); /* XXX for CTL_WAIT below ? */ wakeup((caddr_t) td->td_proc); /* XXX for CTL_WAIT below ? */
break; break;
@ -272,31 +271,19 @@ procfs_control(struct proc *curp, struct proc *p, int op)
*/ */
case PROCFS_CTL_WAIT: case PROCFS_CTL_WAIT:
if (p->p_flag & P_TRACED) { if (p->p_flag & P_TRACED) {
mtx_lock_spin(&sched_lock);
while (error == 0 && while (error == 0 &&
(p->p_stat != SSTOP) && (p->p_stat != SSTOP) &&
(p->p_flag & P_TRACED) && (p->p_flag & P_TRACED) &&
(p->p_pptr == curp)) { (p->p_pptr == td->td_proc))
mtx_unlock_spin(&sched_lock);
error = msleep((caddr_t) p, &p->p_mtx, error = msleep((caddr_t) p, &p->p_mtx,
PWAIT|PCATCH, "procfsx", 0); PWAIT|PCATCH, "procfsx", 0);
mtx_lock_spin(&sched_lock); if (error == 0 && !TRACE_WAIT_P(td->td_proc, p))
}
if (error == 0 && !TRACE_WAIT_P(curp, p))
error = EBUSY; error = EBUSY;
mtx_unlock_spin(&sched_lock); } else
PROC_UNLOCK(p); while (error == 0 && p->p_stat != SSTOP)
} else { error = msleep((caddr_t) p, &p->p_mtx,
PROC_UNLOCK(p);
mtx_lock_spin(&sched_lock);
while (error == 0 && p->p_stat != SSTOP) {
mtx_unlock_spin(&sched_lock);
error = tsleep((caddr_t) p,
PWAIT|PCATCH, "procfs", 0); PWAIT|PCATCH, "procfs", 0);
mtx_lock_spin(&sched_lock); PROC_UNLOCK(p);
}
mtx_unlock_spin(&sched_lock);
}
return (error); return (error);
default: default:
@ -346,13 +333,12 @@ procfs_doprocctl(PFS_FILL_ARGS)
nm = findname(ctlnames, sbuf_data(sb), sbuf_len(sb)); nm = findname(ctlnames, sbuf_data(sb), sbuf_len(sb));
if (nm) { if (nm) {
printf("procfs: got a %s command\n", sbuf_data(sb)); printf("procfs: got a %s command\n", sbuf_data(sb));
error = procfs_control(td->td_proc, p, nm->nm_val); error = procfs_control(td, p, nm->nm_val);
} else { } else {
nm = findname(signames, sbuf_data(sb), sbuf_len(sb)); nm = findname(signames, sbuf_data(sb), sbuf_len(sb));
if (nm) { if (nm) {
printf("procfs: got a sig%s\n", sbuf_data(sb)); printf("procfs: got a sig%s\n", sbuf_data(sb));
PROC_LOCK(p); PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
/* This is very broken XXXKSE: */ /* This is very broken XXXKSE: */
if (TRACE_WAIT_P(td->td_proc, p)) { if (TRACE_WAIT_P(td->td_proc, p)) {
@ -361,13 +347,12 @@ procfs_doprocctl(PFS_FILL_ARGS)
/* XXXKSE: */ /* XXXKSE: */
FIX_SSTEP(FIRST_THREAD_IN_PROC(p)); FIX_SSTEP(FIRST_THREAD_IN_PROC(p));
#endif #endif
mtx_lock_spin(&sched_lock);
/* XXXKSE: */ /* XXXKSE: */
setrunnable(FIRST_THREAD_IN_PROC(p)); setrunnable(FIRST_THREAD_IN_PROC(p));
mtx_unlock_spin(&sched_lock); mtx_unlock_spin(&sched_lock);
} else { } else
mtx_unlock_spin(&sched_lock);
psignal(p, nm->nm_val); psignal(p, nm->nm_val);
}
PROC_UNLOCK(p); PROC_UNLOCK(p);
error = 0; error = 0;
} }