summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2001-03-07 03:09:40 +0000
committerjhb <jhb@FreeBSD.org>2001-03-07 03:09:40 +0000
commit2c951b9c740f03ba39410bbbca30fa9fcc546a57 (patch)
tree74a64743b2abbb2547b6ff749f19ec0427b4f5b1 /sys/fs
parent53e75509c01f5f00c09d9252fc9c6bd3410e90bf (diff)
downloadFreeBSD-src-2c951b9c740f03ba39410bbbca30fa9fcc546a57.zip
FreeBSD-src-2c951b9c740f03ba39410bbbca30fa9fcc546a57.tar.gz
Proc locking. Lock around psignal() and also ensure both an exclusive
proctree lock and the process lock are held when updating p_pptr and p_oppid. When we are just reaading p_pptr we only need the proc lock and not a proctree lock as well.
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/procfs/procfs_ctl.c54
1 files changed, 34 insertions, 20 deletions
diff --git a/sys/fs/procfs/procfs_ctl.c b/sys/fs/procfs/procfs_ctl.c
index 1ca2208..0130795 100644
--- a/sys/fs/procfs/procfs_ctl.c
+++ b/sys/fs/procfs/procfs_ctl.c
@@ -125,13 +125,21 @@ procfs_control(curp, p, op)
* by the calling process.
*/
if (op == PROCFS_CTL_ATTACH) {
+ PROCTREE_LOCK(PT_EXCLUSIVE);
+ PROC_LOCK(p);
/* check whether already being traced */
- if (p->p_flag & P_TRACED)
+ if (p->p_flag & P_TRACED) {
+ PROC_UNLOCK(p);
+ PROCTREE_LOCK(PT_RELEASE);
return (EBUSY);
+ }
/* can't trace yourself! */
- if (p->p_pid == curp->p_pid)
+ if (p->p_pid == curp->p_pid) {
+ PROC_UNLOCK(p);
+ PROCTREE_LOCK(PT_RELEASE);
return (EINVAL);
+ }
/*
* Go ahead and set the trace flag.
@@ -144,13 +152,13 @@ procfs_control(curp, p, op)
p->p_flag |= P_TRACED;
faultin(p);
p->p_xstat = 0; /* XXX ? */
- PROCTREE_LOCK(PT_EXCLUSIVE);
if (p->p_pptr != curp) {
p->p_oppid = p->p_pptr->p_pid;
proc_reparent(p, curp);
}
- PROCTREE_LOCK(PT_RELEASE);
psignal(p, SIGSTOP);
+ PROC_UNLOCK(p);
+ PROCTREE_LOCK(PT_RELEASE);
return (0);
}
@@ -166,15 +174,15 @@ procfs_control(curp, p, op)
break;
default:
- PROCTREE_LOCK(PT_SHARED);
+ PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
if (!TRACE_WAIT_P(curp, p)) {
mtx_unlock_spin(&sched_lock);
- PROCTREE_LOCK(PT_RELEASE);
+ PROC_UNLOCK(p);
return (EBUSY);
}
mtx_unlock_spin(&sched_lock);
- PROCTREE_LOCK(PT_RELEASE);
+ PROC_UNLOCK(p);
}
@@ -190,6 +198,7 @@ procfs_control(curp, p, op)
* To continue with a signal, just send
* the signal name to the ctl file
*/
+ PROC_LOCK(p);
p->p_xstat = 0;
switch (op) {
@@ -199,14 +208,17 @@ procfs_control(curp, p, op)
*/
case PROCFS_CTL_DETACH:
/* if not being traced, then this is a painless no-op */
- if ((p->p_flag & P_TRACED) == 0)
+ if ((p->p_flag & P_TRACED) == 0) {
+ PROC_UNLOCK(p);
return (0);
+ }
/* not being traced any more */
p->p_flag &= ~P_TRACED;
/* remove pending SIGTRAP, else the process will die */
SIGDELSET(p->p_siglist, SIGTRAP);
+ PROC_UNLOCK(p);
/* give process back to original parent */
PROCTREE_LOCK(PT_EXCLUSIVE);
@@ -214,13 +226,16 @@ procfs_control(curp, p, op)
struct proc *pp;
pp = pfind(p->p_oppid);
+ PROC_LOCK(p);
if (pp)
proc_reparent(p, pp);
- }
- PROCTREE_LOCK(PT_RELEASE);
-
+ } else
+ PROC_LOCK(p);
p->p_oppid = 0;
p->p_flag &= ~P_WAITED; /* XXX ? */
+ PROC_UNLOCK(p);
+ PROCTREE_LOCK(PT_RELEASE);
+
wakeup((caddr_t) curp); /* XXX for CTL_WAIT below ? */
break;
@@ -229,7 +244,8 @@ procfs_control(curp, p, op)
* Step. Let the target process execute a single instruction.
*/
case PROCFS_CTL_STEP:
- PHOLD(p);
+ _PHOLD(p);
+ PROC_UNLOCK(p);
error = procfs_sstep(p);
PRELE(p);
if (error)
@@ -241,6 +257,7 @@ procfs_control(curp, p, op)
* or some other trap.
*/
case PROCFS_CTL_RUN:
+ PROC_UNLOCK(p);
break;
/*
@@ -251,24 +268,22 @@ procfs_control(curp, p, op)
case PROCFS_CTL_WAIT:
error = 0;
if (p->p_flag & P_TRACED) {
- PROCTREE_LOCK(PT_SHARED);
mtx_lock_spin(&sched_lock);
while (error == 0 &&
(p->p_stat != SSTOP) &&
(p->p_flag & P_TRACED) &&
(p->p_pptr == curp)) {
mtx_unlock_spin(&sched_lock);
- PROCTREE_LOCK(PT_RELEASE);
- error = tsleep((caddr_t) p,
+ error = msleep((caddr_t) p, &p->p_mtx,
PWAIT|PCATCH, "procfsx", 0);
- PROCTREE_LOCK(PT_SHARED);
mtx_lock_spin(&sched_lock);
}
if (error == 0 && !TRACE_WAIT_P(curp, p))
error = EBUSY;
mtx_unlock_spin(&sched_lock);
- PROCTREE_LOCK(PT_RELEASE);
+ PROC_UNLOCK(p);
} else {
+ PROC_UNLOCK(p);
mtx_lock_spin(&sched_lock);
while (error == 0 && p->p_stat != SSTOP) {
mtx_unlock_spin(&sched_lock);
@@ -328,7 +343,7 @@ procfs_doctl(curp, p, pfs, uio)
} else {
nm = vfs_findname(signames, msg, xlen);
if (nm) {
- PROCTREE_LOCK(PT_SHARED);
+ PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
if (TRACE_WAIT_P(curp, p)) {
p->p_xstat = nm->nm_val;
@@ -337,12 +352,11 @@ procfs_doctl(curp, p, pfs, uio)
#endif
setrunnable(p);
mtx_unlock_spin(&sched_lock);
- PROCTREE_LOCK(PT_RELEASE);
} else {
mtx_unlock_spin(&sched_lock);
- PROCTREE_LOCK(PT_RELEASE);
psignal(p, nm->nm_val);
}
+ PROC_UNLOCK(p);
error = 0;
}
}
OpenPOWER on IntegriCloud