summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_proc.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2002-04-09 20:10:46 +0000
committerjhb <jhb@FreeBSD.org>2002-04-09 20:10:46 +0000
commit97bce5a40f6f17a0a765856fadc0df45dd5ee75f (patch)
tree888c25fcd0b8d42fbe2dc338809dbb338edc3251 /sys/kern/kern_proc.c
parent6615797e535b58bbb6a5cd4a450b6634a80713a1 (diff)
downloadFreeBSD-src-97bce5a40f6f17a0a765856fadc0df45dd5ee75f.zip
FreeBSD-src-97bce5a40f6f17a0a765856fadc0df45dd5ee75f.tar.gz
- Change fill_kinfo_proc() to require that the process is locked when it
is called. - Change sysctl_out_proc() to require that the process is locked when it is called and to drop the lock before it returns. If this proves too complex we can change sysctl_out_proc() to simply acquire the lock at the very end and have the calling code drop the lock right after it returns. - Lock the process we are going to export before the p_cansee() in the loop in sysctl_kern_proc() and hold the lock until we call sysctl_out_proc(). - Don't call p_cansee() on the process about to be exported twice in the aforementioned loop.
Diffstat (limited to 'sys/kern/kern_proc.c')
-rw-r--r--sys/kern/kern_proc.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 8a7bec2..afd6ee2 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -629,6 +629,7 @@ DB_SHOW_COMMAND(pgrpdump, pgrpdump)
/*
* Fill in an kinfo_proc structure for the specified process.
+ * Must be called with the target process locked.
*/
void
fill_kinfo_proc(p, kp)
@@ -644,7 +645,7 @@ fill_kinfo_proc(p, kp)
kp->ki_structsize = sizeof(*kp);
kp->ki_paddr = p;
- PROC_LOCK(p);
+ PROC_LOCK_ASSERT(p, MA_OWNED);
kp->ki_addr =/* p->p_addr; */0; /* XXXKSE */
kp->ki_args = p->p_args;
kp->ki_tracep = p->p_tracep;
@@ -764,7 +765,6 @@ fill_kinfo_proc(p, kp)
kp->ki_lock = p->p_lock;
if (p->p_pptr)
kp->ki_ppid = p->p_pptr->p_pid;
- PROC_UNLOCK(p);
}
/*
@@ -786,6 +786,9 @@ zpfind(pid_t pid)
}
+/*
+ * Must be called with the process locked and will return with it unlocked.
+ */
static int
sysctl_out_proc(struct proc *p, struct sysctl_req *req, int doingzomb)
{
@@ -794,7 +797,9 @@ sysctl_out_proc(struct proc *p, struct sysctl_req *req, int doingzomb)
struct proc *np;
pid_t pid = p->p_pid;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
fill_kinfo_proc(p, &kinfo_proc);
+ PROC_UNLOCK(p);
error = SYSCTL_OUT(req, (caddr_t)&kinfo_proc, sizeof(kinfo_proc));
if (error)
return (error);
@@ -834,7 +839,6 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
PROC_UNLOCK(p);
return (0);
}
- PROC_UNLOCK(p);
error = sysctl_out_proc(p, req, 0);
return (error);
}
@@ -858,16 +862,21 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
else
p = LIST_FIRST(&zombproc);
for (; p != 0; p = LIST_NEXT(p, p_list)) {
+ PROC_LOCK(p);
/*
* Show a user only appropriate processes.
*/
- if (p_cansee(curproc, p))
+ if (p_cansee(curproc, p)) {
+ PROC_UNLOCK(p);
continue;
+ }
/*
* Skip embryonic processes.
*/
- if (p->p_stat == SIDL)
+ if (p->p_stat == SIDL) {
+ PROC_UNLOCK(p);
continue;
+ }
/*
* TODO - make more efficient (see notes below).
* do by session.
@@ -876,17 +885,14 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
case KERN_PROC_PGRP:
/* could do this by traversing pgrp */
- PROC_LOCK(p);
if (p->p_pgrp == NULL ||
p->p_pgrp->pg_id != (pid_t)name[0]) {
PROC_UNLOCK(p);
continue;
}
- PROC_UNLOCK(p);
break;
case KERN_PROC_TTY:
- PROC_LOCK(p);
if ((p->p_flag & P_CONTROLT) == 0 ||
p->p_session == NULL) {
PROC_UNLOCK(p);
@@ -901,25 +907,25 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
continue;
}
SESS_UNLOCK(p->p_session);
- PROC_UNLOCK(p);
break;
case KERN_PROC_UID:
if (p->p_ucred == NULL ||
- p->p_ucred->cr_uid != (uid_t)name[0])
+ p->p_ucred->cr_uid != (uid_t)name[0]) {
+ PROC_UNLOCK(p);
continue;
+ }
break;
case KERN_PROC_RUID:
if (p->p_ucred == NULL ||
- p->p_ucred->cr_ruid != (uid_t)name[0])
+ p->p_ucred->cr_ruid != (uid_t)name[0]) {
+ PROC_UNLOCK(p);
continue;
+ }
break;
}
- if (p_cansee(curproc, p))
- continue;
-
error = sysctl_out_proc(p, req, doingzomb);
if (error) {
sx_sunlock(&allproc_lock);
OpenPOWER on IntegriCloud