From 99b120c8f2e636e27f6443b595784037912ec1c1 Mon Sep 17 00:00:00 2001 From: dchagin Date: Sat, 5 Mar 2011 20:36:42 +0000 Subject: Partially reworked r219042. The reason for this is a bug at ktrops() where process dereferenced without having a lock. This might cause a panic if ktrace was runned with -p flag and the specified process exited between the dropping a lock and writing sv_flags. Since it is impossible to acquire sx lock while holding mtx switch to use asynchronous enqueuerequest() instead of writerequest(). Rename ktr_getrequest_ne() to more understandable name [1]. Requested by: jhb [1] MFC after: 1 Week --- sys/kern/kern_ktrace.c | 50 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) (limited to 'sys/kern/kern_ktrace.c') diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index d90c07a..88413bd 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -138,9 +138,8 @@ static struct sx ktrace_sx; static void ktrace_init(void *dummy); static int sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS); static u_int ktrace_resize_pool(u_int oldsize, u_int newsize); -static struct ktr_request *ktr_getrequest_ne(struct thread *, int type); +static struct ktr_request *ktr_getrequest_entered(struct thread *td, int type); static struct ktr_request *ktr_getrequest(int type); -static void ktr_submitrequest_ne(struct thread *td, struct ktr_request *req); static void ktr_submitrequest(struct thread *td, struct ktr_request *req); static void ktr_freeproc(struct proc *p, struct ucred **uc, struct vnode **vp); @@ -150,7 +149,7 @@ static void ktr_writerequest(struct thread *td, struct ktr_request *req); static int ktrcanset(struct thread *,struct proc *); static int ktrsetchildren(struct thread *,struct proc *,int,int,struct vnode *); static int ktrops(struct thread *,struct proc *,int,int,struct vnode *); -static void ktrprocctor_ne(struct thread *, struct proc *p); +static void ktrprocctor_entered(struct thread *, struct proc *); /* * ktrace itself generates events, such as context switches, which we do not @@ -272,7 +271,7 @@ CTASSERT(sizeof(((struct ktr_header *)NULL)->ktr_comm) == (sizeof((struct thread *)NULL)->td_name)); static struct ktr_request * -ktr_getrequest_ne(struct thread *td, int type) +ktr_getrequest_entered(struct thread *td, int type) { struct ktr_request *req; struct proc *p = td->td_proc; @@ -317,7 +316,7 @@ ktr_getrequest(int type) struct ktr_request *req; ktrace_enter(td); - req = ktr_getrequest_ne(td, type); + req = ktr_getrequest_entered(td, type); if (req == NULL) ktrace_exit(td); @@ -337,7 +336,6 @@ ktr_enqueuerequest(struct thread *td, struct ktr_request *req) mtx_lock(&ktrace_mtx); STAILQ_INSERT_TAIL(&td->td_proc->p_ktr, req, ktr_list); mtx_unlock(&ktrace_mtx); - ktrace_exit(td); } /* @@ -377,7 +375,7 @@ ktr_drain(struct thread *td) * been cached in the thread. */ static void -ktr_submitrequest_ne(struct thread *td, struct ktr_request *req) +ktr_submitrequest(struct thread *td, struct ktr_request *req) { ktrace_assert(td); @@ -387,14 +385,6 @@ ktr_submitrequest_ne(struct thread *td, struct ktr_request *req) ktr_writerequest(td, req); ktr_freerequest(req); sx_xunlock(&ktrace_sx); -} - -static void -ktr_submitrequest(struct thread *td, struct ktr_request *req) -{ - - ktrace_assert(td); - ktr_submitrequest_ne(td, req); ktrace_exit(td); } @@ -523,12 +513,12 @@ ktrprocexit(struct thread *td) return; ktrace_enter(td); + req = ktr_getrequest_entered(td, KTR_PROCDTOR); + if (req != NULL) + ktr_enqueuerequest(td, req); sx_xlock(&ktrace_sx); ktr_drain(td); sx_xunlock(&ktrace_sx); - req = ktr_getrequest_ne(td, KTR_PROCDTOR); - if (req != NULL) - ktr_submitrequest_ne(td, req); PROC_LOCK(p); mtx_lock(&ktrace_mtx); ktr_freeproc(p, &cred, &vp); @@ -545,21 +535,20 @@ ktrprocexit(struct thread *td) } static void -ktrprocctor_ne(struct thread *td, struct proc *p) +ktrprocctor_entered(struct thread *td, struct proc *p) { struct ktr_proc_ctor *ktp; struct ktr_request *req; - struct thread *td2; + struct thread *td2;; ktrace_assert(td); td2 = FIRST_THREAD_IN_PROC(p); - req = ktr_getrequest_ne(td2, KTR_PROCCTOR); + req = ktr_getrequest_entered(td2, KTR_PROCCTOR); if (req == NULL) return; - ktp = &req->ktr_data.ktr_proc_ctor; ktp->sv_flags = p->p_sysent->sv_flags; - ktr_submitrequest_ne(td, req); + ktr_enqueuerequest(td2, req); } void @@ -571,7 +560,7 @@ ktrprocctor(struct proc *p) return; ktrace_enter(td); - ktrprocctor_ne(td, p); + ktrprocctor_entered(td, p); ktrace_exit(td); } @@ -721,6 +710,7 @@ ktrpsig(sig, action, mask, code) sigset_t *mask; int code; { + struct thread *td = curthread; struct ktr_request *req; struct ktr_psig *kp; @@ -732,13 +722,15 @@ ktrpsig(sig, action, mask, code) kp->action = action; kp->mask = *mask; kp->code = code; - ktr_enqueuerequest(curthread, req); + ktr_enqueuerequest(td, req); + ktrace_exit(td); } void ktrcsw(out, user) int out, user; { + struct thread *td = curthread; struct ktr_request *req; struct ktr_csw *kc; @@ -748,7 +740,8 @@ ktrcsw(out, user) kc = &req->ktr_data.ktr_csw; kc->out = out; kc->user = user; - ktr_enqueuerequest(curthread, req); + ktr_enqueuerequest(td, req); + ktrace_exit(td); } void @@ -1021,6 +1014,8 @@ ktrops(td, p, ops, facs, vp) ktr_freeproc(p, &tracecred, &tracevp); } mtx_unlock(&ktrace_mtx); + if ((p->p_traceflag & KTRFAC_MASK) != 0) + ktrprocctor_entered(td, p); PROC_UNLOCK(p); if (tracevp != NULL) { int vfslocked; @@ -1032,9 +1027,6 @@ ktrops(td, p, ops, facs, vp) if (tracecred != NULL) crfree(tracecred); - if ((p->p_traceflag & KTRFAC_MASK) != 0) - ktrprocctor_ne(td, p); - return (1); } -- cgit v1.1