summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_ktrace.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2003-04-25 19:59:35 +0000
committerjhb <jhb@FreeBSD.org>2003-04-25 19:59:35 +0000
commitb3c19f6ec93ef3b9e4ef9b7df26193d839ea3341 (patch)
tree052d0b03795b4d672d4adc0e0d3eda4bf3733320 /sys/kern/kern_ktrace.c
parent8db9172888dfef999398ecc89d0eaa7bfa1d8ee1 (diff)
downloadFreeBSD-src-b3c19f6ec93ef3b9e4ef9b7df26193d839ea3341.zip
FreeBSD-src-b3c19f6ec93ef3b9e4ef9b7df26193d839ea3341.tar.gz
- Push down Giant around vnode operations in ktrace().
- Mark the ktrace() and utrace() syscalls as being MP safe. - Validate the facs argument to ktrace() prior to doing any vnode operations or acquiring any locks. - Share lock the proctree lock over the entire section that calls ktrsetchildren() and ktrops(). We already did this for process groups. Doing it for the process case closes a small race where a process might go away after we look it up. As a result of this, ktrstchildren() now just asserts that the proctree lock is locked rather than acquiring the lock itself. - Add some missing comments to #else and #endif.
Diffstat (limited to 'sys/kern/kern_ktrace.c')
-rw-r--r--sys/kern/kern_ktrace.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index a8aa2b9..8e97122 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -473,12 +473,14 @@ ktrcsw(out, user)
kc->user = user;
ktr_submitrequest(req);
}
-#endif
+#endif /* KTRACE */
/* Interface and common routines */
/*
* ktrace system call
+ *
+ * MPSAFE
*/
#ifndef _SYS_SYSPROTO_H_
struct ktrace_args {
@@ -506,6 +508,12 @@ ktrace(td, uap)
struct nameidata nd;
struct ucred *cred;
+ /*
+ * Need something to (un)trace.
+ */
+ if (ops != KTROP_CLEARFILE && facs == 0)
+ return (EINVAL);
+
td->td_inktrace = 1;
if (ops != KTROP_CLEAR) {
/*
@@ -513,8 +521,10 @@ ktrace(td, uap)
*/
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, td);
flags = FREAD | FWRITE | O_NOFOLLOW;
+ mtx_lock(&Giant);
error = vn_open(&nd, &flags, 0);
if (error) {
+ mtx_unlock(&Giant);
td->td_inktrace = 0;
return (error);
}
@@ -523,9 +533,11 @@ ktrace(td, uap)
VOP_UNLOCK(vp, 0, td);
if (vp->v_type != VREG) {
(void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
+ mtx_unlock(&Giant);
td->td_inktrace = 0;
return (EACCES);
}
+ mtx_unlock(&Giant);
}
/*
* Clear all uses of the tracefile.
@@ -543,8 +555,10 @@ ktrace(td, uap)
p->p_traceflag = 0;
mtx_unlock(&ktrace_mtx);
PROC_UNLOCK(p);
+ mtx_lock(&Giant);
(void) vn_close(vp, FREAD|FWRITE,
cred, td);
+ mtx_unlock(&Giant);
crfree(cred);
} else {
PROC_UNLOCK(p);
@@ -557,20 +571,13 @@ ktrace(td, uap)
goto done;
}
/*
- * need something to (un)trace (XXX - why is this here?)
- */
- if (!facs) {
- error = EINVAL;
- goto done;
- }
- /*
* do it
*/
+ sx_slock(&proctree_lock);
if (uap->pid < 0) {
/*
* by process group
*/
- sx_slock(&proctree_lock);
pg = pgfind(-uap->pid);
if (pg == NULL) {
sx_sunlock(&proctree_lock);
@@ -587,37 +594,46 @@ ktrace(td, uap)
ret |= ktrsetchildren(td, p, ops, facs, vp);
else
ret |= ktrops(td, p, ops, facs, vp);
- sx_sunlock(&proctree_lock);
} else {
/*
* by pid
*/
p = pfind(uap->pid);
if (p == NULL) {
+ sx_sunlock(&proctree_lock);
error = ESRCH;
goto done;
}
+ /*
+ * The slock of the proctree lock will keep this process
+ * from going away, so unlocking the proc here is ok.
+ */
PROC_UNLOCK(p);
- /* XXX: UNLOCK above has a race */
if (descend)
ret |= ktrsetchildren(td, p, ops, facs, vp);
else
ret |= ktrops(td, p, ops, facs, vp);
}
+ sx_sunlock(&proctree_lock);
if (!ret)
error = EPERM;
done:
- if (vp != NULL)
+ if (vp != NULL) {
+ mtx_lock(&Giant);
(void) vn_close(vp, FWRITE, td->td_ucred, td);
+ mtx_unlock(&Giant);
+ }
td->td_inktrace = 0;
return (error);
-#else
- return ENOSYS;
-#endif
+#else /* !KTRACE */
+ return (ENOSYS);
+#endif /* KTRACE */
}
/*
* utrace system call
+ *
+ * MPSAFE
*/
/* ARGSUSED */
int
@@ -650,9 +666,9 @@ utrace(td, uap)
req->ktr_header.ktr_len = uap->len;
ktr_submitrequest(req);
return (0);
-#else
+#else /* !KTRACE */
return (ENOSYS);
-#endif
+#endif /* KTRACE */
}
#ifdef KTRACE
@@ -701,8 +717,11 @@ ktrops(td, p, ops, facs, vp)
}
mtx_unlock(&ktrace_mtx);
PROC_UNLOCK(p);
- if (tracevp != NULL)
+ if (tracevp != NULL) {
+ mtx_lock(&Giant);
vrele(tracevp);
+ mtx_unlock(&Giant);
+ }
if (tracecred != NULL)
crfree(tracecred);
@@ -720,7 +739,7 @@ ktrsetchildren(td, top, ops, facs, vp)
register int ret = 0;
p = top;
- sx_slock(&proctree_lock);
+ sx_assert(&proctree_lock, SX_LOCKED);
for (;;) {
ret |= ktrops(td, p, ops, facs, vp);
/*
@@ -731,10 +750,8 @@ ktrsetchildren(td, top, ops, facs, vp)
if (!LIST_EMPTY(&p->p_children))
p = LIST_FIRST(&p->p_children);
else for (;;) {
- if (p == top) {
- sx_sunlock(&proctree_lock);
+ if (p == top)
return (ret);
- }
if (LIST_NEXT(p, p_sibling)) {
p = LIST_NEXT(p, p_sibling);
break;
OpenPOWER on IntegriCloud