Author: dchagin
Date: Sat Mar  5 20:36:42 2011
New Revision: 219311
URL: http://svn.freebsd.org/changeset/base/219311

Log:
  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

Modified:
  head/sys/kern/kern_ktrace.c

Modified: head/sys/kern/kern_ktrace.c
==============================================================================
--- head/sys/kern/kern_ktrace.c Sat Mar  5 20:15:32 2011        (r219310)
+++ head/sys/kern/kern_ktrace.c Sat Mar  5 20:36:42 2011        (r219311)
@@ -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 thre
 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 *)NU
     (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, st
        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, 
        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);
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to