kern_ktrace.c revision 51941
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1989, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 3. All advertising materials mentioning features or use of this software 141541Srgrimes * must display the following acknowledgement: 151541Srgrimes * This product includes software developed by the University of 161541Srgrimes * California, Berkeley and its contributors. 171541Srgrimes * 4. Neither the name of the University nor the names of its contributors 181541Srgrimes * may be used to endorse or promote products derived from this software 191541Srgrimes * without specific prior written permission. 201541Srgrimes * 211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311541Srgrimes * SUCH DAMAGE. 321541Srgrimes * 331541Srgrimes * @(#)kern_ktrace.c 8.2 (Berkeley) 9/23/93 3450477Speter * $FreeBSD: head/sys/kern/kern_ktrace.c 51941 1999-10-04 18:29:51Z marcel $ 351541Srgrimes */ 361541Srgrimes 3713203Swollman#include "opt_ktrace.h" 381541Srgrimes 391541Srgrimes#include <sys/param.h> 402112Swollman#include <sys/systm.h> 4112221Sbde#include <sys/sysproto.h> 4241059Speter#include <sys/kernel.h> 431541Srgrimes#include <sys/proc.h> 4424131Sbde#include <sys/fcntl.h> 4531561Sbde#include <sys/lock.h> 461541Srgrimes#include <sys/namei.h> 471541Srgrimes#include <sys/vnode.h> 481541Srgrimes#include <sys/ktrace.h> 491541Srgrimes#include <sys/malloc.h> 501541Srgrimes#include <sys/syslog.h> 511541Srgrimes 5247955Sdt#include <stddef.h> 5347955Sdt 5430354Sphkstatic MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE"); 5530309Sphk 5613203Swollman#ifdef KTRACE 5712819Sphkstatic struct ktr_header *ktrgetheader __P((int type)); 5812819Sphkstatic void ktrwrite __P((struct vnode *, struct ktr_header *)); 5912819Sphkstatic int ktrcanset __P((struct proc *,struct proc *)); 6012819Sphkstatic int ktrsetchildren __P((struct proc *,struct proc *,int,int,struct vnode *)); 6112819Sphkstatic int ktrops __P((struct proc *,struct proc *,int,int,struct vnode *)); 6212577Sbde 6312819Sphk 6412819Sphkstatic struct ktr_header * 651541Srgrimesktrgetheader(type) 661541Srgrimes int type; 671541Srgrimes{ 681541Srgrimes register struct ktr_header *kth; 691541Srgrimes struct proc *p = curproc; /* XXX */ 701541Srgrimes 718876Srgrimes MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 7217429Sphk M_KTRACE, M_WAITOK); 731541Srgrimes kth->ktr_type = type; 741541Srgrimes microtime(&kth->ktr_time); 751541Srgrimes kth->ktr_pid = p->p_pid; 7651484Smarcel bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN + 1); 771541Srgrimes return (kth); 781541Srgrimes} 791541Srgrimes 801549Srgrimesvoid 811541Srgrimesktrsyscall(vp, code, narg, args) 821541Srgrimes struct vnode *vp; 8347955Sdt int code, narg; 8447955Sdt register_t args[]; 851541Srgrimes{ 861541Srgrimes struct ktr_header *kth; 871541Srgrimes struct ktr_syscall *ktp; 8847955Sdt register int len = offsetof(struct ktr_syscall, ktr_args) + 8947955Sdt (narg * sizeof(register_t)); 901541Srgrimes struct proc *p = curproc; /* XXX */ 9147955Sdt register_t *argp; 9247955Sdt int i; 931541Srgrimes 941541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 951541Srgrimes kth = ktrgetheader(KTR_SYSCALL); 9617429Sphk MALLOC(ktp, struct ktr_syscall *, len, M_KTRACE, M_WAITOK); 971541Srgrimes ktp->ktr_code = code; 981541Srgrimes ktp->ktr_narg = narg; 9947955Sdt argp = &ktp->ktr_args[0]; 1001541Srgrimes for (i = 0; i < narg; i++) 1011541Srgrimes *argp++ = args[i]; 1021541Srgrimes kth->ktr_buf = (caddr_t)ktp; 1031541Srgrimes kth->ktr_len = len; 1041541Srgrimes ktrwrite(vp, kth); 10517429Sphk FREE(ktp, M_KTRACE); 10617429Sphk FREE(kth, M_KTRACE); 1071541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1081541Srgrimes} 1091541Srgrimes 1101549Srgrimesvoid 1111541Srgrimesktrsysret(vp, code, error, retval) 1121541Srgrimes struct vnode *vp; 11347955Sdt int code, error; 11447955Sdt register_t retval; 1151541Srgrimes{ 1161541Srgrimes struct ktr_header *kth; 1171541Srgrimes struct ktr_sysret ktp; 1181541Srgrimes struct proc *p = curproc; /* XXX */ 1191541Srgrimes 1201541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1211541Srgrimes kth = ktrgetheader(KTR_SYSRET); 1221541Srgrimes ktp.ktr_code = code; 1231541Srgrimes ktp.ktr_error = error; 1241541Srgrimes ktp.ktr_retval = retval; /* what about val2 ? */ 1251541Srgrimes 1261541Srgrimes kth->ktr_buf = (caddr_t)&ktp; 1271541Srgrimes kth->ktr_len = sizeof(struct ktr_sysret); 1281541Srgrimes 1291541Srgrimes ktrwrite(vp, kth); 13017429Sphk FREE(kth, M_KTRACE); 1311541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1321541Srgrimes} 1331541Srgrimes 1341549Srgrimesvoid 1351541Srgrimesktrnamei(vp, path) 1361541Srgrimes struct vnode *vp; 1371541Srgrimes char *path; 1381541Srgrimes{ 1391541Srgrimes struct ktr_header *kth; 1401541Srgrimes struct proc *p = curproc; /* XXX */ 1411541Srgrimes 1421541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1431541Srgrimes kth = ktrgetheader(KTR_NAMEI); 1441541Srgrimes kth->ktr_len = strlen(path); 1451541Srgrimes kth->ktr_buf = path; 1461541Srgrimes 1471541Srgrimes ktrwrite(vp, kth); 14817429Sphk FREE(kth, M_KTRACE); 1491541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1501541Srgrimes} 1511541Srgrimes 1521549Srgrimesvoid 1531541Srgrimesktrgenio(vp, fd, rw, iov, len, error) 1541541Srgrimes struct vnode *vp; 1551541Srgrimes int fd; 1561541Srgrimes enum uio_rw rw; 1571541Srgrimes register struct iovec *iov; 1581541Srgrimes int len, error; 1591541Srgrimes{ 1601541Srgrimes struct ktr_header *kth; 1611541Srgrimes register struct ktr_genio *ktp; 1621541Srgrimes register caddr_t cp; 1631541Srgrimes register int resid = len, cnt; 1641541Srgrimes struct proc *p = curproc; /* XXX */ 1658876Srgrimes 1661541Srgrimes if (error) 1671541Srgrimes return; 1681541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1691541Srgrimes kth = ktrgetheader(KTR_GENIO); 1701541Srgrimes MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, 17117429Sphk M_KTRACE, M_WAITOK); 1721541Srgrimes ktp->ktr_fd = fd; 1731541Srgrimes ktp->ktr_rw = rw; 1741541Srgrimes cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); 1751541Srgrimes while (resid > 0) { 1761541Srgrimes if ((cnt = iov->iov_len) > resid) 1771541Srgrimes cnt = resid; 1781541Srgrimes if (copyin(iov->iov_base, cp, (unsigned)cnt)) 1791541Srgrimes goto done; 1801541Srgrimes cp += cnt; 1811541Srgrimes resid -= cnt; 1821541Srgrimes iov++; 1831541Srgrimes } 1841541Srgrimes kth->ktr_buf = (caddr_t)ktp; 1851541Srgrimes kth->ktr_len = sizeof (struct ktr_genio) + len; 1861541Srgrimes 1871541Srgrimes ktrwrite(vp, kth); 1881541Srgrimesdone: 18917429Sphk FREE(kth, M_KTRACE); 19017429Sphk FREE(ktp, M_KTRACE); 1911541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1921541Srgrimes} 1931541Srgrimes 1941549Srgrimesvoid 1951541Srgrimesktrpsig(vp, sig, action, mask, code) 1961541Srgrimes struct vnode *vp; 19751941Smarcel int sig; 1981541Srgrimes sig_t action; 19951791Smarcel sigset_t *mask; 20051941Smarcel int code; 2011541Srgrimes{ 2021541Srgrimes struct ktr_header *kth; 2031541Srgrimes struct ktr_psig kp; 2041541Srgrimes struct proc *p = curproc; /* XXX */ 2051541Srgrimes 2061541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 2071541Srgrimes kth = ktrgetheader(KTR_PSIG); 2081541Srgrimes kp.signo = (char)sig; 2091541Srgrimes kp.action = action; 21051791Smarcel kp.mask = *mask; 2111541Srgrimes kp.code = code; 2121541Srgrimes kth->ktr_buf = (caddr_t)&kp; 2131541Srgrimes kth->ktr_len = sizeof (struct ktr_psig); 2141541Srgrimes 2151541Srgrimes ktrwrite(vp, kth); 21617429Sphk FREE(kth, M_KTRACE); 2171541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2181541Srgrimes} 2191541Srgrimes 2201549Srgrimesvoid 2211541Srgrimesktrcsw(vp, out, user) 2221541Srgrimes struct vnode *vp; 2231541Srgrimes int out, user; 2241541Srgrimes{ 2251541Srgrimes struct ktr_header *kth; 2261541Srgrimes struct ktr_csw kc; 2271541Srgrimes struct proc *p = curproc; /* XXX */ 2281541Srgrimes 2291541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 2301541Srgrimes kth = ktrgetheader(KTR_CSW); 2311541Srgrimes kc.out = out; 2321541Srgrimes kc.user = user; 2331541Srgrimes kth->ktr_buf = (caddr_t)&kc; 2341541Srgrimes kth->ktr_len = sizeof (struct ktr_csw); 2351541Srgrimes 2361541Srgrimes ktrwrite(vp, kth); 23717429Sphk FREE(kth, M_KTRACE); 2381541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2391541Srgrimes} 24013203Swollman#endif 2411541Srgrimes 2421541Srgrimes/* Interface and common routines */ 2431541Srgrimes 2441541Srgrimes/* 2451541Srgrimes * ktrace system call 2461541Srgrimes */ 24712221Sbde#ifndef _SYS_SYSPROTO_H_ 2481541Srgrimesstruct ktrace_args { 2491541Srgrimes char *fname; 2501541Srgrimes int ops; 2511541Srgrimes int facs; 2521541Srgrimes int pid; 2531541Srgrimes}; 25412221Sbde#endif 2551541Srgrimes/* ARGSUSED */ 2561549Srgrimesint 25730994Sphkktrace(curp, uap) 2581541Srgrimes struct proc *curp; 2591541Srgrimes register struct ktrace_args *uap; 2601541Srgrimes{ 26113203Swollman#ifdef KTRACE 2621541Srgrimes register struct vnode *vp = NULL; 2631541Srgrimes register struct proc *p; 2641541Srgrimes struct pgrp *pg; 2651541Srgrimes int facs = uap->facs & ~KTRFAC_ROOT; 2661541Srgrimes int ops = KTROP(uap->ops); 2671541Srgrimes int descend = uap->ops & KTRFLAG_DESCEND; 2681541Srgrimes int ret = 0; 2691541Srgrimes int error = 0; 2701541Srgrimes struct nameidata nd; 2711541Srgrimes 2721541Srgrimes curp->p_traceflag |= KTRFAC_ACTIVE; 2731541Srgrimes if (ops != KTROP_CLEAR) { 2741541Srgrimes /* 2751541Srgrimes * an operation which requires a file argument. 2761541Srgrimes */ 27750668Sdima NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, curp); 27850668Sdima error = vn_open(&nd, FREAD|FWRITE|O_NOFOLLOW, 0); 2793308Sphk if (error) { 2801541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 2811541Srgrimes return (error); 2821541Srgrimes } 2831541Srgrimes vp = nd.ni_vp; 28422521Sdyson VOP_UNLOCK(vp, 0, curp); 2851541Srgrimes if (vp->v_type != VREG) { 2861541Srgrimes (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); 2871541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 2881541Srgrimes return (EACCES); 2891541Srgrimes } 2901541Srgrimes } 2911541Srgrimes /* 2921541Srgrimes * Clear all uses of the tracefile 2931541Srgrimes */ 2941541Srgrimes if (ops == KTROP_CLEARFILE) { 29514529Shsu for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 2961541Srgrimes if (p->p_tracep == vp) { 2971541Srgrimes if (ktrcanset(curp, p)) { 2981541Srgrimes p->p_tracep = NULL; 2991541Srgrimes p->p_traceflag = 0; 3001541Srgrimes (void) vn_close(vp, FREAD|FWRITE, 3011541Srgrimes p->p_ucred, p); 3021541Srgrimes } else 3031541Srgrimes error = EPERM; 3041541Srgrimes } 3051541Srgrimes } 3061541Srgrimes goto done; 3071541Srgrimes } 3081541Srgrimes /* 3091541Srgrimes * need something to (un)trace (XXX - why is this here?) 3101541Srgrimes */ 3111541Srgrimes if (!facs) { 3121541Srgrimes error = EINVAL; 3131541Srgrimes goto done; 3141541Srgrimes } 3158876Srgrimes /* 3161541Srgrimes * do it 3171541Srgrimes */ 3181541Srgrimes if (uap->pid < 0) { 3191541Srgrimes /* 3201541Srgrimes * by process group 3211541Srgrimes */ 3221541Srgrimes pg = pgfind(-uap->pid); 3231541Srgrimes if (pg == NULL) { 3241541Srgrimes error = ESRCH; 3251541Srgrimes goto done; 3261541Srgrimes } 32714529Shsu for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) 3281541Srgrimes if (descend) 3291541Srgrimes ret |= ktrsetchildren(curp, p, ops, facs, vp); 3308876Srgrimes else 3311541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 3328876Srgrimes 3331541Srgrimes } else { 3341541Srgrimes /* 3351541Srgrimes * by pid 3361541Srgrimes */ 3371541Srgrimes p = pfind(uap->pid); 3381541Srgrimes if (p == NULL) { 3391541Srgrimes error = ESRCH; 3401541Srgrimes goto done; 3411541Srgrimes } 3421541Srgrimes if (descend) 3431541Srgrimes ret |= ktrsetchildren(curp, p, ops, facs, vp); 3441541Srgrimes else 3451541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 3461541Srgrimes } 3471541Srgrimes if (!ret) 3481541Srgrimes error = EPERM; 3491541Srgrimesdone: 3501541Srgrimes if (vp != NULL) 3511541Srgrimes (void) vn_close(vp, FWRITE, curp->p_ucred, curp); 3521541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 3531541Srgrimes return (error); 35413203Swollman#else 35513203Swollman return ENOSYS; 35613203Swollman#endif 3571541Srgrimes} 3581541Srgrimes 35918398Sphk/* 36018398Sphk * utrace system call 36118398Sphk */ 36218398Sphk/* ARGSUSED */ 36318398Sphkint 36430994Sphkutrace(curp, uap) 36518398Sphk struct proc *curp; 36618398Sphk register struct utrace_args *uap; 36718398Sphk{ 36813203Swollman#ifdef KTRACE 36918398Sphk struct ktr_header *kth; 37018398Sphk struct proc *p = curproc; /* XXX */ 37118398Sphk register caddr_t cp; 37218398Sphk 37318398Sphk if (!KTRPOINT(p, KTR_USER)) 37418398Sphk return (0); 37518398Sphk p->p_traceflag |= KTRFAC_ACTIVE; 37618398Sphk kth = ktrgetheader(KTR_USER); 37718469Sphk MALLOC(cp, caddr_t, uap->len, M_KTRACE, M_WAITOK); 37818398Sphk if (!copyin(uap->addr, cp, uap->len)) { 37918469Sphk kth->ktr_buf = cp; 38018469Sphk kth->ktr_len = uap->len; 38118398Sphk ktrwrite(p->p_tracep, kth); 38218398Sphk } 38318398Sphk FREE(kth, M_KTRACE); 38418469Sphk FREE(cp, M_KTRACE); 38518398Sphk p->p_traceflag &= ~KTRFAC_ACTIVE; 38618398Sphk 38718398Sphk return (0); 38818398Sphk#else 38918398Sphk return (ENOSYS); 39018398Sphk#endif 39118398Sphk} 39218398Sphk 39318398Sphk#ifdef KTRACE 39412819Sphkstatic int 3951541Srgrimesktrops(curp, p, ops, facs, vp) 3961541Srgrimes struct proc *p, *curp; 3971541Srgrimes int ops, facs; 3981541Srgrimes struct vnode *vp; 3991541Srgrimes{ 4001541Srgrimes 4011541Srgrimes if (!ktrcanset(curp, p)) 4021541Srgrimes return (0); 4031541Srgrimes if (ops == KTROP_SET) { 4048876Srgrimes if (p->p_tracep != vp) { 4051541Srgrimes /* 4061541Srgrimes * if trace file already in use, relinquish 4071541Srgrimes */ 4081541Srgrimes if (p->p_tracep != NULL) 4091541Srgrimes vrele(p->p_tracep); 4101541Srgrimes VREF(vp); 4111541Srgrimes p->p_tracep = vp; 4121541Srgrimes } 4131541Srgrimes p->p_traceflag |= facs; 4141541Srgrimes if (curp->p_ucred->cr_uid == 0) 4151541Srgrimes p->p_traceflag |= KTRFAC_ROOT; 4168876Srgrimes } else { 4171541Srgrimes /* KTROP_CLEAR */ 4181541Srgrimes if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 4191541Srgrimes /* no more tracing */ 4201541Srgrimes p->p_traceflag = 0; 4211541Srgrimes if (p->p_tracep != NULL) { 4221541Srgrimes vrele(p->p_tracep); 4231541Srgrimes p->p_tracep = NULL; 4241541Srgrimes } 4251541Srgrimes } 4261541Srgrimes } 4271541Srgrimes 4281541Srgrimes return (1); 4291541Srgrimes} 4301541Srgrimes 43112819Sphkstatic int 4321541Srgrimesktrsetchildren(curp, top, ops, facs, vp) 4331541Srgrimes struct proc *curp, *top; 4341541Srgrimes int ops, facs; 4351541Srgrimes struct vnode *vp; 4361541Srgrimes{ 4371541Srgrimes register struct proc *p; 4381541Srgrimes register int ret = 0; 4391541Srgrimes 4401541Srgrimes p = top; 4411541Srgrimes for (;;) { 4421541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 4431541Srgrimes /* 4441541Srgrimes * If this process has children, descend to them next, 4451541Srgrimes * otherwise do any siblings, and if done with this level, 4461541Srgrimes * follow back up the tree (but not past top). 4471541Srgrimes */ 44814529Shsu if (p->p_children.lh_first) 44914529Shsu p = p->p_children.lh_first; 4501541Srgrimes else for (;;) { 4511541Srgrimes if (p == top) 4521541Srgrimes return (ret); 45314529Shsu if (p->p_sibling.le_next) { 45414529Shsu p = p->p_sibling.le_next; 4551541Srgrimes break; 4561541Srgrimes } 45714529Shsu p = p->p_pptr; 4581541Srgrimes } 4591541Srgrimes } 4601541Srgrimes /*NOTREACHED*/ 4611541Srgrimes} 4621541Srgrimes 46312819Sphkstatic void 4641541Srgrimesktrwrite(vp, kth) 4651541Srgrimes struct vnode *vp; 4661541Srgrimes register struct ktr_header *kth; 4671541Srgrimes{ 4681541Srgrimes struct uio auio; 4691541Srgrimes struct iovec aiov[2]; 4701541Srgrimes register struct proc *p = curproc; /* XXX */ 4711541Srgrimes int error; 4721541Srgrimes 4731541Srgrimes if (vp == NULL) 4741541Srgrimes return; 4751541Srgrimes auio.uio_iov = &aiov[0]; 4761541Srgrimes auio.uio_offset = 0; 4771541Srgrimes auio.uio_segflg = UIO_SYSSPACE; 4781541Srgrimes auio.uio_rw = UIO_WRITE; 4791541Srgrimes aiov[0].iov_base = (caddr_t)kth; 4801541Srgrimes aiov[0].iov_len = sizeof(struct ktr_header); 4811541Srgrimes auio.uio_resid = sizeof(struct ktr_header); 4821541Srgrimes auio.uio_iovcnt = 1; 48341628Srvb auio.uio_procp = curproc; 4841541Srgrimes if (kth->ktr_len > 0) { 4851541Srgrimes auio.uio_iovcnt++; 4861541Srgrimes aiov[1].iov_base = kth->ktr_buf; 4871541Srgrimes aiov[1].iov_len = kth->ktr_len; 4881541Srgrimes auio.uio_resid += kth->ktr_len; 4891541Srgrimes } 49022521Sdyson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 4911541Srgrimes error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred); 49222521Sdyson VOP_UNLOCK(vp, 0, p); 4931541Srgrimes if (!error) 4941541Srgrimes return; 4951541Srgrimes /* 4961541Srgrimes * If error encountered, give up tracing on this vnode. 4971541Srgrimes */ 4981541Srgrimes log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", 4991541Srgrimes error); 50014529Shsu for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 5011541Srgrimes if (p->p_tracep == vp) { 5021541Srgrimes p->p_tracep = NULL; 5031541Srgrimes p->p_traceflag = 0; 5041541Srgrimes vrele(vp); 5051541Srgrimes } 5061541Srgrimes } 5071541Srgrimes} 5081541Srgrimes 5091541Srgrimes/* 5101541Srgrimes * Return true if caller has permission to set the ktracing state 5111541Srgrimes * of target. Essentially, the target can't possess any 5121541Srgrimes * more permissions than the caller. KTRFAC_ROOT signifies that 5138876Srgrimes * root previously set the tracing status on the target process, and 5141541Srgrimes * so, only root may further change it. 5151541Srgrimes * 5161541Srgrimes * TODO: check groups. use caller effective gid. 5171541Srgrimes */ 51812819Sphkstatic int 5191541Srgrimesktrcanset(callp, targetp) 5201541Srgrimes struct proc *callp, *targetp; 5211541Srgrimes{ 5221541Srgrimes register struct pcred *caller = callp->p_cred; 5231541Srgrimes register struct pcred *target = targetp->p_cred; 5241541Srgrimes 52546155Sphk if (!PRISON_CHECK(callp, targetp)) 52646155Sphk return (0); 5271541Srgrimes if ((caller->pc_ucred->cr_uid == target->p_ruid && 5281541Srgrimes target->p_ruid == target->p_svuid && 5291541Srgrimes caller->p_rgid == target->p_rgid && /* XXX */ 5301541Srgrimes target->p_rgid == target->p_svgid && 5311541Srgrimes (targetp->p_traceflag & KTRFAC_ROOT) == 0) || 5321541Srgrimes caller->pc_ucred->cr_uid == 0) 5331541Srgrimes return (1); 5341541Srgrimes 5351541Srgrimes return (0); 5361541Srgrimes} 5371541Srgrimes 53813203Swollman#endif /* KTRACE */ 539