- 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:
parent
ce5aaf4554
commit
a92e7c792a
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user