136359Smarc /* 236359Smarc * Copyright (c) 1989 The Regents of the University of California. 336359Smarc * All rights reserved. 436359Smarc * 536359Smarc * Redistribution and use in source and binary forms are permitted 636359Smarc * provided that the above copyright notice and this paragraph are 736359Smarc * duplicated in all such forms and that any documentation, 836359Smarc * advertising materials, and other materials related to such 936359Smarc * distribution and use acknowledge that the software was developed 1036359Smarc * by the University of California, Berkeley. The name of the 1136359Smarc * University may not be used to endorse or promote products derived 1236359Smarc * from this software without specific prior written permission. 1336359Smarc * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1436359Smarc * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1536359Smarc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1636359Smarc * 17*40805Smarc * @(#)kern_ktrace.c 7.3 (Berkeley) 04/05/90 1836359Smarc */ 1936359Smarc 2036359Smarc #ifdef KTRACE 2136359Smarc 2236359Smarc #include "param.h" 2336359Smarc #include "user.h" 2436359Smarc #include "proc.h" 2537728Smckusick #include "file.h" 2637728Smckusick #include "vnode.h" 2736359Smarc #include "ktrace.h" 2836359Smarc #include "malloc.h" 2936359Smarc 3037593Smarc #include "syscalls.c" 3136359Smarc 3236359Smarc extern int nsysent; 3336359Smarc extern char *syscallnames[]; 3436359Smarc 3537593Smarc int ktrace_nocheck = 1; 3637593Smarc 3736359Smarc struct ktr_header * 3836359Smarc ktrgetheader(type) 3936359Smarc { 4036359Smarc register struct ktr_header *kth; 4136359Smarc 4236359Smarc MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 4336359Smarc M_TEMP, M_WAITOK); 4436359Smarc kth->ktr_type = type; 4537593Smarc microtime(&kth->ktr_time); 4636359Smarc kth->ktr_pid = u.u_procp->p_pid; 47*40805Smarc bcopy(u.u_procp->p_comm, kth->ktr_comm, MAXCOMLEN); 4836359Smarc return (kth); 4936359Smarc } 5036359Smarc 5137728Smckusick ktrsyscall(vp, code, narg) 5237728Smckusick struct vnode *vp; 5336359Smarc { 5436359Smarc struct ktr_header *kth = ktrgetheader(KTR_SYSCALL); 5536359Smarc struct ktr_syscall *ktp; 5636359Smarc register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); 5736359Smarc int *argp, i; 5836359Smarc 5937593Smarc if (kth == NULL) 6036359Smarc return; 6136359Smarc MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); 6236359Smarc ktp->ktr_code = code; 6336359Smarc ktp->ktr_narg = narg; 6436359Smarc argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); 6536359Smarc for (i = 0; i < narg; i++) 6636359Smarc *argp++ = u.u_arg[i]; 6736359Smarc kth->ktr_buf = (caddr_t)ktp; 6836359Smarc kth->ktr_len = len; 6937728Smckusick ktrwrite(vp, kth); 7036359Smarc FREE(ktp, M_TEMP); 7136359Smarc FREE(kth, M_TEMP); 7236359Smarc } 7336359Smarc 7437728Smckusick ktrsysret(vp, code) 7537728Smckusick struct vnode *vp; 7636359Smarc { 7736359Smarc struct ktr_header *kth = ktrgetheader(KTR_SYSRET); 78*40805Smarc struct ktr_sysret ktp; 7936359Smarc 8037593Smarc if (kth == NULL) 8136359Smarc return; 82*40805Smarc ktp.ktr_code = code; 83*40805Smarc ktp.ktr_eosys = u.u_eosys; 84*40805Smarc ktp.ktr_error = u.u_error; 85*40805Smarc ktp.ktr_retval = u.u_r.r_val1; /* what about val2 ? */ 8636359Smarc 87*40805Smarc kth->ktr_buf = (caddr_t)&ktp; 8836359Smarc kth->ktr_len = sizeof(struct ktr_sysret); 8936359Smarc 9037728Smckusick ktrwrite(vp, kth); 9136359Smarc FREE(kth, M_TEMP); 9236359Smarc } 9336359Smarc 9437728Smckusick ktrnamei(vp, path) 9537728Smckusick struct vnode *vp; 9636359Smarc char *path; 9736359Smarc { 9836359Smarc struct ktr_header *kth = ktrgetheader(KTR_NAMEI); 9936359Smarc 10037593Smarc if (kth == NULL) 10136359Smarc return; 10236359Smarc kth->ktr_len = strlen(path); 10336359Smarc kth->ktr_buf = path; 10436359Smarc 10537728Smckusick ktrwrite(vp, kth); 10636359Smarc FREE(kth, M_TEMP); 10736359Smarc } 10836359Smarc 10937728Smckusick ktrgenio(vp, fd, rw, iov, len) 11037728Smckusick struct vnode *vp; 11137593Smarc enum uio_rw rw; 11237593Smarc register struct iovec *iov; 11337593Smarc { 11437593Smarc struct ktr_header *kth = ktrgetheader(KTR_GENIO); 11537593Smarc register struct ktr_genio *ktp; 11637593Smarc register caddr_t cp; 11737593Smarc register int resid = len, cnt; 11837593Smarc 11937593Smarc if (kth == NULL || u.u_error) 12037593Smarc return; 12137593Smarc MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, 12237593Smarc M_TEMP, M_WAITOK); 12337593Smarc ktp->ktr_fd = fd; 12437593Smarc ktp->ktr_rw = rw; 12537593Smarc cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); 12637593Smarc while (resid > 0) { 12737593Smarc if ((cnt = iov->iov_len) > resid) 12837593Smarc cnt = resid; 12937593Smarc if (copyin(iov->iov_base, cp, cnt)) 13037593Smarc goto done; 13137593Smarc cp += cnt; 13237593Smarc resid -= cnt; 13337593Smarc iov++; 13437593Smarc } 13537593Smarc kth->ktr_buf = (caddr_t)ktp; 13637593Smarc kth->ktr_len = sizeof (struct ktr_genio) + len; 13737593Smarc 13837728Smckusick ktrwrite(vp, kth); 13937593Smarc done: 14037593Smarc FREE(kth, M_TEMP); 14137593Smarc FREE(ktp, M_TEMP); 14237593Smarc } 14337593Smarc 144*40805Smarc ktrpsig(vp, sig, action, mask, code) 145*40805Smarc struct vnode *vp; 146*40805Smarc sig_t action; 147*40805Smarc { 148*40805Smarc struct ktr_header *kth = ktrgetheader(KTR_PSIG); 149*40805Smarc struct ktr_psig kp; 150*40805Smarc 151*40805Smarc if (kth == NULL) 152*40805Smarc return; 153*40805Smarc kp.signo = (char)sig; 154*40805Smarc kp.action = action; 155*40805Smarc kp.mask = mask; 156*40805Smarc kp.code = code; 157*40805Smarc kth->ktr_buf = (caddr_t)&kp; 158*40805Smarc kth->ktr_len = sizeof (struct ktr_psig); 159*40805Smarc 160*40805Smarc ktrwrite(vp, kth); 161*40805Smarc FREE(kth, M_TEMP); 162*40805Smarc } 163*40805Smarc 164*40805Smarc /* Interface and common routines */ 165*40805Smarc 16636359Smarc /* 16736359Smarc * ktrace system call 16836359Smarc */ 16936359Smarc ktrace() 17036359Smarc { 17136359Smarc register struct a { 17236359Smarc char *fname; 17336359Smarc int ops; 17436359Smarc int facs; 17537593Smarc int pid; 17636359Smarc } *uap = (struct a *)u.u_ap; 17737728Smckusick register struct vnode *vp = NULL; 17836359Smarc register struct nameidata *ndp = &u.u_nd; 17936359Smarc register struct proc *p; 180*40805Smarc register ops = KTROP(uap->ops); 18136359Smarc struct pgrp *pg; 18236359Smarc register int facs = uap->facs; 18337593Smarc register int ret = 0; 18436359Smarc 18536359Smarc /* 18636359Smarc * Until security implications are thought through, 18737593Smarc * limit tracing to root (unless ktrace_nocheck is set). 18836359Smarc */ 18937555Smckusick if (!ktrace_nocheck && (u.u_error = suser(u.u_cred, &u.u_acflag))) 19036359Smarc return; 19136359Smarc if (ops != KTROP_CLEAR) { 19236359Smarc /* 19336359Smarc * an operation which requires a file argument. 19436359Smarc */ 19536359Smarc ndp->ni_segflg = UIO_USERSPACE; 19636359Smarc ndp->ni_dirp = uap->fname; 19737728Smckusick if (u.u_error = vn_open(ndp, FREAD|FWRITE, 0)) 19836359Smarc return; 19937728Smckusick vp = ndp->ni_vp; 20037728Smckusick if (vp->v_type != VREG) { 20136359Smarc u.u_error = EACCES; 20237728Smckusick vrele(vp); 20336359Smarc return; 20436359Smarc } 20536359Smarc } 20636359Smarc /* 20736359Smarc * Clear all uses of the tracefile 20836359Smarc */ 20936359Smarc if (ops == KTROP_CLEARFILE) { 21036359Smarc for (p = allproc; p != NULL; p = p->p_nxt) { 21137728Smckusick if (p->p_tracep == vp) { 21236359Smarc p->p_tracep = NULL; 21336359Smarc p->p_traceflag = 0; 21437728Smckusick vrele(vp); 21536359Smarc } 21636359Smarc } 21736359Smarc goto done; 21836359Smarc } 21936359Smarc /* 22036359Smarc * need something to (un)trace 22136359Smarc */ 22236359Smarc if (!facs) { 22336359Smarc u.u_error = EINVAL; 22436359Smarc goto done; 22536359Smarc } 226*40805Smarc /* 227*40805Smarc * doit 228*40805Smarc */ 22936359Smarc if (uap->pid < 0) { 23036359Smarc pg = pgfind(-uap->pid); 23136359Smarc if (pg == NULL) { 23236359Smarc u.u_error = ESRCH; 23336359Smarc goto done; 23436359Smarc } 23536359Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) 236*40805Smarc if (uap->ops&KTRFLAG_DESCEND) 23737728Smckusick ret |= ktrsetchildren(p, ops, facs, vp); 23836359Smarc else 23937728Smckusick ret |= ktrops(p, ops, facs, vp); 24036359Smarc 24136359Smarc } else { 24236359Smarc p = pfind(uap->pid); 24336359Smarc if (p == NULL) { 24436359Smarc u.u_error = ESRCH; 24536359Smarc goto done; 24636359Smarc } 247*40805Smarc if (ops&KTRFLAG_DESCEND) 24837728Smckusick ret |= ktrsetchildren(p, ops, facs, vp); 24936359Smarc else 25037728Smckusick ret |= ktrops(p, ops, facs, vp); 25136359Smarc } 25237593Smarc if (!ret) 25337593Smarc u.u_error = EPERM; 25436359Smarc done: 25537728Smckusick if (vp != NULL) 25637728Smckusick vrele(vp); 25736359Smarc } 25836359Smarc 25937728Smckusick ktrops(p, ops, facs, vp) 26036359Smarc struct proc *p; 26137728Smckusick struct vnode *vp; 26236359Smarc { 26337593Smarc 26437593Smarc if (u.u_uid && u.u_uid != p->p_uid) 26537593Smarc return 0; 26636359Smarc if (ops == KTROP_SET) { 267*40805Smarc if (p->p_tracep != vp) { 26836359Smarc /* 26936359Smarc * if trace file already in use, relinquish 27036359Smarc */ 27136359Smarc if (p->p_tracep != NULL) 27237728Smckusick vrele(p->p_tracep); 27338423Smarc VREF(vp); 27437728Smckusick p->p_tracep = vp; 27536359Smarc } 27636359Smarc p->p_traceflag |= facs; 27736359Smarc } else { 27836359Smarc /* KTROP_CLEAR */ 279*40805Smarc if (((p->p_traceflag &= ~facs) & ~KTRFAC_INHERIT) == 0) { 280*40805Smarc /* no more tracing */ 281*40805Smarc p->p_traceflag = 0; 28236359Smarc if (p->p_tracep != NULL) { 28337728Smckusick vrele(p->p_tracep); 28436359Smarc p->p_tracep = NULL; 28536359Smarc } 28636359Smarc } 28736359Smarc } 28837593Smarc 28937593Smarc return 1; 29036359Smarc } 29137593Smarc 29237728Smckusick ktrsetchildren(top, ops, facs, vp) 29336359Smarc struct proc *top; 29437728Smckusick struct vnode *vp; 29536359Smarc { 29636359Smarc register struct proc *p; 29736359Smarc register int ndx; 29837593Smarc register int ret = 0; 29936359Smarc 30036359Smarc p = top; 30136359Smarc for (;;) { 302*40805Smarc ret |= ktrops(p, ops, facs, vp); 30336359Smarc /* 30436359Smarc * If this process has children, descend to them next, 30536359Smarc * otherwise do any siblings, and if done with this level, 30636359Smarc * follow back up the tree (but not past top). 30736359Smarc */ 30836359Smarc if (p->p_cptr) 30936359Smarc p = p->p_cptr; 31036359Smarc else if (p == top) 31137593Smarc return ret; 31236359Smarc else if (p->p_osptr) 31336359Smarc p = p->p_osptr; 31436359Smarc else for (;;) { 31536359Smarc p = p->p_pptr; 31636359Smarc if (p == top) 31737593Smarc return ret; 31836359Smarc if (p->p_osptr) { 31936359Smarc p = p->p_osptr; 32036359Smarc break; 32136359Smarc } 32236359Smarc } 32336359Smarc } 32437593Smarc /*NOTREACHED*/ 32536359Smarc } 32636359Smarc 32737728Smckusick ktrwrite(vp, kth) 32837728Smckusick struct vnode *vp; 32937728Smckusick register struct ktr_header *kth; 33036359Smarc { 33137728Smckusick struct uio auio; 33237728Smckusick struct iovec aiov[2]; 33339581Smckusick int error; 33437728Smckusick 33537728Smckusick if (vp == NULL) 33637593Smarc return; 33737728Smckusick auio.uio_iov = &aiov[0]; 33837728Smckusick auio.uio_offset = 0; 33937728Smckusick auio.uio_segflg = UIO_SYSSPACE; 34037728Smckusick auio.uio_rw = UIO_WRITE; 34137728Smckusick aiov[0].iov_base = (caddr_t)kth; 34237728Smckusick aiov[0].iov_len = sizeof(struct ktr_header); 34337728Smckusick auio.uio_resid = sizeof(struct ktr_header); 34437728Smckusick auio.uio_iovcnt = 1; 34536359Smarc if (kth->ktr_len > 0) { 34637728Smckusick auio.uio_iovcnt++; 34737728Smckusick aiov[1].iov_base = kth->ktr_buf; 34837728Smckusick aiov[1].iov_len = kth->ktr_len; 34937728Smckusick auio.uio_resid += kth->ktr_len; 35036359Smarc } 35139581Smckusick VOP_LOCK(vp); 35239581Smckusick error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, u.u_cred); 35339581Smckusick VOP_UNLOCK(vp); 35436359Smarc } 35536359Smarc #endif 356