kern_ktrace.c revision 70707
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 70707 2001-01-06 09:34:20Z alfred $ 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> 5170707Salfred#include <sys/sysent.h> 521541Srgrimes 5330354Sphkstatic MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE"); 5430309Sphk 5513203Swollman#ifdef KTRACE 5612819Sphkstatic struct ktr_header *ktrgetheader __P((int type)); 5762378Sgreenstatic void ktrwrite __P((struct vnode *, struct ktr_header *, struct uio *)); 5812819Sphkstatic int ktrcanset __P((struct proc *,struct proc *)); 5912819Sphkstatic int ktrsetchildren __P((struct proc *,struct proc *,int,int,struct vnode *)); 6012819Sphkstatic int ktrops __P((struct proc *,struct proc *,int,int,struct vnode *)); 6112577Sbde 6212819Sphk 6312819Sphkstatic struct ktr_header * 641541Srgrimesktrgetheader(type) 651541Srgrimes int type; 661541Srgrimes{ 671541Srgrimes register struct ktr_header *kth; 681541Srgrimes struct proc *p = curproc; /* XXX */ 691541Srgrimes 708876Srgrimes MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 7117429Sphk M_KTRACE, M_WAITOK); 721541Srgrimes kth->ktr_type = type; 731541Srgrimes microtime(&kth->ktr_time); 741541Srgrimes kth->ktr_pid = p->p_pid; 7551484Smarcel bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN + 1); 761541Srgrimes return (kth); 771541Srgrimes} 781541Srgrimes 791549Srgrimesvoid 801541Srgrimesktrsyscall(vp, code, narg, args) 811541Srgrimes struct vnode *vp; 8247955Sdt int code, narg; 8347955Sdt register_t args[]; 841541Srgrimes{ 851541Srgrimes struct ktr_header *kth; 861541Srgrimes struct ktr_syscall *ktp; 8747955Sdt register int len = offsetof(struct ktr_syscall, ktr_args) + 8847955Sdt (narg * sizeof(register_t)); 891541Srgrimes struct proc *p = curproc; /* XXX */ 9047955Sdt register_t *argp; 9147955Sdt int i; 921541Srgrimes 931541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 941541Srgrimes kth = ktrgetheader(KTR_SYSCALL); 9517429Sphk MALLOC(ktp, struct ktr_syscall *, len, M_KTRACE, M_WAITOK); 961541Srgrimes ktp->ktr_code = code; 971541Srgrimes ktp->ktr_narg = narg; 9847955Sdt argp = &ktp->ktr_args[0]; 991541Srgrimes for (i = 0; i < narg; i++) 1001541Srgrimes *argp++ = args[i]; 10165556Sjasone kth->ktr_buffer = (caddr_t)ktp; 1021541Srgrimes kth->ktr_len = len; 10362378Sgreen ktrwrite(vp, kth, NULL); 10417429Sphk FREE(ktp, M_KTRACE); 10517429Sphk FREE(kth, M_KTRACE); 1061541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1071541Srgrimes} 1081541Srgrimes 1091549Srgrimesvoid 1101541Srgrimesktrsysret(vp, code, error, retval) 1111541Srgrimes struct vnode *vp; 11247955Sdt int code, error; 11347955Sdt register_t retval; 1141541Srgrimes{ 1151541Srgrimes struct ktr_header *kth; 1161541Srgrimes struct ktr_sysret ktp; 1171541Srgrimes struct proc *p = curproc; /* XXX */ 1181541Srgrimes 1191541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1201541Srgrimes kth = ktrgetheader(KTR_SYSRET); 1211541Srgrimes ktp.ktr_code = code; 1221541Srgrimes ktp.ktr_error = error; 1231541Srgrimes ktp.ktr_retval = retval; /* what about val2 ? */ 1241541Srgrimes 12565556Sjasone kth->ktr_buffer = (caddr_t)&ktp; 1261541Srgrimes kth->ktr_len = sizeof(struct ktr_sysret); 1271541Srgrimes 12862378Sgreen ktrwrite(vp, kth, NULL); 12917429Sphk FREE(kth, M_KTRACE); 1301541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1311541Srgrimes} 1321541Srgrimes 1331549Srgrimesvoid 1341541Srgrimesktrnamei(vp, path) 1351541Srgrimes struct vnode *vp; 1361541Srgrimes char *path; 1371541Srgrimes{ 1381541Srgrimes struct ktr_header *kth; 1391541Srgrimes struct proc *p = curproc; /* XXX */ 1401541Srgrimes 1411541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1421541Srgrimes kth = ktrgetheader(KTR_NAMEI); 1431541Srgrimes kth->ktr_len = strlen(path); 14465556Sjasone kth->ktr_buffer = path; 1451541Srgrimes 14662378Sgreen ktrwrite(vp, kth, NULL); 14717429Sphk FREE(kth, M_KTRACE); 1481541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1491541Srgrimes} 1501541Srgrimes 1511549Srgrimesvoid 15262378Sgreenktrgenio(vp, fd, rw, uio, error) 1531541Srgrimes struct vnode *vp; 1541541Srgrimes int fd; 1551541Srgrimes enum uio_rw rw; 15662378Sgreen struct uio *uio; 15762378Sgreen int error; 1581541Srgrimes{ 1591541Srgrimes struct ktr_header *kth; 16062378Sgreen struct ktr_genio ktg; 1611541Srgrimes struct proc *p = curproc; /* XXX */ 1628876Srgrimes 1631541Srgrimes if (error) 1641541Srgrimes return; 1651541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1661541Srgrimes kth = ktrgetheader(KTR_GENIO); 16762378Sgreen ktg.ktr_fd = fd; 16862378Sgreen ktg.ktr_rw = rw; 16965556Sjasone kth->ktr_buffer = (caddr_t)&ktg; 17062378Sgreen kth->ktr_len = sizeof(struct ktr_genio); 17162378Sgreen uio->uio_offset = 0; 17262791Sgreen uio->uio_rw = UIO_WRITE; 1731541Srgrimes 17462378Sgreen ktrwrite(vp, kth, uio); 17517429Sphk FREE(kth, M_KTRACE); 1761541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1771541Srgrimes} 1781541Srgrimes 1791549Srgrimesvoid 1801541Srgrimesktrpsig(vp, sig, action, mask, code) 1811541Srgrimes struct vnode *vp; 18251941Smarcel int sig; 1831541Srgrimes sig_t action; 18451791Smarcel sigset_t *mask; 18551941Smarcel int code; 1861541Srgrimes{ 1871541Srgrimes struct ktr_header *kth; 1881541Srgrimes struct ktr_psig kp; 1891541Srgrimes struct proc *p = curproc; /* XXX */ 1901541Srgrimes 1911541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1921541Srgrimes kth = ktrgetheader(KTR_PSIG); 1931541Srgrimes kp.signo = (char)sig; 1941541Srgrimes kp.action = action; 19551791Smarcel kp.mask = *mask; 1961541Srgrimes kp.code = code; 19765556Sjasone kth->ktr_buffer = (caddr_t)&kp; 1981541Srgrimes kth->ktr_len = sizeof (struct ktr_psig); 1991541Srgrimes 20062378Sgreen ktrwrite(vp, kth, NULL); 20117429Sphk FREE(kth, M_KTRACE); 2021541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2031541Srgrimes} 2041541Srgrimes 2051549Srgrimesvoid 2061541Srgrimesktrcsw(vp, out, user) 2071541Srgrimes struct vnode *vp; 2081541Srgrimes int out, user; 2091541Srgrimes{ 2101541Srgrimes struct ktr_header *kth; 2111541Srgrimes struct ktr_csw kc; 2121541Srgrimes struct proc *p = curproc; /* XXX */ 2131541Srgrimes 2141541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 2151541Srgrimes kth = ktrgetheader(KTR_CSW); 2161541Srgrimes kc.out = out; 2171541Srgrimes kc.user = user; 21865556Sjasone kth->ktr_buffer = (caddr_t)&kc; 2191541Srgrimes kth->ktr_len = sizeof (struct ktr_csw); 2201541Srgrimes 22162378Sgreen ktrwrite(vp, kth, NULL); 22217429Sphk FREE(kth, M_KTRACE); 2231541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2241541Srgrimes} 22513203Swollman#endif 2261541Srgrimes 2271541Srgrimes/* Interface and common routines */ 2281541Srgrimes 2291541Srgrimes/* 2301541Srgrimes * ktrace system call 2311541Srgrimes */ 23212221Sbde#ifndef _SYS_SYSPROTO_H_ 2331541Srgrimesstruct ktrace_args { 2341541Srgrimes char *fname; 2351541Srgrimes int ops; 2361541Srgrimes int facs; 2371541Srgrimes int pid; 2381541Srgrimes}; 23912221Sbde#endif 2401541Srgrimes/* ARGSUSED */ 2411549Srgrimesint 24230994Sphkktrace(curp, uap) 2431541Srgrimes struct proc *curp; 2441541Srgrimes register struct ktrace_args *uap; 2451541Srgrimes{ 24613203Swollman#ifdef KTRACE 2471541Srgrimes register struct vnode *vp = NULL; 2481541Srgrimes register struct proc *p; 2491541Srgrimes struct pgrp *pg; 2501541Srgrimes int facs = uap->facs & ~KTRFAC_ROOT; 2511541Srgrimes int ops = KTROP(uap->ops); 2521541Srgrimes int descend = uap->ops & KTRFLAG_DESCEND; 2531541Srgrimes int ret = 0; 25462550Smckusick int flags, error = 0; 2551541Srgrimes struct nameidata nd; 2561541Srgrimes 2571541Srgrimes curp->p_traceflag |= KTRFAC_ACTIVE; 2581541Srgrimes if (ops != KTROP_CLEAR) { 2591541Srgrimes /* 2601541Srgrimes * an operation which requires a file argument. 2611541Srgrimes */ 26250668Sdima NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, curp); 26362550Smckusick flags = FREAD | FWRITE | O_NOFOLLOW; 26462550Smckusick error = vn_open(&nd, &flags, 0); 2653308Sphk if (error) { 2661541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 2671541Srgrimes return (error); 2681541Srgrimes } 26954655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 2701541Srgrimes vp = nd.ni_vp; 27122521Sdyson VOP_UNLOCK(vp, 0, curp); 2721541Srgrimes if (vp->v_type != VREG) { 2731541Srgrimes (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); 2741541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 2751541Srgrimes return (EACCES); 2761541Srgrimes } 2771541Srgrimes } 2781541Srgrimes /* 2791541Srgrimes * Clear all uses of the tracefile 2801541Srgrimes */ 2811541Srgrimes if (ops == KTROP_CLEARFILE) { 28269947Sjake ALLPROC_LOCK(AP_SHARED); 28353212Sphk LIST_FOREACH(p, &allproc, p_list) { 2841541Srgrimes if (p->p_tracep == vp) { 2851541Srgrimes if (ktrcanset(curp, p)) { 2861541Srgrimes p->p_tracep = NULL; 2871541Srgrimes p->p_traceflag = 0; 2881541Srgrimes (void) vn_close(vp, FREAD|FWRITE, 2891541Srgrimes p->p_ucred, p); 2901541Srgrimes } else 2911541Srgrimes error = EPERM; 2921541Srgrimes } 2931541Srgrimes } 29469947Sjake ALLPROC_LOCK(AP_RELEASE); 2951541Srgrimes goto done; 2961541Srgrimes } 2971541Srgrimes /* 2981541Srgrimes * need something to (un)trace (XXX - why is this here?) 2991541Srgrimes */ 3001541Srgrimes if (!facs) { 3011541Srgrimes error = EINVAL; 3021541Srgrimes goto done; 3031541Srgrimes } 3048876Srgrimes /* 3051541Srgrimes * do it 3061541Srgrimes */ 3071541Srgrimes if (uap->pid < 0) { 3081541Srgrimes /* 3091541Srgrimes * by process group 3101541Srgrimes */ 3111541Srgrimes pg = pgfind(-uap->pid); 3121541Srgrimes if (pg == NULL) { 3131541Srgrimes error = ESRCH; 3141541Srgrimes goto done; 3151541Srgrimes } 31653212Sphk LIST_FOREACH(p, &pg->pg_members, p_pglist) 3171541Srgrimes if (descend) 3181541Srgrimes ret |= ktrsetchildren(curp, p, ops, facs, vp); 3198876Srgrimes else 3201541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 3211541Srgrimes } else { 3221541Srgrimes /* 3231541Srgrimes * by pid 3241541Srgrimes */ 3251541Srgrimes p = pfind(uap->pid); 3261541Srgrimes if (p == NULL) { 3271541Srgrimes error = ESRCH; 3281541Srgrimes goto done; 3291541Srgrimes } 3301541Srgrimes if (descend) 3311541Srgrimes ret |= ktrsetchildren(curp, p, ops, facs, vp); 3321541Srgrimes else 3331541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 3341541Srgrimes } 3351541Srgrimes if (!ret) 3361541Srgrimes error = EPERM; 3371541Srgrimesdone: 3381541Srgrimes if (vp != NULL) 3391541Srgrimes (void) vn_close(vp, FWRITE, curp->p_ucred, curp); 3401541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 3411541Srgrimes return (error); 34213203Swollman#else 34313203Swollman return ENOSYS; 34413203Swollman#endif 3451541Srgrimes} 3461541Srgrimes 34718398Sphk/* 34818398Sphk * utrace system call 34918398Sphk */ 35018398Sphk/* ARGSUSED */ 35118398Sphkint 35230994Sphkutrace(curp, uap) 35318398Sphk struct proc *curp; 35418398Sphk register struct utrace_args *uap; 35518398Sphk{ 35613203Swollman#ifdef KTRACE 35718398Sphk struct ktr_header *kth; 35818398Sphk struct proc *p = curproc; /* XXX */ 35918398Sphk register caddr_t cp; 36018398Sphk 36118398Sphk if (!KTRPOINT(p, KTR_USER)) 36218398Sphk return (0); 36370707Salfred if (SCARG(uap, len) > KTR_USER_MAXLEN) 36470707Salfred return (EINVAL); 36518398Sphk p->p_traceflag |= KTRFAC_ACTIVE; 36618398Sphk kth = ktrgetheader(KTR_USER); 36718469Sphk MALLOC(cp, caddr_t, uap->len, M_KTRACE, M_WAITOK); 36818398Sphk if (!copyin(uap->addr, cp, uap->len)) { 36965556Sjasone kth->ktr_buffer = cp; 37018469Sphk kth->ktr_len = uap->len; 37162378Sgreen ktrwrite(p->p_tracep, kth, NULL); 37218398Sphk } 37318398Sphk FREE(kth, M_KTRACE); 37418469Sphk FREE(cp, M_KTRACE); 37518398Sphk p->p_traceflag &= ~KTRFAC_ACTIVE; 37618398Sphk 37718398Sphk return (0); 37818398Sphk#else 37918398Sphk return (ENOSYS); 38018398Sphk#endif 38118398Sphk} 38218398Sphk 38318398Sphk#ifdef KTRACE 38412819Sphkstatic int 3851541Srgrimesktrops(curp, p, ops, facs, vp) 3861541Srgrimes struct proc *p, *curp; 3871541Srgrimes int ops, facs; 3881541Srgrimes struct vnode *vp; 3891541Srgrimes{ 3901541Srgrimes 3911541Srgrimes if (!ktrcanset(curp, p)) 3921541Srgrimes return (0); 3931541Srgrimes if (ops == KTROP_SET) { 3948876Srgrimes if (p->p_tracep != vp) { 3951541Srgrimes /* 3961541Srgrimes * if trace file already in use, relinquish 3971541Srgrimes */ 3981541Srgrimes if (p->p_tracep != NULL) 3991541Srgrimes vrele(p->p_tracep); 4001541Srgrimes VREF(vp); 4011541Srgrimes p->p_tracep = vp; 4021541Srgrimes } 4031541Srgrimes p->p_traceflag |= facs; 4041541Srgrimes if (curp->p_ucred->cr_uid == 0) 4051541Srgrimes p->p_traceflag |= KTRFAC_ROOT; 4068876Srgrimes } else { 4071541Srgrimes /* KTROP_CLEAR */ 4081541Srgrimes if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 4091541Srgrimes /* no more tracing */ 4101541Srgrimes p->p_traceflag = 0; 4111541Srgrimes if (p->p_tracep != NULL) { 4121541Srgrimes vrele(p->p_tracep); 4131541Srgrimes p->p_tracep = NULL; 4141541Srgrimes } 4151541Srgrimes } 4161541Srgrimes } 4171541Srgrimes 4181541Srgrimes return (1); 4191541Srgrimes} 4201541Srgrimes 42112819Sphkstatic int 4221541Srgrimesktrsetchildren(curp, top, ops, facs, vp) 4231541Srgrimes struct proc *curp, *top; 4241541Srgrimes int ops, facs; 4251541Srgrimes struct vnode *vp; 4261541Srgrimes{ 4271541Srgrimes register struct proc *p; 4281541Srgrimes register int ret = 0; 4291541Srgrimes 4301541Srgrimes p = top; 43170317Sjake PROCTREE_LOCK(PT_SHARED); 4321541Srgrimes for (;;) { 4331541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 4341541Srgrimes /* 4351541Srgrimes * If this process has children, descend to them next, 4361541Srgrimes * otherwise do any siblings, and if done with this level, 4371541Srgrimes * follow back up the tree (but not past top). 4381541Srgrimes */ 43953212Sphk if (!LIST_EMPTY(&p->p_children)) 44053212Sphk p = LIST_FIRST(&p->p_children); 4411541Srgrimes else for (;;) { 44270317Sjake if (p == top) { 44370317Sjake PROCTREE_LOCK(PT_RELEASE); 4441541Srgrimes return (ret); 44570317Sjake } 44653212Sphk if (LIST_NEXT(p, p_sibling)) { 44753212Sphk p = LIST_NEXT(p, p_sibling); 4481541Srgrimes break; 4491541Srgrimes } 45014529Shsu p = p->p_pptr; 4511541Srgrimes } 4521541Srgrimes } 4531541Srgrimes /*NOTREACHED*/ 4541541Srgrimes} 4551541Srgrimes 45612819Sphkstatic void 45762378Sgreenktrwrite(vp, kth, uio) 4581541Srgrimes struct vnode *vp; 4591541Srgrimes register struct ktr_header *kth; 46062378Sgreen struct uio *uio; 4611541Srgrimes{ 4621541Srgrimes struct uio auio; 4631541Srgrimes struct iovec aiov[2]; 46462976Smckusick struct proc *p = curproc; /* XXX */ 46562976Smckusick struct mount *mp; 4661541Srgrimes int error; 4671541Srgrimes 4681541Srgrimes if (vp == NULL) 4691541Srgrimes return; 4701541Srgrimes auio.uio_iov = &aiov[0]; 4711541Srgrimes auio.uio_offset = 0; 4721541Srgrimes auio.uio_segflg = UIO_SYSSPACE; 4731541Srgrimes auio.uio_rw = UIO_WRITE; 4741541Srgrimes aiov[0].iov_base = (caddr_t)kth; 4751541Srgrimes aiov[0].iov_len = sizeof(struct ktr_header); 4761541Srgrimes auio.uio_resid = sizeof(struct ktr_header); 4771541Srgrimes auio.uio_iovcnt = 1; 47841628Srvb auio.uio_procp = curproc; 4791541Srgrimes if (kth->ktr_len > 0) { 4801541Srgrimes auio.uio_iovcnt++; 48165556Sjasone aiov[1].iov_base = kth->ktr_buffer; 4821541Srgrimes aiov[1].iov_len = kth->ktr_len; 4831541Srgrimes auio.uio_resid += kth->ktr_len; 48462378Sgreen if (uio != NULL) 48562378Sgreen kth->ktr_len += uio->uio_resid; 4861541Srgrimes } 48762976Smckusick vn_start_write(vp, &mp, V_WAIT); 48822521Sdyson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 48962378Sgreen (void)VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 49062378Sgreen error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, p->p_ucred); 49162378Sgreen if (error == 0 && uio != NULL) { 49262378Sgreen (void)VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 49362378Sgreen error = VOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, p->p_ucred); 49462378Sgreen } 49522521Sdyson VOP_UNLOCK(vp, 0, p); 49662976Smckusick vn_finished_write(mp); 4971541Srgrimes if (!error) 4981541Srgrimes return; 4991541Srgrimes /* 5001541Srgrimes * If error encountered, give up tracing on this vnode. 5011541Srgrimes */ 5021541Srgrimes log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", 5031541Srgrimes error); 50469947Sjake ALLPROC_LOCK(AP_SHARED); 50553212Sphk LIST_FOREACH(p, &allproc, p_list) { 5061541Srgrimes if (p->p_tracep == vp) { 5071541Srgrimes p->p_tracep = NULL; 5081541Srgrimes p->p_traceflag = 0; 5091541Srgrimes vrele(vp); 5101541Srgrimes } 5111541Srgrimes } 51269947Sjake ALLPROC_LOCK(AP_RELEASE); 5131541Srgrimes} 5141541Srgrimes 5151541Srgrimes/* 5161541Srgrimes * Return true if caller has permission to set the ktracing state 5171541Srgrimes * of target. Essentially, the target can't possess any 5181541Srgrimes * more permissions than the caller. KTRFAC_ROOT signifies that 5198876Srgrimes * root previously set the tracing status on the target process, and 5201541Srgrimes * so, only root may further change it. 5211541Srgrimes * 52265237Srwatson * XXX: These checks are stronger than for ptrace() 52365237Srwatson * 5241541Srgrimes * TODO: check groups. use caller effective gid. 5251541Srgrimes */ 52612819Sphkstatic int 5271541Srgrimesktrcanset(callp, targetp) 5281541Srgrimes struct proc *callp, *targetp; 5291541Srgrimes{ 5301541Srgrimes register struct pcred *caller = callp->p_cred; 5311541Srgrimes register struct pcred *target = targetp->p_cred; 5321541Srgrimes 53346155Sphk if (!PRISON_CHECK(callp, targetp)) 53446155Sphk return (0); 5351541Srgrimes if ((caller->pc_ucred->cr_uid == target->p_ruid && 5361541Srgrimes target->p_ruid == target->p_svuid && 5371541Srgrimes caller->p_rgid == target->p_rgid && /* XXX */ 5381541Srgrimes target->p_rgid == target->p_svgid && 5391541Srgrimes (targetp->p_traceflag & KTRFAC_ROOT) == 0) || 5401541Srgrimes caller->pc_ucred->cr_uid == 0) 5411541Srgrimes return (1); 5421541Srgrimes 5431541Srgrimes return (0); 5441541Srgrimes} 5451541Srgrimes 54613203Swollman#endif /* KTRACE */ 547