136359Smarc /* 236359Smarc * Copyright (c) 1989 The Regents of the University of California. 336359Smarc * All rights reserved. 436359Smarc * 544436Sbostic * %sccs.include.redist.c% 636359Smarc * 7*46424Smarc * @(#)kern_ktrace.c 7.10 (Berkeley) 02/15/91 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" 19*46424Smarc #include "syslog.h" 2036359Smarc 2137593Smarc #include "syscalls.c" 2236359Smarc 2336359Smarc extern int nsysent; 2436359Smarc extern char *syscallnames[]; 2536359Smarc 2636359Smarc struct ktr_header * 2736359Smarc ktrgetheader(type) 2836359Smarc { 2936359Smarc register struct ktr_header *kth; 3036359Smarc 3136359Smarc MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 3236359Smarc M_TEMP, M_WAITOK); 3336359Smarc kth->ktr_type = type; 3437593Smarc microtime(&kth->ktr_time); 3536359Smarc kth->ktr_pid = u.u_procp->p_pid; 3640805Smarc bcopy(u.u_procp->p_comm, kth->ktr_comm, MAXCOMLEN); 3736359Smarc return (kth); 3836359Smarc } 3936359Smarc 4043444Smckusick ktrsyscall(vp, code, narg, args) 4137728Smckusick struct vnode *vp; 4243444Smckusick int code, narg, args[]; 4336359Smarc { 4436359Smarc struct ktr_header *kth = ktrgetheader(KTR_SYSCALL); 4536359Smarc struct ktr_syscall *ktp; 4636359Smarc register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); 4736359Smarc int *argp, i; 4836359Smarc 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); 6036359Smarc } 6136359Smarc 6243444Smckusick ktrsysret(vp, code, error, retval) 6337728Smckusick struct vnode *vp; 6443444Smckusick int code, error, retval; 6536359Smarc { 6636359Smarc struct ktr_header *kth = ktrgetheader(KTR_SYSRET); 6740805Smarc struct ktr_sysret ktp; 6836359Smarc 6940805Smarc ktp.ktr_code = code; 7043444Smckusick ktp.ktr_error = error; 7143444Smckusick ktp.ktr_retval = retval; /* what about val2 ? */ 7236359Smarc 7340805Smarc kth->ktr_buf = (caddr_t)&ktp; 7436359Smarc kth->ktr_len = sizeof(struct ktr_sysret); 7536359Smarc 7637728Smckusick ktrwrite(vp, kth); 7736359Smarc FREE(kth, M_TEMP); 7836359Smarc } 7936359Smarc 8037728Smckusick ktrnamei(vp, path) 8137728Smckusick struct vnode *vp; 8236359Smarc char *path; 8336359Smarc { 8436359Smarc struct ktr_header *kth = ktrgetheader(KTR_NAMEI); 8536359Smarc 8636359Smarc kth->ktr_len = strlen(path); 8736359Smarc kth->ktr_buf = path; 8836359Smarc 8937728Smckusick ktrwrite(vp, kth); 9036359Smarc FREE(kth, M_TEMP); 9136359Smarc } 9236359Smarc 9343444Smckusick ktrgenio(vp, fd, rw, iov, len, error) 9437728Smckusick struct vnode *vp; 9543444Smckusick int fd; 9637593Smarc enum uio_rw rw; 9737593Smarc register struct iovec *iov; 9837593Smarc { 9937593Smarc struct ktr_header *kth = ktrgetheader(KTR_GENIO); 10037593Smarc register struct ktr_genio *ktp; 10137593Smarc register caddr_t cp; 10237593Smarc register int resid = len, cnt; 10337593Smarc 104*46424Smarc if (error) 10537593Smarc return; 10637593Smarc MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, 10737593Smarc M_TEMP, M_WAITOK); 10837593Smarc ktp->ktr_fd = fd; 10937593Smarc ktp->ktr_rw = rw; 11037593Smarc cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); 11137593Smarc while (resid > 0) { 11237593Smarc if ((cnt = iov->iov_len) > resid) 11337593Smarc cnt = resid; 11441573Smckusick if (copyin(iov->iov_base, cp, (unsigned)cnt)) 11537593Smarc goto done; 11637593Smarc cp += cnt; 11737593Smarc resid -= cnt; 11837593Smarc iov++; 11937593Smarc } 12037593Smarc kth->ktr_buf = (caddr_t)ktp; 12137593Smarc kth->ktr_len = sizeof (struct ktr_genio) + len; 12237593Smarc 12337728Smckusick ktrwrite(vp, kth); 12437593Smarc done: 12537593Smarc FREE(kth, M_TEMP); 12637593Smarc FREE(ktp, M_TEMP); 12737593Smarc } 12837593Smarc 12940805Smarc ktrpsig(vp, sig, action, mask, code) 13040805Smarc struct vnode *vp; 13140805Smarc sig_t action; 13240805Smarc { 13340805Smarc struct ktr_header *kth = ktrgetheader(KTR_PSIG); 13440805Smarc struct ktr_psig kp; 13540805Smarc 13640805Smarc kp.signo = (char)sig; 13740805Smarc kp.action = action; 13840805Smarc kp.mask = mask; 13940805Smarc kp.code = code; 14040805Smarc kth->ktr_buf = (caddr_t)&kp; 14140805Smarc kth->ktr_len = sizeof (struct ktr_psig); 14240805Smarc 14340805Smarc ktrwrite(vp, kth); 14440805Smarc FREE(kth, M_TEMP); 14540805Smarc } 14640805Smarc 14740805Smarc /* Interface and common routines */ 14840805Smarc 14936359Smarc /* 15036359Smarc * ktrace system call 15136359Smarc */ 15243444Smckusick /* ARGSUSED */ 15343444Smckusick ktrace(curp, uap, retval) 15443444Smckusick struct proc *curp; 15543444Smckusick register struct args { 15636359Smarc char *fname; 15736359Smarc int ops; 15836359Smarc int facs; 15937593Smarc int pid; 16043444Smckusick } *uap; 16143444Smckusick int *retval; 16243444Smckusick { 16337728Smckusick register struct vnode *vp = NULL; 16436359Smarc register struct nameidata *ndp = &u.u_nd; 16536359Smarc register struct proc *p; 16636359Smarc struct pgrp *pg; 167*46424Smarc int facs = uap->facs & ~KTRFAC_ROOT; 168*46424Smarc int ops = KTROP(uap->ops); 169*46424Smarc int descend = uap->ops & KTRFLAG_DESCEND; 170*46424Smarc int ret = 0; 17143444Smckusick int error = 0; 17236359Smarc 17336359Smarc if (ops != KTROP_CLEAR) { 17436359Smarc /* 17536359Smarc * an operation which requires a file argument. 17636359Smarc */ 17736359Smarc ndp->ni_segflg = UIO_USERSPACE; 17836359Smarc ndp->ni_dirp = uap->fname; 17943444Smckusick if (error = vn_open(ndp, FREAD|FWRITE, 0)) 18044404Skarels return (error); 18137728Smckusick vp = ndp->ni_vp; 18237728Smckusick if (vp->v_type != VREG) { 18337728Smckusick vrele(vp); 18444404Skarels return (EACCES); 18536359Smarc } 18636359Smarc } 18736359Smarc /* 18836359Smarc * Clear all uses of the tracefile 18936359Smarc */ 19036359Smarc if (ops == KTROP_CLEARFILE) { 19136359Smarc for (p = allproc; p != NULL; p = p->p_nxt) { 19237728Smckusick if (p->p_tracep == vp) { 193*46424Smarc if (ktrcanset(curp, p)) { 194*46424Smarc p->p_tracep = NULL; 195*46424Smarc p->p_traceflag = 0; 196*46424Smarc vrele(vp); 197*46424Smarc } else 198*46424Smarc error = EPERM; 19936359Smarc } 20036359Smarc } 20136359Smarc goto done; 20236359Smarc } 20336359Smarc /* 204*46424Smarc * need something to (un)trace (XXX - why is this here?) 20536359Smarc */ 20636359Smarc if (!facs) { 20743444Smckusick error = EINVAL; 20836359Smarc goto done; 20936359Smarc } 21040805Smarc /* 211*46424Smarc * do it 21240805Smarc */ 21336359Smarc if (uap->pid < 0) { 214*46424Smarc /* 215*46424Smarc * by process group 216*46424Smarc */ 21736359Smarc pg = pgfind(-uap->pid); 21836359Smarc if (pg == NULL) { 21943444Smckusick error = ESRCH; 22036359Smarc goto done; 22136359Smarc } 22236359Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) 223*46424Smarc if (descend) 224*46424Smarc ret |= ktrsetchildren(curp, p, ops, facs, vp); 22536359Smarc else 226*46424Smarc ret |= ktrops(curp, p, ops, facs, vp); 22736359Smarc 22836359Smarc } else { 229*46424Smarc /* 230*46424Smarc * by pid 231*46424Smarc */ 23236359Smarc p = pfind(uap->pid); 23336359Smarc if (p == NULL) { 23443444Smckusick error = ESRCH; 23536359Smarc goto done; 23636359Smarc } 237*46424Smarc if (descend) 238*46424Smarc ret |= ktrsetchildren(curp, p, ops, facs, vp); 23936359Smarc else 240*46424Smarc ret |= ktrops(curp, p, ops, facs, vp); 24136359Smarc } 24237593Smarc if (!ret) 24343444Smckusick error = EPERM; 24436359Smarc done: 24537728Smckusick if (vp != NULL) 24637728Smckusick vrele(vp); 24744404Skarels return (error); 24836359Smarc } 24936359Smarc 250*46424Smarc ktrops(curp, p, ops, facs, vp) 251*46424Smarc struct proc *curp, *p; 25237728Smckusick struct vnode *vp; 25336359Smarc { 25437593Smarc 255*46424Smarc if (!ktrcanset(curp, p)) 25644404Skarels return (0); 25736359Smarc if (ops == KTROP_SET) { 25840805Smarc if (p->p_tracep != vp) { 25936359Smarc /* 26036359Smarc * if trace file already in use, relinquish 26136359Smarc */ 26236359Smarc if (p->p_tracep != NULL) 26337728Smckusick vrele(p->p_tracep); 26438423Smarc VREF(vp); 26537728Smckusick p->p_tracep = vp; 26636359Smarc } 26736359Smarc p->p_traceflag |= facs; 268*46424Smarc if (curp->p_uid == 0) 269*46424Smarc p->p_traceflag |= KTRFAC_ROOT; 27036359Smarc } else { 27136359Smarc /* KTROP_CLEAR */ 272*46424Smarc if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 27340805Smarc /* no more tracing */ 27440805Smarc p->p_traceflag = 0; 27536359Smarc if (p->p_tracep != NULL) { 27637728Smckusick vrele(p->p_tracep); 27736359Smarc p->p_tracep = NULL; 27836359Smarc } 27936359Smarc } 28036359Smarc } 28137593Smarc 282*46424Smarc return (1); 28336359Smarc } 28437593Smarc 285*46424Smarc ktrsetchildren(curp, top, ops, facs, vp) 286*46424Smarc struct proc *curp, *top; 28737728Smckusick struct vnode *vp; 28836359Smarc { 28936359Smarc register struct proc *p; 29037593Smarc register int ret = 0; 29136359Smarc 29236359Smarc p = top; 29336359Smarc for (;;) { 294*46424Smarc ret |= ktrops(curp, p, ops, facs, vp); 29536359Smarc /* 29636359Smarc * If this process has children, descend to them next, 29736359Smarc * otherwise do any siblings, and if done with this level, 29836359Smarc * follow back up the tree (but not past top). 29936359Smarc */ 30036359Smarc if (p->p_cptr) 30136359Smarc p = p->p_cptr; 30236359Smarc else if (p == top) 303*46424Smarc return (ret); 30436359Smarc else if (p->p_osptr) 30536359Smarc p = p->p_osptr; 30636359Smarc else for (;;) { 30736359Smarc p = p->p_pptr; 30836359Smarc if (p == top) 309*46424Smarc return (ret); 31036359Smarc if (p->p_osptr) { 31136359Smarc p = p->p_osptr; 31236359Smarc break; 31336359Smarc } 31436359Smarc } 31536359Smarc } 31637593Smarc /*NOTREACHED*/ 31736359Smarc } 31836359Smarc 31937728Smckusick ktrwrite(vp, kth) 32037728Smckusick struct vnode *vp; 32137728Smckusick register struct ktr_header *kth; 32236359Smarc { 32337728Smckusick struct uio auio; 32437728Smckusick struct iovec aiov[2]; 32541573Smckusick struct proc *p; 32639581Smckusick int error; 32737728Smckusick 32837728Smckusick if (vp == NULL) 32937593Smarc return; 33037728Smckusick auio.uio_iov = &aiov[0]; 33137728Smckusick auio.uio_offset = 0; 33237728Smckusick auio.uio_segflg = UIO_SYSSPACE; 33337728Smckusick auio.uio_rw = UIO_WRITE; 33437728Smckusick aiov[0].iov_base = (caddr_t)kth; 33537728Smckusick aiov[0].iov_len = sizeof(struct ktr_header); 33637728Smckusick auio.uio_resid = sizeof(struct ktr_header); 33737728Smckusick auio.uio_iovcnt = 1; 33836359Smarc if (kth->ktr_len > 0) { 33937728Smckusick auio.uio_iovcnt++; 34037728Smckusick aiov[1].iov_base = kth->ktr_buf; 34137728Smckusick aiov[1].iov_len = kth->ktr_len; 34237728Smckusick auio.uio_resid += kth->ktr_len; 34336359Smarc } 34439581Smckusick VOP_LOCK(vp); 34539581Smckusick error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, u.u_cred); 34639581Smckusick VOP_UNLOCK(vp); 34741573Smckusick if (!error) 34841573Smckusick return; 34941573Smckusick /* 35041573Smckusick * If error encountered, give up tracing on this vnode. 35141573Smckusick */ 352*46424Smarc log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", error); 35341573Smckusick for (p = allproc; p != NULL; p = p->p_nxt) { 35441573Smckusick if (p->p_tracep == vp) { 35541573Smckusick p->p_tracep = NULL; 35641573Smckusick p->p_traceflag = 0; 35741573Smckusick vrele(vp); 35841573Smckusick } 35941573Smckusick } 36036359Smarc } 361*46424Smarc 362*46424Smarc /* 363*46424Smarc * Return true if caller has permission to set the ktracing state 364*46424Smarc * of target. Essentially, the target can't possess any 365*46424Smarc * more permissions than the caller. KTRFAC_ROOT signifies that 366*46424Smarc * root previously set the tracing status on the target process, and 367*46424Smarc * so, only root may further change it. 368*46424Smarc * 369*46424Smarc * TODO: check groups (have to wait till group list is moved 370*46424Smarc * out of u. use caller effective gid. 371*46424Smarc */ 372*46424Smarc ktrcanset(caller, target) 373*46424Smarc register struct proc *caller, *target; 374*46424Smarc { 375*46424Smarc if ((caller->p_uid == target->p_ruid && 376*46424Smarc target->p_ruid == target->p_svuid && 377*46424Smarc caller->p_rgid == target->p_rgid && /* XXX */ 378*46424Smarc target->p_rgid == target->p_svgid && 379*46424Smarc (target->p_traceflag & KTRFAC_ROOT) == 0) || 380*46424Smarc caller->p_uid == 0) 381*46424Smarc return (1); 382*46424Smarc 383*46424Smarc return (0); 384*46424Smarc } 385*46424Smarc 38636359Smarc #endif 387