BSD 4_3_Reno release
[unix-history] / usr / src / sys / kern / kern_ktrace.c
index 5396ebc..0c39240 100644 (file)
@@ -2,19 +2,22 @@
  * Copyright (c) 1989 The Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1989 The Regents of the University of California.
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution is only permitted until one year after the first shipment
+ * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
+ * binary forms are permitted provided that: (1) source distributions retain
+ * this entire copyright notice and comment, and (2) distributions including
+ * binaries display the following acknowledgement:  This product includes
+ * software developed by the University of California, Berkeley and its
+ * contributors'' in the documentation or other materials provided with the
+ * distribution and in all advertising materials mentioning features or use
+ * of this software.  Neither the name of the University nor the names of
+ * its contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  *
- *     @(#)kern_ktrace.c       7.2 (Berkeley) %G%
+ *     @(#)kern_ktrace.c       7.9 (Berkeley) 6/28/90
  */
 
 #ifdef KTRACE
  */
 
 #ifdef KTRACE
@@ -32,7 +35,7 @@
 extern int nsysent;
 extern char *syscallnames[];
 
 extern int nsysent;
 extern char *syscallnames[];
 
-int ktrace_nocheck = 1;
+int ktrace_nocheck = 0;        /* set to 1 when security checks in place */
 
 struct ktr_header *
 ktrgetheader(type)
 
 struct ktr_header *
 ktrgetheader(type)
@@ -44,12 +47,13 @@ ktrgetheader(type)
        kth->ktr_type = type;
        microtime(&kth->ktr_time);
        kth->ktr_pid = u.u_procp->p_pid;
        kth->ktr_type = type;
        microtime(&kth->ktr_time);
        kth->ktr_pid = u.u_procp->p_pid;
-       bcopy(u.u_comm, kth->ktr_comm, MAXCOMLEN);
+       bcopy(u.u_procp->p_comm, kth->ktr_comm, MAXCOMLEN);
        return (kth);
 }
 
        return (kth);
 }
 
-ktrsyscall(vp, code, narg)
+ktrsyscall(vp, code, narg, args)
        struct vnode *vp;
        struct vnode *vp;
+       int code, narg, args[];
 {
        struct  ktr_header *kth = ktrgetheader(KTR_SYSCALL);
        struct  ktr_syscall *ktp;
 {
        struct  ktr_header *kth = ktrgetheader(KTR_SYSCALL);
        struct  ktr_syscall *ktp;
@@ -63,7 +67,7 @@ ktrsyscall(vp, code, narg)
        ktp->ktr_narg = narg;
        argp = (int *)((char *)ktp + sizeof(struct ktr_syscall));
        for (i = 0; i < narg; i++)
        ktp->ktr_narg = narg;
        argp = (int *)((char *)ktp + sizeof(struct ktr_syscall));
        for (i = 0; i < narg; i++)
-               *argp++ = u.u_arg[i];
+               *argp++ = args[i];
        kth->ktr_buf = (caddr_t)ktp;
        kth->ktr_len = len;
        ktrwrite(vp, kth);
        kth->ktr_buf = (caddr_t)ktp;
        kth->ktr_len = len;
        ktrwrite(vp, kth);
@@ -71,26 +75,23 @@ ktrsyscall(vp, code, narg)
        FREE(kth, M_TEMP);
 }
 
        FREE(kth, M_TEMP);
 }
 
-ktrsysret(vp, code)
+ktrsysret(vp, code, error, retval)
        struct vnode *vp;
        struct vnode *vp;
