Add a function "ktrsettracevnode", that changes the ktrace vnode for a process
authorart <art@openbsd.org>
Thu, 20 Apr 2000 10:03:41 +0000 (10:03 +0000)
committerart <art@openbsd.org>
Thu, 20 Apr 2000 10:03:41 +0000 (10:03 +0000)
in a correct way. Use it in all places where the vnode was changed.
(most of the earlier code was incorrect and had races).

sys/kern/kern_exec.c
sys/kern/kern_exit.c
sys/kern/kern_ktrace.c
sys/sys/ktrace.h

index 15ed8af..b5de0c0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_exec.c,v 1.41 2000/03/23 15:55:52 art Exp $      */
+/*     $OpenBSD: kern_exec.c,v 1.42 2000/04/20 10:03:42 art Exp $      */
 /*     $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $  */
 
 /*-
@@ -497,8 +497,7 @@ sys_execve(p, v, retval)
                 */
                if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) {
                        p->p_traceflag = 0;
-                       vrele(p->p_tracep);
-                       p->p_tracep = NULL;
+                       ktrsettracevnode(p, NULL);
                }
 #endif
                p->p_ucred = crcopy(cred);
index 5efdeea..97a9864 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_exit.c,v 1.22 2000/03/23 15:55:52 art Exp $      */
+/*     $OpenBSD: kern_exit.c,v 1.23 2000/04/20 10:03:43 art Exp $      */
 /*     $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $  */
 
 /*
@@ -63,6 +63,7 @@
 #include <sys/filedesc.h>
 #include <sys/signalvar.h>
 #include <sys/sched.h>
+#include <sys/ktrace.h>
 #ifdef SYSVSHM
 #include <sys/shm.h>
 #endif
@@ -210,7 +211,7 @@ exit1(p, rv)
         */
        p->p_traceflag = 0;     /* don't trace the vrele() */
        if (p->p_tracep)
-               vrele(p->p_tracep);
+               ktrsettracevnode(p, NULL);
 #endif
        /*
         * Remove proc from allproc queue and pidhash chain.
index 77d4b6b..240d13c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_ktrace.c,v 1.17 2000/04/19 10:56:41 art Exp $    */
+/*     $OpenBSD: kern_ktrace.c,v 1.18 2000/04/20 10:03:42 art Exp $    */
 /*     $NetBSD: kern_ktrace.c,v 1.23 1996/02/09 18:59:36 christos Exp $        */
 
 /*
@@ -60,6 +60,29 @@ int ktrsetchildren __P((struct proc *, struct proc *, int, int,
 int ktrwrite __P((struct vnode *, struct ktr_header *));
 int ktrcanset __P((struct proc *, struct proc *));
 
+/*
+ * Change the trace vnode in a correct way (to avoid races).
+ */
+void
+ktrsettracevnode(p, newvp)
+       struct proc *p;
+       struct vnode *newvp;
+{
+       struct vnode *vp;
+
+       if (p->p_tracep == newvp)       /* avoid work */
+               return;
+
+       if (newvp != NULL)
+               VREF(newvp);
+
+       vp = p->p_tracep;
+       p->p_tracep = newvp;
+
+       if (vp != NULL)
+               vrele(vp);
+}
+
 void
 ktrinitheader(kth, p, type)
        struct ktr_header *kth;
@@ -324,9 +347,8 @@ sys_ktrace(curp, v, retval)
                for (p = LIST_FIRST(&allproc); p; p = LIST_NEXT(p, p_list)) {
                        if (p->p_tracep == vp) {
                                if (ktrcanset(curp, p)) {
-                                       p->p_tracep = NULL;
                                        p->p_traceflag = 0;
-                                       vrele(vp);
+                                       ktrsettracevnode(p, NULL);
                                } else
                                        error = EPERM;
                        }
@@ -391,15 +413,7 @@ ktrops(curp, p, ops, facs, vp)
        if (!ktrcanset(curp, p))
                return (0);
        if (ops == KTROP_SET) {
-               if (p->p_tracep != vp) { 
-                       /*
-                        * if trace file already in use, relinquish
-                        */
-                       if (p->p_tracep != NULL)
-                               vrele(p->p_tracep);
-                       VREF(vp);
-                       p->p_tracep = vp;
-               }
+               ktrsettracevnode(p, vp);
                p->p_traceflag |= facs;
                if (curp->p_ucred->cr_uid == 0)
                        p->p_traceflag |= KTRFAC_ROOT;
@@ -408,10 +422,7 @@ ktrops(curp, p, ops, facs, vp)
                if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
                        /* no more tracing */
                        p->p_traceflag = 0;
-                       if (p->p_tracep != NULL) {
-                               vrele(p->p_tracep);
-                               p->p_tracep = NULL;
-                       }
+                       ktrsettracevnode(p, NULL);
                }
        }
 
@@ -496,9 +507,8 @@ ktrwrite(vp, kth)
            error);
        for (p = LIST_FIRST(&allproc); p != NULL; p = LIST_NEXT(p, p_list)) {
                if (p->p_tracep == vp) {
-                       p->p_tracep = NULL;
                        p->p_traceflag = 0;
-                       vrele(vp);
+                       ktrsettracevnode(p, NULL);
                }
        }
 
index 83e1f7d..2fc4b4b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ktrace.h,v 1.2 1996/03/03 12:11:54 niklas Exp $       */
+/*     $OpenBSD: ktrace.h,v 1.3 2000/04/20 10:03:41 art Exp $  */
 /*     $NetBSD: ktrace.h,v 1.12 1996/02/04 02:12:29 christos Exp $     */
 
 /*
@@ -173,4 +173,6 @@ void ktrpsig __P((struct vnode *, int, sig_t, int, int));
 void ktrsyscall __P((struct vnode *, register_t, size_t, register_t []));
 void ktrsysret __P((struct vnode *, register_t, int, register_t));
 
+void ktrsettracevnode __P((struct proc *, struct vnode *));
+
 #endif /* !_KERNEL */