new calling convension for system calls
[unix-history] / usr / src / sys / kern / kern_ktrace.c
index 29080b3..5aaca9a 100644 (file)
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)kern_ktrace.c       1.2 (Berkeley) %G%
+ *     @(#)kern_ktrace.c       7.5 (Berkeley) %G%
  */
 
 #ifdef KTRACE
 
 #include "param.h"
  */
 
 #ifdef KTRACE
 
 #include "param.h"
-#include "systm.h"
-#include "dir.h"
 #include "user.h"
 #include "user.h"
-#include "assym.s"
 #include "proc.h"
 #include "proc.h"
-#include "seg.h"
-#include "acct.h"
-#include "fs.h"
-#include "inode.h"
-#include "syslog.h"
-#include "kernel.h"
+#include "file.h"
+#include "vnode.h"
 #include "ktrace.h"
 #include "malloc.h"
 
 #include "ktrace.h"
 #include "malloc.h"
 
-#include "../sys/syscalls.c"
+#include "syscalls.c"
 
 extern int nsysent;
 extern char *syscallnames[];
 
 
 extern int nsysent;
 extern char *syscallnames[];
 
+int ktrace_nocheck = 1;
+
 struct ktr_header *
 ktrgetheader(type)
 {
 struct ktr_header *
 ktrgetheader(type)
 {
@@ -46,34 +41,24 @@ ktrgetheader(type)
 
        MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 
                M_TEMP, M_WAITOK);
 
        MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 
                M_TEMP, M_WAITOK);
-       if (kth == NULL)
-               return (NULL);
        kth->ktr_type = type;
        kth->ktr_type = type;
-       kth->ktr_time = time;
+       microtime(&kth->ktr_time);
        kth->ktr_pid = u.u_procp->p_pid;
        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(ip, code, narg)
-       struct inode *ip;
+ktrsyscall(vp, code, narg)
+       struct vnode *vp;
 {
        struct  ktr_header *kth = ktrgetheader(KTR_SYSCALL);
        struct  ktr_syscall *ktp;
        register len = sizeof(struct ktr_syscall) + (narg * sizeof(int));
        int     *argp, i;
 
 {
        struct  ktr_header *kth = ktrgetheader(KTR_SYSCALL);
        struct  ktr_syscall *ktp;
        register len = sizeof(struct ktr_syscall) + (narg * sizeof(int));
        int     *argp, i;
 
-       if (kth == NULL) {
-               printf("lost syscall trace - no header\n");     /* DEBUG */
+       if (kth == NULL)
                return;
                return;
-       }
        MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK);
        MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK);
-       if (ktp == NULL) {
-               printf("lost syscall trace - no buffer\n");     /* DEBUG */
-               FREE(kth, M_TEMP);
-               return;
-       }
        ktp->ktr_code = code;
        ktp->ktr_narg = narg;
        argp = (int *)((char *)ktp + sizeof(struct ktr_syscall));
        ktp->ktr_code = code;
        ktp->ktr_narg = narg;
        argp = (int *)((char *)ktp + sizeof(struct ktr_syscall));
@@ -81,79 +66,124 @@ ktrsyscall(ip, code, narg)
                *argp++ = u.u_arg[i];
        kth->ktr_buf = (caddr_t)ktp;
        kth->ktr_len = len;
                *argp++ = u.u_arg[i];
        kth->ktr_buf = (caddr_t)ktp;
        kth->ktr_len = len;
-       ktrwrite(ip, kth);
+       ktrwrite(vp, kth);
        FREE(ktp, M_TEMP);
        FREE(kth, M_TEMP);
 }
 
        FREE(ktp, M_TEMP);
        FREE(kth, M_TEMP);
 }
 