+       int code, error, retval;
 {
        struct ktr_header *kth = ktrgetheader(KTR_SYSRET);
 {
        struct ktr_header *kth = ktrgetheader(KTR_SYSRET);
-       struct ktr_sysret *ktp;
+       struct ktr_sysret ktp;
 
        if (kth == NULL)
                return;
 
        if (kth == NULL)
                return;
-       MALLOC(ktp, struct ktr_sysret *, sizeof(struct ktr_sysret),
-               M_TEMP , M_WAITOK);
-       ktp->ktr_code = code;
-       ktp->ktr_eosys = u.u_eosys;
-       ktp->ktr_error = u.u_error;
-       ktp->ktr_retval = u.u_r.r_val1;         /* what about val2 ? */
+       ktp.ktr_code = code;
+       ktp.ktr_error = error;
+       ktp.ktr_retval = retval;                /* what about val2 ? */
 
 
-       kth->ktr_buf = (caddr_t)ktp;
+       kth->ktr_buf = (caddr_t)&ktp;
        kth->ktr_len = sizeof(struct ktr_sysret);
 
        ktrwrite(vp, kth);
        kth->ktr_len = sizeof(struct ktr_sysret);
 
        ktrwrite(vp, kth);
-       FREE(ktp, M_TEMP);
        FREE(kth, M_TEMP);
 }
 
        FREE(kth, M_TEMP);
 }
 
@@ -109,8 +110,9 @@ ktrnamei(vp, path)
        FREE(kth, M_TEMP);
 }
 
        FREE(kth, M_TEMP);
 }
 
-ktrgenio(vp, fd, rw, iov, len)
+ktrgenio(vp, fd, rw, iov, len, error)
        struct vnode *vp;
        struct vnode *vp;
+       int fd;
        enum uio_rw rw;
        register struct iovec *iov;
 {
        enum uio_rw rw;
        register struct iovec *iov;
 {
@@ -119,7 +121,7 @@ ktrgenio(vp, fd, rw, iov, len)
        register caddr_t cp;
        register int resid = len, cnt;
        
        register caddr_t cp;
        register int resid = len, cnt;
        
-       if (kth == NULL || u.u_error)
+       if (kth == NULL || error)
                return;
        MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len,
                M_TEMP, M_WAITOK);
                return;
        MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len,
                M_TEMP, M_WAITOK);
@@ -129,7 +131,7 @@ ktrgenio(vp, fd, rw, iov, len)
        while (resid > 0) {
                if ((cnt = iov->iov_len) > resid)
                        cnt = resid;
        while (resid > 0) {
                if ((cnt = iov->iov_len) > resid)
                        cnt = resid;
-               if (copyin(iov->iov_base, cp, cnt))
+               if (copyin(iov->iov_base, cp, (unsigned)cnt))
                        goto done;
                cp += cnt;
                resid -= cnt;
                        goto done;
                cp += cnt;
                resid -= cnt;
@@ -144,44 +146,69 @@ done:
        FREE(ktp, M_TEMP);
 }
 
        FREE(ktp, M_TEMP);
 }
 
+ktrpsig(vp, sig, action, mask, code)
+       struct  vnode *vp;
+       sig_t   action;
+{
+       struct ktr_header *kth = ktrgetheader(KTR_PSIG);
+       struct ktr_psig kp;
+
+       if (kth == NULL)
+               return;
+       kp.signo = (char)sig;
+       kp.action = action;
+       kp.mask = mask;
+       kp.code = code;
+       kth->ktr_buf = (caddr_t)&kp;
+       kth->ktr_len = sizeof (struct ktr_psig);
+
+       ktrwrite(vp, kth);
+       FREE(kth, M_TEMP);
+}
+
+/* Interface and common routines */
+
 /*
  * ktrace system call
  */
 /*
  * ktrace system call
  */
