136359Smarc /* 2*63174Sbostic * Copyright (c) 1989, 1993 3*63174Sbostic * The Regents of the University of California. All rights reserved. 436359Smarc * 544436Sbostic * %sccs.include.redist.c% 636359Smarc * 7*63174Sbostic * @(#)kern_ktrace.c 8.1 (Berkeley) 06/10/93 836359Smarc */ 936359Smarc 1036359Smarc #ifdef KTRACE 1136359Smarc 1256517Sbostic #include <sys/param.h> 1356517Sbostic #include <sys/proc.h> 1456517Sbostic #include <sys/file.h> 1556517Sbostic #include <sys/namei.h> 1656517Sbostic #include <sys/vnode.h> 1756517Sbostic #include <sys/ktrace.h> 1856517Sbostic #include <sys/malloc.h> 1956517Sbostic #include <sys/syslog.h> 2036359Smarc 2136359Smarc struct ktr_header * 2236359Smarc ktrgetheader(type) 2360514Storek int type; 2436359Smarc { 2536359Smarc register struct ktr_header *kth; 2648017Smckusick struct proc *p = curproc; /* XXX */ 2736359Smarc 2836359Smarc MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 2936359Smarc M_TEMP, M_WAITOK); 3036359Smarc kth->ktr_type = type; 3137593Smarc microtime(&kth->ktr_time); 3247548Skarels kth->ktr_pid = p->p_pid; 3347548Skarels bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN); 3436359Smarc return (kth); 3536359Smarc } 3636359Smarc 3743444Smckusick ktrsyscall(vp, code, narg, args) 3837728Smckusick struct vnode *vp; 3943444Smckusick int code, narg, args[]; 4036359Smarc { 4153012Smarc struct ktr_header *kth; 4236359Smarc struct ktr_syscall *ktp; 4336359Smarc register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); 4453012Smarc struct proc *p = curproc; /* XXX */ 4536359Smarc int *argp, i; 4636359Smarc 4753012Smarc p->p_traceflag |= KTRFAC_ACTIVE; 4853012Smarc kth = ktrgetheader(KTR_SYSCALL); 4936359Smarc MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); 5036359Smarc ktp->ktr_code = code; 5136359Smarc ktp->ktr_narg = narg; 5236359Smarc argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); 5336359Smarc for (i = 0; i < narg; i++) 5443444Smckusick *argp++ = args[i]; 5536359Smarc kth->ktr_buf = (caddr_t)ktp; 5636359Smarc kth->ktr_len = len; 5737728Smckusick ktrwrite(vp, kth); 5836359Smarc FREE(ktp, M_TEMP); 5936359Smarc FREE(kth, M_TEMP); 6053012Smarc p->p_traceflag &= ~KTRFAC_ACTIVE; 6136359Smarc } 6236359Smarc 6343444Smckusick ktrsysret(vp, code, error, retval) 6437728Smckusick struct vnode *vp; 6543444Smckusick int code, error, retval; 6636359Smarc { 6753012Smarc struct ktr_header *kth; 6840805Smarc struct ktr_sysret ktp; 6953012Smarc struct proc *p = curproc; /* XXX */ 7036359Smarc 7153012Smarc p->p_traceflag |= KTRFAC_ACTIVE; 7253012Smarc kth = ktrgetheader(KTR_SYSRET); 7340805Smarc ktp.ktr_code = code; 7443444Smckusick ktp.ktr_error = error; 7543444Smckusick ktp.ktr_retval = retval; /* what about val2 ? */ 7636359Smarc 7740805Smarc kth->ktr_buf = (caddr_t)&ktp; 7836359Smarc kth->ktr_len = sizeof(struct ktr_sysret); 7936359Smarc 8037728Smckusick ktrwrite(vp, kth); 8136359Smarc FREE(kth, M_TEMP); 8253012Smarc p->p_traceflag &= ~KTRFAC_ACTIVE; 8336359Smarc } 8436359Smarc 8537728Smckusick ktrnamei(vp, path) 8637728Smckusick struct vnode *vp; 8736359Smarc char *path; 8836359Smarc { 8953012Smarc struct ktr_header *kth; 9053012Smarc struct proc *p = curproc; /* XXX */ 9136359Smarc 9253012Smarc p->p_traceflag |= KTRFAC_ACTIVE; 9353012Smarc kth = ktrgetheader(KTR_NAMEI); 9436359Smarc kth->ktr_len = strlen(path); 9536359Smarc kth->ktr_buf = path; 9636359Smarc 9737728Smckusick ktrwrite(vp, kth); 9836359Smarc FREE(kth, M_TEMP); 9953012Smarc p->p_traceflag &= ~KTRFAC_ACTIVE; 10036359Smarc } 10136359Smarc 10243444Smckusick ktrgenio(vp, fd, rw, iov, len, error) 10337728Smckusick struct vnode *vp; 10443444Smckusick int fd; 10537593Smarc enum uio_rw rw; 10637593Smarc register struct iovec *iov; 10760514Storek int len, error; 10837593Smarc { 10953012Smarc struct ktr_header *kth; 11037593Smarc register struct ktr_genio *ktp; 11137593Smarc register caddr_t cp; 11237593Smarc register int resid = len, cnt; 11353012Smarc struct proc *p = curproc; /* XXX */ 11437593Smarc 11546424Smarc if (error) 11637593Smarc return; 11753012Smarc p->p_traceflag |= KTRFAC_ACTIVE; 11853012Smarc kth = ktrgetheader(KTR_GENIO); 11937593Smarc MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, 12037593Smarc M_TEMP, M_WAITOK); 12137593Smarc ktp->ktr_fd = fd; 12237593Smarc ktp->ktr_rw = rw; 12337593Smarc cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); 12437593Smarc while (resid > 0) { 12537593Smarc if ((cnt = iov->iov_len) > resid) 12637593Smarc cnt = resid; 12741573Smckusick if (copyin(iov->iov_base, cp, (unsigned)cnt)) 12837593Smarc goto done; 12937593Smarc cp += cnt; 13037593Smarc resid -= cnt; 13137593Smarc iov++; 13237593Smarc } 13337593Smarc kth->ktr_buf = (caddr_t)ktp; 13437593Smarc kth->ktr_len = sizeof (struct ktr_genio) + len; 13537593Smarc 13637728Smckusick ktrwrite(vp, kth); 13737593Smarc done: 13837593Smarc FREE(kth, M_TEMP); 13937593Smarc FREE(ktp, M_TEMP); 14053012Smarc p->p_traceflag &= ~KTRFAC_ACTIVE; 14137593Smarc } 14237593Smarc 14340805Smarc ktrpsig(vp, sig, action, mask, code) 14460514Storek struct vnode *vp; 14560514Storek int sig; 14660514Storek sig_t action; 14760514Storek int mask, code; 14840805Smarc { 14953012Smarc struct ktr_header *kth; 15040805Smarc struct ktr_psig kp; 15153012Smarc struct proc *p = curproc; /* XXX */ 15240805Smarc 15353012Smarc p->p_traceflag |= KTRFAC_ACTIVE; 15453012Smarc kth = ktrgetheader(KTR_PSIG); 15540805Smarc kp.signo = (char)sig; 15640805Smarc kp.action = action; 15740805Smarc kp.mask = mask; 15840805Smarc kp.code = code; 15940805Smarc kth->ktr_buf = (caddr_t)&kp; 16040805Smarc kth->ktr_len = sizeof (struct ktr_psig); 16140805Smarc 16240805Smarc ktrwrite(vp, kth); 16340805Smarc FREE(kth, M_TEMP); 16453012Smarc p->p_traceflag &= ~KTRFAC_ACTIVE; 16540805Smarc } 16640805Smarc 16753012Smarc ktrcsw(vp, out, user) 16860514Storek struct vnode *vp; 16960514Storek int out, user; 17053012Smarc { 17153012Smarc struct ktr_header *kth; 17253012Smarc struct ktr_csw kc; 17353012Smarc struct proc *p = curproc; /* XXX */ 17453012Smarc 17553012Smarc p->p_traceflag |= KTRFAC_ACTIVE; 17653012Smarc kth = ktrgetheader(KTR_CSW); 17753012Smarc kc.out = out; 17853012Smarc kc.user = user; 17953012Smarc kth->ktr_buf = (caddr_t)&kc; 18053012Smarc kth->ktr_len = sizeof (struct ktr_csw); 18153012Smarc 18253012Smarc ktrwrite(vp, kth); 18353012Smarc FREE(kth, M_TEMP); 18453012Smarc p->p_traceflag &= ~KTRFAC_ACTIVE; 18553012Smarc } 18653012Smarc 18740805Smarc /* Interface and common routines */ 18840805Smarc 18936359Smarc /* 19036359Smarc * ktrace system call 19136359Smarc */ 19254924Storek struct ktrace_args { 19354924Storek char *fname; 19454924Storek int ops; 19554924Storek int facs; 19654924Storek int pid; 19754924Storek }; 19843444Smckusick /* ARGSUSED */ 19943444Smckusick ktrace(curp, uap, retval) 20043444Smckusick struct proc *curp; 20154924Storek register struct ktrace_args *uap; 20243444Smckusick int *retval; 20343444Smckusick { 20437728Smckusick register struct vnode *vp = NULL; 20536359Smarc register struct proc *p; 20636359Smarc struct pgrp *pg; 20746424Smarc int facs = uap->facs & ~KTRFAC_ROOT; 20846424Smarc int ops = KTROP(uap->ops); 20946424Smarc int descend = uap->ops & KTRFLAG_DESCEND; 21046424Smarc int ret = 0; 21143444Smckusick int error = 0; 21247548Skarels struct nameidata nd; 21336359Smarc 21453012Smarc curp->p_traceflag |= KTRFAC_ACTIVE; 21536359Smarc if (ops != KTROP_CLEAR) { 21636359Smarc /* 21736359Smarc * an operation which requires a file argument. 21836359Smarc */ 21953012Smarc NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, curp); 22053012Smarc if (error = vn_open(&nd, FREAD|FWRITE, 0)) { 22153012Smarc curp->p_traceflag &= ~KTRFAC_ACTIVE; 22244404Skarels return (error); 22353012Smarc } 22447548Skarels vp = nd.ni_vp; 22549914Smckusick VOP_UNLOCK(vp); 22637728Smckusick if (vp->v_type != VREG) { 22750106Smckusick (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); 22853012Smarc curp->p_traceflag &= ~KTRFAC_ACTIVE; 22944404Skarels return (EACCES); 23036359Smarc } 23136359Smarc } 23236359Smarc /* 23336359Smarc * Clear all uses of the tracefile 23436359Smarc */ 23536359Smarc if (ops == KTROP_CLEARFILE) { 23654757Storek for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 23737728Smckusick if (p->p_tracep == vp) { 23846424Smarc if (ktrcanset(curp, p)) { 23946424Smarc p->p_tracep = NULL; 24046424Smarc p->p_traceflag = 0; 24150106Smckusick (void) vn_close(vp, FREAD|FWRITE, 24250106Smckusick p->p_ucred, p); 24346424Smarc } else 24446424Smarc error = EPERM; 24536359Smarc } 24636359Smarc } 24736359Smarc goto done; 24836359Smarc } 24936359Smarc /* 25046424Smarc * need something to (un)trace (XXX - why is this here?) 25136359Smarc */ 25236359Smarc if (!facs) { 25343444Smckusick error = EINVAL; 25436359Smarc goto done; 25536359Smarc } 25640805Smarc /* 25746424Smarc * do it 25840805Smarc */ 25936359Smarc if (uap->pid < 0) { 26046424Smarc /* 26146424Smarc * by process group 26246424Smarc */ 26336359Smarc pg = pgfind(-uap->pid); 26436359Smarc if (pg == NULL) { 26543444Smckusick error = ESRCH; 26636359Smarc goto done; 26736359Smarc } 26836359Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) 26946424Smarc if (descend) 27046424Smarc ret |= ktrsetchildren(curp, p, ops, facs, vp); 27136359Smarc else 27246424Smarc ret |= ktrops(curp, p, ops, facs, vp); 27336359Smarc 27436359Smarc } else { 27546424Smarc /* 27646424Smarc * by pid 27746424Smarc */ 27836359Smarc p = pfind(uap->pid); 27936359Smarc if (p == NULL) { 28043444Smckusick error = ESRCH; 28136359Smarc goto done; 28236359Smarc } 28346424Smarc if (descend) 28446424Smarc ret |= ktrsetchildren(curp, p, ops, facs, vp); 28536359Smarc else 28646424Smarc ret |= ktrops(curp, p, ops, facs, vp); 28736359Smarc } 28837593Smarc if (!ret) 28943444Smckusick error = EPERM; 29036359Smarc done: 29137728Smckusick if (vp != NULL) 29250106Smckusick (void) vn_close(vp, FWRITE, curp->p_ucred, curp); 29353012Smarc curp->p_traceflag &= ~KTRFAC_ACTIVE; 29444404Skarels return (error); 29536359Smarc } 29636359Smarc 29760514Storek int 29846424Smarc ktrops(curp, p, ops, facs, vp) 29960514Storek struct proc *p, *curp; 30060514Storek int ops, facs; 30137728Smckusick struct vnode *vp; 30236359Smarc { 30337593Smarc 30446424Smarc if (!ktrcanset(curp, p)) 30544404Skarels return (0); 30636359Smarc if (ops == KTROP_SET) { 30740805Smarc if (p->p_tracep != vp) { 30836359Smarc /* 30936359Smarc * if trace file already in use, relinquish 31036359Smarc */ 31136359Smarc if (p->p_tracep != NULL) 31237728Smckusick vrele(p->p_tracep); 31338423Smarc VREF(vp); 31437728Smckusick p->p_tracep = vp; 31536359Smarc } 31636359Smarc p->p_traceflag |= facs; 31747548Skarels if (curp->p_ucred->cr_uid == 0) 31846424Smarc p->p_traceflag |= KTRFAC_ROOT; 31936359Smarc } else { 32036359Smarc /* KTROP_CLEAR */ 32146424Smarc if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 32240805Smarc /* no more tracing */ 32340805Smarc p->p_traceflag = 0; 32436359Smarc if (p->p_tracep != NULL) { 32537728Smckusick vrele(p->p_tracep); 32636359Smarc p->p_tracep = NULL; 32736359Smarc } 32836359Smarc } 32936359Smarc } 33037593Smarc 33146424Smarc return (1); 33236359Smarc } 33337593Smarc 33446424Smarc ktrsetchildren(curp, top, ops, facs, vp) 33546424Smarc struct proc *curp, *top; 33660514Storek int ops, facs; 33737728Smckusick struct vnode *vp; 33836359Smarc { 33936359Smarc register struct proc *p; 34037593Smarc register int ret = 0; 34136359Smarc 34236359Smarc p = top; 34336359Smarc for (;;) { 34446424Smarc ret |= ktrops(curp, p, ops, facs, vp); 34536359Smarc /* 34636359Smarc * If this process has children, descend to them next, 34736359Smarc * otherwise do any siblings, and if done with this level, 34836359Smarc * follow back up the tree (but not past top). 34936359Smarc */ 35036359Smarc if (p->p_cptr) 35136359Smarc p = p->p_cptr; 35236359Smarc else if (p == top) 35346424Smarc return (ret); 35436359Smarc else if (p->p_osptr) 35536359Smarc p = p->p_osptr; 35636359Smarc else for (;;) { 35736359Smarc p = p->p_pptr; 35836359Smarc if (p == top) 35946424Smarc return (ret); 36036359Smarc if (p->p_osptr) { 36136359Smarc p = p->p_osptr; 36236359Smarc break; 36336359Smarc } 36436359Smarc } 36536359Smarc } 36637593Smarc /*NOTREACHED*/ 36736359Smarc } 36836359Smarc 36937728Smckusick ktrwrite(vp, kth) 37037728Smckusick struct vnode *vp; 37137728Smckusick register struct ktr_header *kth; 37236359Smarc { 37337728Smckusick struct uio auio; 37437728Smckusick struct iovec aiov[2]; 37548017Smckusick register struct proc *p = curproc; /* XXX */ 37639581Smckusick int error; 37737728Smckusick 37837728Smckusick if (vp == NULL) 37937593Smarc return; 38037728Smckusick auio.uio_iov = &aiov[0]; 38137728Smckusick auio.uio_offset = 0; 38237728Smckusick auio.uio_segflg = UIO_SYSSPACE; 38337728Smckusick auio.uio_rw = UIO_WRITE; 38437728Smckusick aiov[0].iov_base = (caddr_t)kth; 38537728Smckusick aiov[0].iov_len = sizeof(struct ktr_header); 38637728Smckusick auio.uio_resid = sizeof(struct ktr_header); 38737728Smckusick auio.uio_iovcnt = 1; 38848017Smckusick auio.uio_procp = (struct proc *)0; 38936359Smarc if (kth->ktr_len > 0) { 39037728Smckusick auio.uio_iovcnt++; 39137728Smckusick aiov[1].iov_base = kth->ktr_buf; 39237728Smckusick aiov[1].iov_len = kth->ktr_len; 39337728Smckusick auio.uio_resid += kth->ktr_len; 39436359Smarc } 39539581Smckusick VOP_LOCK(vp); 39648017Smckusick error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred); 39739581Smckusick VOP_UNLOCK(vp); 39841573Smckusick if (!error) 39941573Smckusick return; 40041573Smckusick /* 40141573Smckusick * If error encountered, give up tracing on this vnode. 40241573Smckusick */ 40347548Skarels log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", 40447548Skarels error); 40554757Storek for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 40641573Smckusick if (p->p_tracep == vp) { 40741573Smckusick p->p_tracep = NULL; 40841573Smckusick p->p_traceflag = 0; 40941573Smckusick vrele(vp); 41041573Smckusick } 41141573Smckusick } 41236359Smarc } 41346424Smarc 41446424Smarc /* 41546424Smarc * Return true if caller has permission to set the ktracing state 41646424Smarc * of target. Essentially, the target can't possess any 41746424Smarc * more permissions than the caller. KTRFAC_ROOT signifies that 41846424Smarc * root previously set the tracing status on the target process, and 41946424Smarc * so, only root may further change it. 42046424Smarc * 42147548Skarels * TODO: check groups. use caller effective gid. 42246424Smarc */ 42347548Skarels ktrcanset(callp, targetp) 42447548Skarels struct proc *callp, *targetp; 42546424Smarc { 42647548Skarels register struct pcred *caller = callp->p_cred; 42747548Skarels register struct pcred *target = targetp->p_cred; 42847548Skarels 42947548Skarels if ((caller->pc_ucred->cr_uid == target->p_ruid && 43046424Smarc target->p_ruid == target->p_svuid && 43146424Smarc caller->p_rgid == target->p_rgid && /* XXX */ 43246424Smarc target->p_rgid == target->p_svgid && 43347548Skarels (targetp->p_traceflag & KTRFAC_ROOT) == 0) || 43447548Skarels caller->pc_ucred->cr_uid == 0) 43546424Smarc return (1); 43646424Smarc 43746424Smarc return (0); 43846424Smarc } 43946424Smarc 44036359Smarc #endif 441