-ktrsysret(ip, code)
-       struct inode *ip;
+ktrsysret(vp, code)
+       struct vnode *vp;
 {
        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) {
-               printf("lost syscall ret - no header\n");       /* DEBUG */
-               return;
-       }
-       MALLOC(ktp, struct ktr_sysret *, sizeof(struct ktr_sysret),
-               M_TEMP , M_WAITOK);
-       if (ktp == NULL) {
-               printf("lost syscall ret - no buffer\n");       /* DEBUG */
-               FREE(kth, M_TEMP);
+       if (kth == NULL)
                return;
                return;
-       }
-       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 = u.u_error;
+       ktp.ktr_retval = u.u_r.r_val1;          /* what about val2 ? */
 
 
-       kth->ktr_buf = (caddr_t)ktp;
+       kth->ktr_buf = (caddr_t)&ktp;
        kth->ktr_len = sizeof(struct ktr_sysret);
 
        kth->ktr_len = sizeof(struct ktr_sysret);
 
-       ktrwrite(ip, kth);
-       FREE(ktp, M_TEMP);
+       ktrwrite(vp, kth);
        FREE(kth, M_TEMP);
 }
 
        FREE(kth, M_TEMP);
 }
 
-ktrnamei(ip, path)
-       struct inode *ip;
+ktrnamei(vp, path)
+       struct vnode *vp;
        char *path;
 {
        struct ktr_header *kth = ktrgetheader(KTR_NAMEI);
 
        char *path;
 {
        struct ktr_header *kth = ktrgetheader(KTR_NAMEI);
 
-       if (kth == NULL) {
-               printf("lost namei - no header\n");     /* DEBUG */
+       if (kth == NULL)
                return;
                return;
-       }
        kth->ktr_len = strlen(path);
        kth->ktr_buf = path;
 
        kth->ktr_len = strlen(path);
        kth->ktr_buf = path;
 
-       ktrwrite(ip, kth);
+       ktrwrite(vp, kth);
        FREE(kth, M_TEMP);
 }
 
        FREE(kth, M_TEMP);
 }
 
+ktrgenio(vp, fd, rw, iov, len)
+       struct vnode *vp;
+       enum uio_rw rw;
+       register struct iovec *iov;
+{
+       struct ktr_header *kth = ktrgetheader(KTR_GENIO);
+       register struct ktr_genio *ktp;
+       register caddr_t cp;
+       register int resid = len, cnt;
+       
+       if (kth == NULL || u.u_error)
+               return;
+       MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len,
+               M_TEMP, M_WAITOK);
+       ktp->ktr_fd = fd;
+       ktp->ktr_rw = rw;
+       cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio));
+       while (resid > 0) {
+               if ((cnt = iov->iov_len) > resid)
+                       cnt = resid;
+               if (copyin(iov->iov_base, cp, (unsigned)cnt))
+                       goto done;
+               cp += cnt;
+               resid -= cnt;
+               iov++;
+       }
+       kth->ktr_buf = (caddr_t)ktp;
+       kth->ktr_len = sizeof (struct ktr_genio) + len;
+
+       ktrwrite(vp, kth);
+done:
+       FREE(kth, 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()
 {
 /*
  * ktrace system call
  */
 ktrace()
 {
-       register struct inode *ip = NULL;
        register struct a {
                char    *fname;
                int     ops;
                int     facs;
        register struct a {
                char    *fname;
                int     ops;
                int     facs;
-               pid_t   pid;
+               int     pid;
        } *uap = (struct a *)u.u_ap;
        } *uap = (struct a *)u.u_ap;
+       register struct vnode *vp = NULL;
        register struct nameidata *ndp = &u.u_nd;
        register struct proc *p;
        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 facs = uap->facs;
+       register int ret = 0;
 
        /*
         * Until security implications are thought through,
 
        /*
         * Until security implications are thought through,
-        * limit tracing to root.
+        * 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 && (u.u_error = suser(u.u_cred, &u.u_acflag)))
                return;
@@ -161,39 +191,30 @@ ktrace()
                /*
                 * an operation which requires a file argument.
                 */
                /*
                 * an operation which requires a file argument.
                 */
-               ndp->ni_nameiop = LOOKUP | FOLLOW;
                ndp->ni_segflg = UIO_USERSPACE;
                ndp->ni_dirp = uap->fname;
                ndp->ni_segflg = UIO_USERSPACE;
                ndp->ni_dirp = uap->fname;
-               ip = namei(ndp);
-               if (ip == NULL)
+               if (u.u_error = vn_open(ndp, FREAD|FWRITE, 0))
                        return;
                        return;
-               if ((ip->i_mode&IFMT) != IFREG) {
+               vp = ndp->ni_vp;
+               if (vp->v_type != VREG) {
                        u.u_error = EACCES;
                        u.u_error = EACCES;
-                       iput(ip);
+                       vrele(vp);
                        return;
                }
                        return;
                }
-               if (ip->i_fs->fs_ronly) {
-                       u.u_error = EROFS;
-                       iput(ip);
-                       return;
-               }
-               iunlock(ip);
        }
        /*
         * Clear all uses of the tracefile
         */
        if (ops == KTROP_CLEARFILE) {
                for (p = allproc; p != NULL; p = p->p_nxt) {
        }
        /*
         * Clear all uses of the tracefile
         */
        if (ops == KTROP_CLEARFILE) {
                for (p = allproc; p != NULL; p = p->p_nxt) {
-                       if (p->p_tracep == ip) {
-                               p->p_flag &= ~SKTR;
+                       if (p->p_tracep == vp) {
                                p->p_tracep = NULL;
                                p->p_traceflag = 0;
                                p->p_tracep = NULL;
                                p->p_traceflag = 0;
-                               irele(ip);
+                               vrele(vp);
                        }
                }
                goto done;
        }
                        }
                }
                goto done;
        }
-
        /*
         * need something to (un)trace
         */
        /*
         * need something to (un)trace
         */
@@ -201,7 +222,9 @@ ktrace()
                u.u_error = EINVAL;
                goto done;
        }
                u.u_error = EINVAL;
                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) {
@@ -209,10 +232,10 @@ ktrace()
                        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)