-ktrace()
-{
-       register struct a {
+/* ARGSUSED */
+ktrace(curp, uap, retval)
+       struct proc *curp;
+       register struct args {
                char    *fname;
                int     ops;
                int     facs;
                int     pid;
                char    *fname;
                int     ops;
                int     facs;
                int     pid;
-       } *uap = (struct a *)u.u_ap;
+       } *uap;
+       int *retval;
+{
        register struct vnode *vp = NULL;
        register struct nameidata *ndp = &u.u_nd;
        register struct proc *p;
        register struct vnode *vp = NULL;
        register struct nameidata *ndp = &u.u_nd;
        register struct proc *p;
+       register ops = KTROP(uap->ops);
        struct pgrp *pg;
        struct pgrp *pg;
-       register int ops = uap->ops&0x3;
        register int facs = uap->facs;
        register int ret = 0;
        register int facs = uap->facs;
        register int ret = 0;
+       int error = 0;
 
        /*
         * Until security implications are thought through,
         * limit tracing to root (unless ktrace_nocheck is set).
         */
 
        /*
         * Until security implications are thought through,
         * limit tracing to root (unless ktrace_nocheck is set).
         */
-       if (!ktrace_nocheck && (u.u_error = suser(u.u_cred, &u.u_acflag)))
-               return;
+       if (!ktrace_nocheck && (error = suser(u.u_cred, &u.u_acflag)))
+               return (error);
        if (ops != KTROP_CLEAR) {
                /*
                 * an operation which requires a file argument.
                 */
                ndp->ni_segflg = UIO_USERSPACE;
                ndp->ni_dirp = uap->fname;
        if (ops != KTROP_CLEAR) {
                /*
                 * an operation which requires a file argument.
                 */
                ndp->ni_segflg = UIO_USERSPACE;
                ndp->ni_dirp = uap->fname;
-               if (u.u_error = vn_open(ndp, FREAD|FWRITE, 0))
-                       return;
+               if (error = vn_open(ndp, FREAD|FWRITE, 0))
+                       return (error);
                vp = ndp->ni_vp;
                if (vp->v_type != VREG) {
                vp = ndp->ni_vp;
                if (vp->v_type != VREG) {
-                       u.u_error = EACCES;
                        vrele(vp);
                        vrele(vp);
-                       return;
+                       return (EACCES);
                }
        }
        /*
                }
        }
        /*
@@ -190,7 +217,6 @@ ktrace()
        if (ops == KTROP_CLEARFILE) {
                for (p = allproc; p != NULL; p = p->p_nxt) {
                        if (p->p_tracep == vp) {
        if (ops == KTROP_CLEARFILE) {
                for (p = allproc; p != NULL; p = p->p_nxt) {
                        if (p->p_tracep == vp) {
-                               p->p_flag &= ~SKTR;
                                p->p_tracep = NULL;
                                p->p_traceflag = 0;
                                vrele(vp);
                                p->p_tracep = NULL;
                                p->p_traceflag = 0;
                                vrele(vp);
@@ -198,23 +224,24 @@ ktrace()
                }
                goto done;
        }
                }
                goto done;
        }
-
        /*
         * need something to (un)trace
         */
        if (!facs) {
        /*
         * need something to (un)trace
         */
        if (!facs) {
-               u.u_error = EINVAL;
+               error = EINVAL;
                goto done;
        }
                goto done;
        }
-
+       /* 
+        * doit
+        */
        if (uap->pid < 0) {
                pg = pgfind(-uap->pid);
                if (pg == NULL) {
        if (uap->pid < 0) {
                pg = pgfind(-uap->pid);
                if (pg == NULL) {
-                       u.u_error = ESRCH;
+                       error = ESRCH;
                        goto done;
                }
                for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt)
                        goto done;
                }
                for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt)
-                       if (uap->ops&KTROP_INHERITFLAG)
+                       if (uap->ops&KTRFLAG_DESCEND)
                                ret |= ktrsetchildren(p, ops, facs, vp);
                        else 
                                ret |= ktrops(p, ops, facs, vp);
                                ret |= ktrsetchildren(p, ops, facs, vp);
                        else 
                                ret |= ktrops(p, ops, facs, vp);
@@ -222,19 +249,20 @@ ktrace()
        } else {
                p = pfind(uap->pid);
                if (p == NULL) {
        } else {
                p = pfind(uap->pid);
                if (p == NULL) {
-                       u.u_error = ESRCH;
+                       error = ESRCH;
                        goto done;
                }
                        goto done;
                }
-               if (uap->ops&KTROP_INHERITFLAG)
+               if (ops&KTRFLAG_DESCEND)
                        ret |= ktrsetchildren(p, ops, facs, vp);
                else
                        ret |= ktrops(p, ops, facs, vp);
        }
        if (!ret)
                        ret |= ktrsetchildren(p, ops, facs, vp);
                else
                        ret |= ktrops(p, ops, facs, vp);
        }
        if (!ret)
-               u.u_error = EPERM;
+               error = EPERM;
 done:
        if (vp != NULL)
                vrele(vp);
 done:
        if (vp != NULL)
                vrele(vp);
+       return (error);
 }
 
 ktrops(p, ops, facs, vp)
 }
 
 ktrops(p, ops, facs, vp)
