diff options
author | jhb <jhb@FreeBSD.org> | 2006-03-28 21:30:22 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2006-03-28 21:30:22 +0000 |
commit | 44f0d9f5195c6fba57e25137546f98690ea5f1d2 (patch) | |
tree | 4f5f0c0176236c8d422846a1ad3de7d7acc57d6e /sys/kern/kern_ktrace.c | |
parent | 0d8b767dc84c60efc1d4a020824e0fb91f8015e9 (diff) | |
download | FreeBSD-src-44f0d9f5195c6fba57e25137546f98690ea5f1d2.zip FreeBSD-src-44f0d9f5195c6fba57e25137546f98690ea5f1d2.tar.gz |
- Conditionalize Giant around VFS operations for ALQ, ktrace, and
generating a coredump as the result of a signal.
- Fix a bug where we could leak a Giant lock if vn_start_write() failed
in coredump().
Reported by: jmg (2)
Diffstat (limited to 'sys/kern/kern_ktrace.c')
-rw-r--r-- | sys/kern/kern_ktrace.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 7f42f67..cd846d6 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -598,7 +598,7 @@ ktrace(td, uap) int ops = KTROP(uap->ops); int descend = uap->ops & KTRFLAG_DESCEND; int nfound, ret = 0; - int flags, error = 0; + int flags, error = 0, vfslocked; struct nameidata nd; struct ucred *cred; @@ -613,25 +613,25 @@ ktrace(td, uap) /* * an operation which requires a file argument. */ - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, td); + NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_USERSPACE, + uap->fname, td); flags = FREAD | FWRITE | O_NOFOLLOW; - mtx_lock(&Giant); error = vn_open(&nd, &flags, 0, -1); if (error) { - mtx_unlock(&Giant); ktrace_exit(td); return (error); } + vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; VOP_UNLOCK(vp, 0, td); if (vp->v_type != VREG) { (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); ktrace_exit(td); return (EACCES); } - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); } /* * Clear all uses of the tracefile. @@ -649,10 +649,10 @@ ktrace(td, uap) p->p_traceflag = 0; mtx_unlock(&ktrace_mtx); PROC_UNLOCK(p); - mtx_lock(&Giant); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); (void) vn_close(vp, FREAD|FWRITE, cred, td); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); crfree(cred); } else { PROC_UNLOCK(p); @@ -732,9 +732,9 @@ ktrace(td, uap) error = EPERM; done: if (vp != NULL) { - mtx_lock(&Giant); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); (void) vn_close(vp, FWRITE, td->td_ucred, td); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); } ktrace_exit(td); return (error); @@ -888,7 +888,7 @@ ktr_writerequest(struct thread *td, struct ktr_request *req) struct iovec aiov[3]; struct mount *mp; int datalen, buflen, vrele_count; - int error; + int error, vfslocked; /* * We hold the vnode and credential for use in I/O in case ktrace is @@ -944,7 +944,7 @@ ktr_writerequest(struct thread *td, struct ktr_request *req) auio.uio_iovcnt++; } - mtx_lock(&Giant); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vn_start_write(vp, &mp, V_WAIT); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); (void)VOP_LEASE(vp, td, cred, LEASE_WRITE); @@ -956,7 +956,7 @@ ktr_writerequest(struct thread *td, struct ktr_request *req) VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); vrele(vp); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); if (!error) return; /* @@ -1000,10 +1000,10 @@ ktr_writerequest(struct thread *td, struct ktr_request *req) * them but not yet committed them, as those are per-thread. The * thread will have to clear it itself on system call return. */ - mtx_lock(&Giant); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); while (vrele_count-- > 0) vrele(vp); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); } /* |