136359Smarc /* 236359Smarc * Copyright (c) 1989 The Regents of the University of California. 336359Smarc * All rights reserved. 436359Smarc * 544436Sbostic * %sccs.include.redist.c% 636359Smarc * 7*50106Smckusick * @(#)kern_ktrace.c 7.15 (Berkeley) 06/21/91 836359Smarc */ 936359Smarc 1036359Smarc #ifdef KTRACE 1136359Smarc 1236359Smarc #include "param.h" 1336359Smarc #include "proc.h" 1437728Smckusick #include "file.h" 1548017Smckusick #include "namei.h" 1637728Smckusick #include "vnode.h" 1736359Smarc #include "ktrace.h" 1836359Smarc #include "malloc.h" 1946424Smarc #include "syslog.h" 2036359Smarc 2136359Smarc struct ktr_header * 2236359Smarc ktrgetheader(type) 2336359Smarc { 2436359Smarc register struct ktr_header *kth; 2548017Smckusick struct proc *p = curproc; /* XXX */ 2636359Smarc 2736359Smarc MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 2836359Smarc M_TEMP, M_WAITOK); 2936359Smarc kth->ktr_type = type; 3037593Smarc microtime(&kth->ktr_time); 3147548Skarels kth->ktr_pid = p->p_pid; 3247548Skarels bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN); 3336359Smarc return (kth); 3436359Smarc } 3536359Smarc 3643444Smckusick ktrsyscall(vp, code, narg, args) 3737728Smckusick struct vnode *vp; 3843444Smckusick int code, narg, args[]; 3936359Smarc { 4036359Smarc struct ktr_header *kth = ktrgetheader(KTR_SYSCALL); 4136359Smarc struct ktr_syscall *ktp; 4236359Smarc register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); 4336359Smarc int *argp, i; 4436359Smarc 4536359Smarc MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); 4636359Smarc ktp->ktr_code = code; 4736359Smarc ktp->ktr_narg = narg; 4836359Smarc argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); 4936359Smarc for (i = 0; i < narg; i++) 5043444Smckusick *argp++ = args[i]; 5136359Smarc kth->ktr_buf = (caddr_t)ktp; 5236359Smarc kth->ktr_len = len; 5337728Smckusick ktrwrite(vp, kth); 5436359Smarc FREE(ktp, M_TEMP); 5536359Smarc FREE(kth, M_TEMP); 5636359Smarc } 5736359Smarc 5843444Smckusick ktrsysret(vp, code, error, retval) 5937728Smckusick struct vnode *vp; 6043444Smckusick int code, error, retval; 6136359Smarc { 6236359Smarc struct ktr_header *kth = ktrgetheader(KTR_SYSRET); 6340805Smarc struct ktr_sysret ktp; 6436359Smarc 6540805Smarc ktp.ktr_code = code; 6643444Smckusick ktp.ktr_error = error; 6743444Smckusick ktp.ktr_retval = retval; /* what about val2 ? */ 6836359Smarc 6940805Smarc kth->ktr_buf = (caddr_t)&ktp; 7036359Smarc kth->ktr_len = sizeof(struct ktr_sysret); 7136359Smarc 7237728Smckusick ktrwrite(vp, kth); 7336359Smarc FREE(kth, M_TEMP); 7436359Smarc } 7536359Smarc 7637728Smckusick ktrnamei(vp, path) 7737728Smckusick struct vnode *vp; 7836359Smarc char *path; 7936359Smarc { 8036359Smarc struct ktr_header *kth = ktrgetheader(KTR_NAMEI); 8136359Smarc 8236359Smarc kth->ktr_len = strlen(path); 8336359Smarc kth->ktr_buf = path; 8436359Smarc 8537728Smckusick ktrwrite(vp, kth); 8636359Smarc FREE(kth, M_TEMP); 8736359Smarc } 8836359Smarc 8943444Smckusick ktrgenio(vp, fd, rw, iov, len, error) 9037728Smckusick struct vnode *vp; 9143444Smckusick int fd; 9237593Smarc enum uio_rw rw; 9337593Smarc register struct iovec *iov; 9437593Smarc { 9537593Smarc struct ktr_header *kth = ktrgetheader(KTR_GENIO); 9637593Smarc register struct ktr_genio *ktp; 9737593Smarc register caddr_t cp; 9837593Smarc register int resid = len, cnt; 9937593Smarc 10046424Smarc if (error) 10137593Smarc return; 10237593Smarc MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, 10337593Smarc M_TEMP, M_WAITOK); 10437593Smarc ktp->ktr_fd = fd; 10537593Smarc ktp->ktr_rw = rw; 10637593Smarc cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); 10737593Smarc while (resid > 0) { 10837593Smarc if ((cnt = iov->iov_len) > resid) 10937593Smarc cnt = resid; 11041573Smckusick if (copyin(iov->iov_base, cp, (unsigned)cnt)) 11137593Smarc goto done; 11237593Smarc cp += cnt; 11337593Smarc resid -= cnt; 11437593Smarc iov++; 11537593Smarc } 11637593Smarc kth->ktr_buf = (caddr_t)ktp; 11737593Smarc kth->ktr_len = sizeof (struct ktr_genio) + len; 11837593Smarc 11937728Smckusick ktrwrite(vp, kth); 12037593Smarc done: 12137593Smarc FREE(kth, M_TEMP); 12237593Smarc FREE(ktp, M_TEMP); 12337593Smarc } 12437593Smarc 12540805Smarc ktrpsig(vp, sig, action, mask, code) 12640805Smarc struct vnode *vp; 12740805Smarc sig_t action; 12840805Smarc { 12940805Smarc struct ktr_header *kth = ktrgetheader(KTR_PSIG); 13040805Smarc struct ktr_psig kp; 13140805Smarc 13240805Smarc kp.signo = (char)sig; 13340805Smarc kp.action = action; 13440805Smarc kp.mask = mask; 13540805Smarc kp.code = code; 13640805Smarc kth->ktr_buf = (caddr_t)&kp; 13740805Smarc kth->ktr_len = sizeof (struct ktr_psig); 13840805Smarc 13940805Smarc ktrwrite(vp, kth); 14040805Smarc FREE(kth, M_TEMP); 14140805Smarc } 14240805Smarc 14340805Smarc /* Interface and common routines */ 14440805Smarc 14536359Smarc /* 14636359Smarc * ktrace system call 14736359Smarc */ 14843444Smckusick /* ARGSUSED */ 14943444Smckusick ktrace(curp, uap, retval) 15043444Smckusick struct proc *curp; 15143444Smckusick register struct args { 15236359Smarc char *fname; 15336359Smarc int ops; 15436359Smarc int facs; 15537593Smarc int pid; 15643444Smckusick } *uap; 15743444Smckusick int *retval; 15843444Smckusick { 15937728Smckusick register struct vnode *vp = NULL; 16036359Smarc register struct proc *p; 16136359Smarc struct pgrp *pg; 16246424Smarc int facs = uap->facs & ~KTRFAC_ROOT; 16346424Smarc int ops = KTROP(uap->ops); 16446424Smarc int descend = uap->ops & KTRFLAG_DESCEND; 16546424Smarc int ret = 0; 16643444Smckusick int error = 0; 16747548Skarels struct nameidata nd; 16836359Smarc 16936359Smarc if (ops != KTROP_CLEAR) { 17036359Smarc /* 17136359Smarc * an operation which requires a file argument. 17236359Smarc */ 17347548Skarels nd.ni_segflg = UIO_USERSPACE; 17447548Skarels nd.ni_dirp = uap->fname; 17547548Skarels if (error = vn_open(&nd, curp, FREAD|FWRITE, 0)) 17644404Skarels return (error); 17747548Skarels vp = nd.ni_vp; 17849914Smckusick VOP_UNLOCK(vp); 17937728Smckusick if (vp->v_type != VREG) { 180*50106Smckusick (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); 18144404Skarels return (EACCES); 18236359Smarc } 18336359Smarc } 18436359Smarc /* 18536359Smarc * Clear all uses of the tracefile 18636359Smarc */ 18736359Smarc if (ops == KTROP_CLEARFILE) { 18836359Smarc for (p = allproc; p != NULL; p = p->p_nxt) { 18937728Smckusick if (p->p_tracep == vp) { 19046424Smarc if (ktrcanset(curp, p)) { 19146424Smarc p->p_tracep = NULL; 19246424Smarc p->p_traceflag = 0; 193*50106Smckusick (void) vn_close(vp, FREAD|FWRITE, 194*50106Smckusick p->p_ucred, p); 19546424Smarc } else 19646424Smarc error = EPERM; 19736359Smarc } 19836359Smarc } 19936359Smarc goto done; 20036359Smarc } 20136359Smarc /* 20246424Smarc * need something to (un)trace (XXX - why is this here?) 20336359Smarc */ 20436359Smarc if (!facs) { 20543444Smckusick error = EINVAL; 20636359Smarc goto done; 20736359Smarc } 20840805Smarc /* 20946424Smarc * do it 21040805Smarc */ 21136359Smarc if (uap->pid < 0) { 21246424Smarc /* 21346424Smarc * by process group 21446424Smarc */ 21536359Smarc pg = pgfind(-uap->pid); 21636359Smarc if (pg == NULL) { 21743444Smckusick error = ESRCH; 21836359Smarc goto done; 21936359Smarc } 22036359Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) 22146424Smarc if (descend) 22246424Smarc ret |= ktrsetchildren(curp, p, ops, facs, vp); 22336359Smarc else 22446424Smarc ret |= ktrops(curp, p, ops, facs, vp); 22536359Smarc 22636359Smarc } else { 22746424Smarc /* 22846424Smarc * by pid 22946424Smarc */ 23036359Smarc p = pfind(uap->pid); 23136359Smarc if (p == NULL) { 23243444Smckusick error = ESRCH; 23336359Smarc goto done; 23436359Smarc } 23546424Smarc if (descend) 23646424Smarc ret |= ktrsetchildren(curp, p, ops, facs, vp); 23736359Smarc else 23846424Smarc ret |= ktrops(curp, p, ops, facs, vp); 23936359Smarc } 24037593Smarc if (!ret) 24143444Smckusick error = EPERM; 24236359Smarc done: 24337728Smckusick if (vp != NULL) 244*50106Smckusick (void) vn_close(vp, FWRITE, curp->p_ucred, curp); 24544404Skarels return (error); 24636359Smarc } 24736359Smarc 24846424Smarc ktrops(curp, p, ops, facs, vp) 24946424Smarc struct proc *curp, *p; 25037728Smckusick struct vnode *vp; 25136359Smarc { 25237593Smarc 25346424Smarc if (!ktrcanset(curp, p)) 25444404Skarels return (0); 25536359Smarc if (ops == KTROP_SET) { 25640805Smarc if (p->p_tracep != vp) { 25736359Smarc /* 25836359Smarc * if trace file already in use, relinquish 25936359Smarc */ 26036359Smarc if (p->p_tracep != NULL) 26137728Smckusick vrele(p->p_tracep); 26238423Smarc VREF(vp); 26337728Smckusick p->p_tracep = vp; 26436359Smarc } 26536359Smarc p->p_traceflag |= facs; 26647548Skarels if (curp->p_ucred->cr_uid == 0) 26746424Smarc p->p_traceflag |= KTRFAC_ROOT; 26836359Smarc } else { 26936359Smarc /* KTROP_CLEAR */ 27046424Smarc if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 27140805Smarc /* no more tracing */ 27240805Smarc p->p_traceflag = 0; 27336359Smarc if (p->p_tracep != NULL) { 27437728Smckusick vrele(p->p_tracep); 27536359Smarc p->p_tracep = NULL; 27636359Smarc } 27736359Smarc } 27836359Smarc } 27937593Smarc 28046424Smarc return (1); 28136359Smarc } 28237593Smarc 28346424Smarc ktrsetchildren(curp, top, ops, facs, vp) 28446424Smarc struct proc *curp, *top; 28537728Smckusick struct vnode *vp; 28636359Smarc { 28736359Smarc register struct proc *p; 28837593Smarc register int ret = 0; 28936359Smarc 29036359Smarc p = top; 29136359Smarc for (;;) { 29246424Smarc ret |= ktrops(curp, p, ops, facs, vp); 29336359Smarc /* 29436359Smarc * If this process has children, descend to them next, 29536359Smarc * otherwise do any siblings, and if done with this level, 29636359Smarc * follow back up the tree (but not past top). 29736359Smarc */ 29836359Smarc if (p->p_cptr) 29936359Smarc p = p->p_cptr; 30036359Smarc else if (p == top) 30146424Smarc return (ret); 30236359Smarc else if (p->p_osptr) 30336359Smarc p = p->p_osptr; 30436359Smarc else for (;;) { 30536359Smarc p = p->p_pptr; 30636359Smarc if (p == top) 30746424Smarc return (ret); 30836359Smarc if (p->p_osptr) { 30936359Smarc p = p->p_osptr; 31036359Smarc break; 31136359Smarc } 31236359Smarc } 31336359Smarc } 31437593Smarc /*NOTREACHED*/ 31536359Smarc } 31636359Smarc 31737728Smckusick ktrwrite(vp, kth) 31837728Smckusick struct vnode *vp; 31937728Smckusick register struct ktr_header *kth; 32036359Smarc { 32137728Smckusick struct uio auio; 32237728Smckusick struct iovec aiov[2]; 32348017Smckusick register struct proc *p = curproc; /* XXX */ 32439581Smckusick int error; 32537728Smckusick 32637728Smckusick if (vp == NULL) 32737593Smarc return; 32837728Smckusick auio.uio_iov = &aiov[0]; 32937728Smckusick auio.uio_offset = 0; 33037728Smckusick auio.uio_segflg = UIO_SYSSPACE; 33137728Smckusick auio.uio_rw = UIO_WRITE; 33237728Smckusick aiov[0].iov_base = (caddr_t)kth; 33337728Smckusick aiov[0].iov_len = sizeof(struct ktr_header); 33437728Smckusick auio.uio_resid = sizeof(struct ktr_header); 33537728Smckusick auio.uio_iovcnt = 1; 33648017Smckusick auio.uio_procp = (struct proc *)0; 33736359Smarc if (kth->ktr_len > 0) { 33837728Smckusick auio.uio_iovcnt++; 33937728Smckusick aiov[1].iov_base = kth->ktr_buf; 34037728Smckusick aiov[1].iov_len = kth->ktr_len; 34137728Smckusick auio.uio_resid += kth->ktr_len; 34236359Smarc } 34339581Smckusick VOP_LOCK(vp); 34448017Smckusick error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred); 34539581Smckusick VOP_UNLOCK(vp); 34641573Smckusick if (!error) 34741573Smckusick return; 34841573Smckusick /* 34941573Smckusick * If error encountered, give up tracing on this vnode. 35041573Smckusick */ 35147548Skarels log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", 35247548Skarels 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 } 36146424Smarc 36246424Smarc /* 36346424Smarc * Return true if caller has permission to set the ktracing state 36446424Smarc * of target. Essentially, the target can't possess any 36546424Smarc * more permissions than the caller. KTRFAC_ROOT signifies that 36646424Smarc * root previously set the tracing status on the target process, and 36746424Smarc * so, only root may further change it. 36846424Smarc * 36947548Skarels * TODO: check groups. use caller effective gid. 37046424Smarc */ 37147548Skarels ktrcanset(callp, targetp) 37247548Skarels struct proc *callp, *targetp; 37346424Smarc { 37447548Skarels register struct pcred *caller = callp->p_cred; 37547548Skarels register struct pcred *target = targetp->p_cred; 37647548Skarels 37747548Skarels if ((caller->pc_ucred->cr_uid == target->p_ruid && 37846424Smarc target->p_ruid == target->p_svuid && 37946424Smarc caller->p_rgid == target->p_rgid && /* XXX */ 38046424Smarc target->p_rgid == target->p_svgid && 38147548Skarels (targetp->p_traceflag & KTRFAC_ROOT) == 0) || 38247548Skarels caller->pc_ucred->cr_uid == 0) 38346424Smarc return (1); 38446424Smarc 38546424Smarc return (0); 38646424Smarc } 38746424Smarc 38836359Smarc #endif 389