-                               ktrsetchildren(p, ops, facs, ip);
+                       if (uap->ops&KTRFLAG_DESCEND)
+                               ret |= ktrsetchildren(p, ops, facs, vp);
                        else 
                        else 
-                               ktrops(p, ops, facs, ip);
+                               ret |= ktrops(p, ops, facs, vp);
                                        
        } else {
                p = pfind(uap->pid);
                                        
        } else {
                p = pfind(uap->pid);
@@ -220,56 +243,61 @@ ktrace()
                        u.u_error = ESRCH;
                        goto done;
                }
                        u.u_error = ESRCH;
                        goto done;
                }
-               if (uap->ops&KTROP_INHERITFLAG)
-                       ktrsetchildren(p, ops, facs, ip);
+               if (ops&KTRFLAG_DESCEND)
+                       ret |= ktrsetchildren(p, ops, facs, vp);
                else
                else
-                       ktrops(p, ops, facs, ip);
+                       ret |= ktrops(p, ops, facs, vp);
        }
        }
+       if (!ret)
+               u.u_error = EPERM;
 done:
 done:
-       if (ip != NULL)
-               irele(ip);
+       if (vp != NULL)
+               vrele(vp);
 }
 
 }
 
-ktrops(p, ops, facs, ip)
+ktrops(p, ops, facs, vp)
        struct proc *p;
        struct proc *p;