@@ -243,9 +271,9 @@ ktrops(p, ops, facs, vp)
 {
 
        if (u.u_uid && u.u_uid != p->p_uid)
 {
 
        if (u.u_uid && u.u_uid != p->p_uid)
-               return 0;
+               return (0);
        if (ops == KTROP_SET) {
        if (ops == KTROP_SET) {
-               if (p->p_tracep != vp) {
+               if (p->p_tracep != vp) { 
                        /*
                         * if trace file already in use, relinquish
                         */
                        /*
                         * if trace file already in use, relinquish
                         */
@@ -257,12 +285,13 @@ ktrops(p, ops, facs, vp)
                p->p_traceflag |= facs;
        } else {        
                /* KTROP_CLEAR */
                p->p_traceflag |= facs;
        } else {        
                /* KTROP_CLEAR */
-               if ((p->p_traceflag &= ~facs) == 0) {
+               if (((p->p_traceflag &= ~facs) & ~KTRFAC_INHERIT) == 0) {
+                       /* no more tracing */
+                       p->p_traceflag = 0;
                        if (p->p_tracep != NULL) {
                                vrele(p->p_tracep);
                                p->p_tracep = NULL;
                        }
                        if (p->p_tracep != NULL) {
                                vrele(p->p_tracep);
                                p->p_tracep = NULL;
                        }
-                       p->p_flag &= ~SKTR;
                }
        }
 
                }
        }
 
@@ -274,13 +303,11 @@ ktrsetchildren(top, ops, facs, vp)
        struct vnode *vp;
 {
        register struct proc *p;
        struct vnode *vp;
 {
        register struct proc *p;
-       register int ndx;
        register int ret = 0;
 
        p = top;
        for (;;) {
        register int ret = 0;
 
        p = top;
        for (;;) {
-               if ((ret |= ktrops(p, ops, facs, vp)) && ops == KTROP_SET)
-                       p->p_flag |= SKTR;
+               ret |= ktrops(p, ops, facs, vp);
                /*
                 * If this process has children, descend to them next,
                 * otherwise do any siblings, and if done with this level,
                /*
                 * If this process has children, descend to them next,
                 * otherwise do any siblings, and if done with this level,
@@ -311,6 +338,7 @@ ktrwrite(vp, kth)
 {
        struct uio auio;
        struct iovec aiov[2];
 {
        struct uio auio;
        struct iovec aiov[2];
+       struct proc *p;
        int error;
 
        if (vp == NULL)
        int error;
 
        if (vp == NULL)
@@ -332,5 +360,18 @@ ktrwrite(vp, kth)
        VOP_LOCK(vp);
        error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, u.u_cred);
        VOP_UNLOCK(vp);
        VOP_LOCK(vp);
        error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, u.u_cred);
        VOP_UNLOCK(vp);
+       if (!error)
+               return;
+       /*
+        * If error encountered, give up tracing on this vnode.
+        */
+       uprintf("\ntrace write failed with errno %d, tracing stopped\n", error);
+       for (p = allproc; p != NULL; p = p->p_nxt) {
+               if (p->p_tracep == vp) {
+                       p->p_tracep = NULL;
+                       p->p_traceflag = 0;
+                       vrele(vp);
+               }
+       }
 }
 #endif
 }
 #endif