136359Smarc /* 236359Smarc * Copyright (c) 1989 The Regents of the University of California. 336359Smarc * All rights reserved. 436359Smarc * 5*44436Sbostic * %sccs.include.redist.c% 636359Smarc * 7*44436Sbostic * @(#)kern_ktrace.c 7.9 (Berkeley) 06/28/90 836359Smarc */ 936359Smarc 1036359Smarc #ifdef KTRACE 1136359Smarc 1236359Smarc #include "param.h" 1344404Skarels #include "user.h" 1436359Smarc #include "proc.h" 1537728Smckusick #include "file.h" 1637728Smckusick #include "vnode.h" 1736359Smarc #include "ktrace.h" 1836359Smarc #include "malloc.h" 1936359Smarc 2037593Smarc #include "syscalls.c" 2136359Smarc 2236359Smarc extern int nsysent; 2336359Smarc extern char *syscallnames[]; 2436359Smarc 2544385Smarc int ktrace_nocheck = 0; /* set to 1 when security checks in place */ 2637593Smarc 2736359Smarc struct ktr_header * 2836359Smarc ktrgetheader(type) 2936359Smarc { 3036359Smarc register struct ktr_header *kth; 3136359Smarc 3236359Smarc MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 3336359Smarc M_TEMP, M_WAITOK); 3436359Smarc kth->ktr_type = type; 3537593Smarc microtime(&kth->ktr_time); 3636359Smarc kth->ktr_pid = u.u_procp->p_pid; 3740805Smarc bcopy(u.u_procp->p_comm, kth->ktr_comm, MAXCOMLEN); 3836359Smarc return (kth); 3936359Smarc } 4036359Smarc 4143444Smckusick ktrsyscall(vp, code, narg, args) 4237728Smckusick struct vnode *vp; 4343444Smckusick int code, narg, args[]; 4436359Smarc { 4536359Smarc struct ktr_header *kth = ktrgetheader(KTR_SYSCALL); 4636359Smarc struct ktr_syscall *ktp; 4736359Smarc register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); 4836359Smarc int *argp, i; 4936359Smarc 5037593Smarc if (kth == NULL) 5136359Smarc return; 5236359Smarc MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); 5336359Smarc ktp->ktr_code = code; 5436359Smarc ktp->ktr_narg = narg; 5536359Smarc argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); 5636359Smarc for (i = 0; i < narg; i++) 5743444Smckusick *argp++ = args[i]; 5836359Smarc kth->ktr_buf = (caddr_t)ktp; 5936359Smarc kth->ktr_len = len; 6037728Smckusick ktrwrite(vp, kth); 6136359Smarc FREE(ktp, M_TEMP); 6236359Smarc FREE(kth, M_TEMP); 6336359Smarc } 6436359Smarc 6543444Smckusick ktrsysret(vp, code, error, retval) 6637728Smckusick struct vnode *vp; 6743444Smckusick int code, error, retval; 6836359Smarc { 6936359Smarc struct ktr_header *kth = ktrgetheader(KTR_SYSRET); 7040805Smarc struct ktr_sysret ktp; 7136359Smarc 7237593Smarc if (kth == NULL) 7336359Smarc return; 7440805Smarc ktp.ktr_code = code; 7543444Smckusick ktp.ktr_error = error; 7643444Smckusick ktp.ktr_retval = retval; /* what about val2 ? */ 7736359Smarc 7840805Smarc kth->ktr_buf = (caddr_t)&ktp; 7936359Smarc kth->ktr_len = sizeof(struct ktr_sysret); 8036359Smarc 8137728Smckusick ktrwrite(vp, kth); 8236359Smarc FREE(kth, M_TEMP); 8336359Smarc } 8436359Smarc 8537728Smckusick ktrnamei(vp, path) 8637728Smckusick struct vnode *vp; 8736359Smarc char *path; 8836359Smarc { 8936359Smarc struct ktr_header *kth = ktrgetheader(KTR_NAMEI); 9036359Smarc 9137593Smarc if (kth == NULL) 9236359Smarc return; 9336359Smarc kth->ktr_len = strlen(path); 9436359Smarc kth->ktr_buf = path; 9536359Smarc 9637728Smckusick ktrwrite(vp, kth); 9736359Smarc FREE(kth, M_TEMP); 9836359Smarc } 9936359Smarc 10043444Smckusick ktrgenio(vp, fd, rw, iov, len, error) 10137728Smckusick struct vnode *vp; 10243444Smckusick int fd; 10337593Smarc enum uio_rw rw; 10437593Smarc register struct iovec *iov; 10537593Smarc { 10637593Smarc struct ktr_header *kth = ktrgetheader(KTR_GENIO); 10737593Smarc register struct ktr_genio *ktp; 10837593Smarc register caddr_t cp; 10937593Smarc register int resid = len, cnt; 11037593Smarc 11143444Smckusick if (kth == NULL || error) 11237593Smarc return; 11337593Smarc MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, 11437593Smarc M_TEMP, M_WAITOK); 11537593Smarc ktp->ktr_fd = fd; 11637593Smarc ktp->ktr_rw = rw; 11737593Smarc cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); 11837593Smarc while (resid > 0) { 11937593Smarc if ((cnt = iov->iov_len) > resid) 12037593Smarc cnt = resid; 12141573Smckusick if (copyin(iov->iov_base, cp, (unsigned)cnt)) 12237593Smarc goto done; 12337593Smarc cp += cnt; 12437593Smarc resid -= cnt; 12537593Smarc iov++; 12637593Smarc } 12737593Smarc kth->ktr_buf = (caddr_t)ktp; 12837593Smarc kth->ktr_len = sizeof (struct ktr_genio) + len; 12937593Smarc 13037728Smckusick ktrwrite(vp, kth); 13137593Smarc done: 13237593Smarc FREE(kth, M_TEMP); 13337593Smarc FREE(ktp, M_TEMP); 13437593Smarc } 13537593Smarc 13640805Smarc ktrpsig(vp, sig, action, mask, code) 13740805Smarc struct vnode *vp; 13840805Smarc sig_t action; 13940805Smarc { 14040805Smarc struct ktr_header *kth = ktrgetheader(KTR_PSIG); 14140805Smarc struct ktr_psig kp; 14240805Smarc 14340805Smarc if (kth == NULL) 14440805Smarc return; 14540805Smarc kp.signo = (char)sig; 14640805Smarc kp.action = action; 14740805Smarc kp.mask = mask; 14840805Smarc kp.code = code; 14940805Smarc kth->ktr_buf = (caddr_t)&kp; 15040805Smarc kth->ktr_len = sizeof (struct ktr_psig); 15140805Smarc 15240805Smarc ktrwrite(vp, kth); 15340805Smarc FREE(kth, M_TEMP); 15440805Smarc } 15540805Smarc 15640805Smarc /* Interface and common routines */ 15740805Smarc 15836359Smarc /* 15936359Smarc * ktrace system call 16036359Smarc */ 16143444Smckusick /* ARGSUSED */ 16243444Smckusick ktrace(curp, uap, retval) 16343444Smckusick struct proc *curp; 16443444Smckusick register struct args { 16536359Smarc char *fname; 16636359Smarc int ops; 16736359Smarc int facs; 16837593Smarc int pid; 16943444Smckusick } *uap; 17043444Smckusick int *retval; 17143444Smckusick { 17237728Smckusick register struct vnode *vp = NULL; 17336359Smarc register struct nameidata *ndp = &u.u_nd; 17436359Smarc register struct proc *p; 17540805Smarc register ops = KTROP(uap->ops); 17636359Smarc struct pgrp *pg; 17736359Smarc register int facs = uap->facs; 17837593Smarc register int ret = 0; 17943444Smckusick int error = 0; 18036359Smarc 18136359Smarc /* 18236359Smarc * Until security implications are thought through, 18337593Smarc * limit tracing to root (unless ktrace_nocheck is set). 18436359Smarc */ 18543444Smckusick if (!ktrace_nocheck && (error = suser(u.u_cred, &u.u_acflag))) 18644404Skarels return (error); 18736359Smarc if (ops != KTROP_CLEAR) { 18836359Smarc /* 18936359Smarc * an operation which requires a file argument. 19036359Smarc */ 19136359Smarc ndp->ni_segflg = UIO_USERSPACE; 19236359Smarc ndp->ni_dirp = uap->fname; 19343444Smckusick if (error = vn_open(ndp, FREAD|FWRITE, 0)) 19444404Skarels return (error); 19537728Smckusick vp = ndp->ni_vp; 19637728Smckusick if (vp->v_type != VREG) { 19737728Smckusick vrele(vp); 19844404Skarels return (EACCES); 19936359Smarc } 20036359Smarc } 20136359Smarc /* 20236359Smarc * Clear all uses of the tracefile 20336359Smarc */ 20436359Smarc if (ops == KTROP_CLEARFILE) { 20536359Smarc for (p = allproc; p != NULL; p = p->p_nxt) { 20637728Smckusick if (p->p_tracep == vp) { 20736359Smarc p->p_tracep = NULL; 20836359Smarc p->p_traceflag = 0; 20937728Smckusick vrele(vp); 21036359Smarc } 21136359Smarc } 21236359Smarc goto done; 21336359Smarc } 21436359Smarc /* 21536359Smarc * need something to (un)trace 21636359Smarc */ 21736359Smarc if (!facs) { 21843444Smckusick error = EINVAL; 21936359Smarc goto done; 22036359Smarc } 22140805Smarc /* 22240805Smarc * doit 22340805Smarc */ 22436359Smarc if (uap->pid < 0) { 22536359Smarc pg = pgfind(-uap->pid); 22636359Smarc if (pg == NULL) { 22743444Smckusick error = ESRCH; 22836359Smarc goto done; 22936359Smarc } 23036359Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) 23140805Smarc if (uap->ops&KTRFLAG_DESCEND) 23237728Smckusick ret |= ktrsetchildren(p, ops, facs, vp); 23336359Smarc else 23437728Smckusick ret |= ktrops(p, ops, facs, vp); 23536359Smarc 23636359Smarc } else { 23736359Smarc p = pfind(uap->pid); 23836359Smarc if (p == NULL) { 23943444Smckusick error = ESRCH; 24036359Smarc goto done; 24136359Smarc } 24240805Smarc if (ops&KTRFLAG_DESCEND) 24337728Smckusick ret |= ktrsetchildren(p, ops, facs, vp); 24436359Smarc else 24537728Smckusick ret |= ktrops(p, ops, facs, vp); 24636359Smarc } 24737593Smarc if (!ret) 24843444Smckusick error = EPERM; 24936359Smarc done: 25037728Smckusick if (vp != NULL) 25137728Smckusick vrele(vp); 25244404Skarels return (error); 25336359Smarc } 25436359Smarc 25537728Smckusick ktrops(p, ops, facs, vp) 25636359Smarc struct proc *p; 25737728Smckusick struct vnode *vp; 25836359Smarc { 25937593Smarc 26037593Smarc if (u.u_uid && u.u_uid != p->p_uid) 26144404Skarels return (0); 26236359Smarc if (ops == KTROP_SET) { 26340805Smarc if (p->p_tracep != vp) { 26436359Smarc /* 26536359Smarc * if trace file already in use, relinquish 26636359Smarc */ 26736359Smarc if (p->p_tracep != NULL) 26837728Smckusick vrele(p->p_tracep); 26938423Smarc VREF(vp); 27037728Smckusick p->p_tracep = vp; 27136359Smarc } 27236359Smarc p->p_traceflag |= facs; 27336359Smarc } else { 27436359Smarc /* KTROP_CLEAR */ 27540805Smarc if (((p->p_traceflag &= ~facs) & ~KTRFAC_INHERIT) == 0) { 27640805Smarc /* no more tracing */ 27740805Smarc p->p_traceflag = 0; 27836359Smarc if (p->p_tracep != NULL) { 27937728Smckusick vrele(p->p_tracep); 28036359Smarc p->p_tracep = NULL; 28136359Smarc } 28236359Smarc } 28336359Smarc } 28437593Smarc 28537593Smarc return 1; 28636359Smarc } 28737593Smarc 28837728Smckusick ktrsetchildren(top, ops, facs, vp) 28936359Smarc struct proc *top; 29037728Smckusick struct vnode *vp; 29136359Smarc { 29236359Smarc register struct proc *p; 29337593Smarc register int ret = 0; 29436359Smarc 29536359Smarc p = top; 29636359Smarc for (;;) { 29740805Smarc ret |= ktrops(p, ops, facs, vp); 29836359Smarc /* 29936359Smarc * If this process has children, descend to them next, 30036359Smarc * otherwise do any siblings, and if done with this level, 30136359Smarc * follow back up the tree (but not past top). 30236359Smarc */ 30336359Smarc if (p->p_cptr) 30436359Smarc p = p->p_cptr; 30536359Smarc else if (p == top) 30637593Smarc return ret; 30736359Smarc else if (p->p_osptr) 30836359Smarc p = p->p_osptr; 30936359Smarc else for (;;) { 31036359Smarc p = p->p_pptr; 31136359Smarc if (p == top) 31237593Smarc return ret; 31336359Smarc if (p->p_osptr) { 31436359Smarc p = p->p_osptr; 31536359Smarc break; 31636359Smarc } 31736359Smarc } 31836359Smarc } 31937593Smarc /*NOTREACHED*/ 32036359Smarc } 32136359Smarc 32237728Smckusick ktrwrite(vp, kth) 32337728Smckusick struct vnode *vp; 32437728Smckusick register struct ktr_header *kth; 32536359Smarc { 32637728Smckusick struct uio auio; 32737728Smckusick struct iovec aiov[2]; 32841573Smckusick struct proc *p; 32939581Smckusick int error; 33037728Smckusick 33137728Smckusick if (vp == NULL) 33237593Smarc return; 33337728Smckusick auio.uio_iov = &aiov[0]; 33437728Smckusick auio.uio_offset = 0; 33537728Smckusick auio.uio_segflg = UIO_SYSSPACE; 33637728Smckusick auio.uio_rw = UIO_WRITE; 33737728Smckusick aiov[0].iov_base = (caddr_t)kth; 33837728Smckusick aiov[0].iov_len = sizeof(struct ktr_header); 33937728Smckusick auio.uio_resid = sizeof(struct ktr_header); 34037728Smckusick auio.uio_iovcnt = 1; 34136359Smarc if (kth->ktr_len > 0) { 34237728Smckusick auio.uio_iovcnt++; 34337728Smckusick aiov[1].iov_base = kth->ktr_buf; 34437728Smckusick aiov[1].iov_len = kth->ktr_len; 34537728Smckusick auio.uio_resid += kth->ktr_len; 34636359Smarc } 34739581Smckusick VOP_LOCK(vp); 34839581Smckusick error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, u.u_cred); 34939581Smckusick VOP_UNLOCK(vp); 35041573Smckusick if (!error) 35141573Smckusick return; 35241573Smckusick /* 35341573Smckusick * If error encountered, give up tracing on this vnode. 35441573Smckusick */ 35541573Smckusick uprintf("\ntrace write failed with errno %d, tracing stopped\n", error); 35641573Smckusick for (p = allproc; p != NULL; p = p->p_nxt) { 35741573Smckusick if (p->p_tracep == vp) { 35841573Smckusick p->p_tracep = NULL; 35941573Smckusick p->p_traceflag = 0; 36041573Smckusick vrele(vp); 36141573Smckusick } 36241573Smckusick } 36336359Smarc } 36436359Smarc #endif 365