-       struct inode *ip;
+       struct vnode *vp;
 {
 {
+
+       if (u.u_uid && u.u_uid != p->p_uid)
+               return 0;
        if (ops == KTROP_SET) {
        if (ops == KTROP_SET) {
-               if (p->p_tracep != ip) {
+               if (p->p_tracep != vp) { 
                        /*
                         * if trace file already in use, relinquish
                         */
                        if (p->p_tracep != NULL)
                        /*
                         * if trace file already in use, relinquish
                         */
                        if (p->p_tracep != NULL)
-                               irele(p->p_tracep);
-                       igrab(ip);
-                       p->p_tracep = ip;
-                       iunlock(ip);
+                               vrele(p->p_tracep);
+                       VREF(vp);
+                       p->p_tracep = 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) {
                        if (p->p_tracep != NULL) {
-                               irele(p->p_tracep);
+                               vrele(p->p_tracep);
                                p->p_tracep = NULL;
                        }
                                p->p_tracep = NULL;
                        }
-                       p->p_flag &= SKTR;
                }
        }
                }
        }
+
+       return 1;
 }
 }
-               
-ktrsetchildren(top, ops, facs, ip)
+
+ktrsetchildren(top, ops, facs, vp)
        struct proc *top;
        struct proc *top;
-       struct inode *ip;
+       struct vnode *vp;
 {
        register struct proc *p;
 {
        register struct proc *p;
-       register int ndx;
+       register int ret = 0;
 
        p = top;
        for (;;) {
 
        p = top;
        for (;;) {
-               if (ops == KTROP_SET)
-                       p->p_flag |= SKTR;
-               ktrops(p, ops, facs, ip);
+               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,
@@ -278,46 +306,62 @@ ktrsetchildren(top, ops, facs, ip)
                if (p->p_cptr)
                        p = p->p_cptr;
                else if (p == top)
                if (p->p_cptr)
                        p = p->p_cptr;
                else if (p == top)
-                       return;
+                       return ret;
                else if (p->p_osptr)
                        p = p->p_osptr;
                else for (;;) {
                        p = p->p_pptr;
                        if (p == top)
                else if (p->p_osptr)
                        p = p->p_osptr;
                else for (;;) {
                        p = p->p_pptr;
                        if (p == top)
-                               return;
+                               return ret;
                        if (p->p_osptr) {
                                p = p->p_osptr;
                                break;
                        }
                }
        }
                        if (p->p_osptr) {
                                p = p->p_osptr;
                                break;
                        }
                }
        }
+       /*NOTREACHED*/
 }
 
 }
 
-ktrwrite(ip, kth)
-       register struct inode *ip;
-       struct ktr_header *kth;
+ktrwrite(vp, kth)
+       struct vnode *vp;
+       register struct ktr_header *kth;
 {
 {
-       int save = u.u_error;
-       int osize;
-       
-       ilock(ip);
-       osize = ip->i_size;
-       u.u_error = 0;
-       u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)kth, 
-                       sizeof(struct ktr_header), ip->i_size, 1, (int *)0);
-       if (u.u_error) {
-               itrunc(ip, (u_long)osize);
-               goto end;
-       }
+       struct uio auio;
+       struct iovec aiov[2];
+       struct proc *p;
+       int error;
+
+       if (vp == NULL)
+               return;
+       auio.uio_iov = &aiov[0];
+       auio.uio_offset = 0;
+       auio.uio_segflg = UIO_SYSSPACE;
+       auio.uio_rw = UIO_WRITE;
+       aiov[0].iov_base = (caddr_t)kth;
+       aiov[0].iov_len = sizeof(struct ktr_header);
+       auio.uio_resid = sizeof(struct ktr_header);
+       auio.uio_iovcnt = 1;
        if (kth->ktr_len > 0) {
        if (kth->ktr_len > 0) {
-               u.u_error = rdwri(UIO_WRITE, ip, kth->ktr_buf,
-                           kth->ktr_len, ip->i_size, 1, (int *)0);
-               if (u.u_error)
-                       itrunc(ip, (u_long)osize);
+               auio.uio_iovcnt++;
+               aiov[1].iov_base = kth->ktr_buf;
+               aiov[1].iov_len = kth->ktr_len;
+               auio.uio_resid += kth->ktr_len;
+       }
+       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);
+               }
        }
        }
-end:
-       u.u_error = save;
-       iunlock(ip);
 }
 }
-
 #endif
 #endif