kern_ktrace.c revision 76166
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 76166 2001-05-01 08:13:21Z markm $ 351541Srgrimes */ 361541Srgrimes 3713203Swollman#include "opt_ktrace.h" 381541Srgrimes 391541Srgrimes#include <sys/param.h> 402112Swollman#include <sys/systm.h> 4176166Smarkm#include <sys/lock.h> 4276166Smarkm#include <sys/mutex.h> 4312221Sbde#include <sys/sysproto.h> 4441059Speter#include <sys/kernel.h> 451541Srgrimes#include <sys/proc.h> 4624131Sbde#include <sys/fcntl.h> 471541Srgrimes#include <sys/namei.h> 481541Srgrimes#include <sys/vnode.h> 491541Srgrimes#include <sys/ktrace.h> 501541Srgrimes#include <sys/malloc.h> 5174927Sjhb#include <sys/sx.h> 521541Srgrimes#include <sys/syslog.h> 5372786Srwatson#include <sys/jail.h> 541541Srgrimes 5530354Sphkstatic MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE"); 5630309Sphk 5713203Swollman#ifdef KTRACE 5812819Sphkstatic struct ktr_header *ktrgetheader __P((int type)); 5962378Sgreenstatic void ktrwrite __P((struct vnode *, struct ktr_header *, struct uio *)); 6012819Sphkstatic int ktrcanset __P((struct proc *,struct proc *)); 6112819Sphkstatic int ktrsetchildren __P((struct proc *,struct proc *,int,int,struct vnode *)); 6212819Sphkstatic int ktrops __P((struct proc *,struct proc *,int,int,struct vnode *)); 6312577Sbde 6412819Sphk 6512819Sphkstatic struct ktr_header * 661541Srgrimesktrgetheader(type) 671541Srgrimes int type; 681541Srgrimes{ 691541Srgrimes register struct ktr_header *kth; 701541Srgrimes struct proc *p = curproc; /* XXX */ 711541Srgrimes 728876Srgrimes MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 7317429Sphk M_KTRACE, M_WAITOK); 741541Srgrimes kth->ktr_type = type; 751541Srgrimes microtime(&kth->ktr_time); 761541Srgrimes kth->ktr_pid = p->p_pid; 7751484Smarcel bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN + 1); 781541Srgrimes return (kth); 791541Srgrimes} 801541Srgrimes 811549Srgrimesvoid 821541Srgrimesktrsyscall(vp, code, narg, args) 831541Srgrimes struct vnode *vp; 8447955Sdt int code, narg; 8547955Sdt register_t args[]; 861541Srgrimes{ 871541Srgrimes struct ktr_header *kth; 881541Srgrimes struct ktr_syscall *ktp; 8947955Sdt register int len = offsetof(struct ktr_syscall, ktr_args) + 9047955Sdt (narg * sizeof(register_t)); 911541Srgrimes struct proc *p = curproc; /* XXX */ 9247955Sdt register_t *argp; 9347955Sdt int i; 941541Srgrimes 951541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 961541Srgrimes kth = ktrgetheader(KTR_SYSCALL); 9717429Sphk MALLOC(ktp, struct ktr_syscall *, len, M_KTRACE, M_WAITOK); 981541Srgrimes ktp->ktr_code = code; 991541Srgrimes ktp->ktr_narg = narg; 10047955Sdt argp = &ktp->ktr_args[0]; 1011541Srgrimes for (i = 0; i < narg; i++) 1021541Srgrimes *argp++ = args[i]; 10365556Sjasone kth->ktr_buffer = (caddr_t)ktp; 1041541Srgrimes kth->ktr_len = len; 10562378Sgreen ktrwrite(vp, kth, NULL); 10617429Sphk FREE(ktp, M_KTRACE); 10717429Sphk FREE(kth, M_KTRACE); 1081541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1091541Srgrimes} 1101541Srgrimes 1111549Srgrimesvoid 1121541Srgrimesktrsysret(vp, code, error, retval) 1131541Srgrimes struct vnode *vp; 11447955Sdt int code, error; 11547955Sdt register_t retval; 1161541Srgrimes{ 1171541Srgrimes struct ktr_header *kth; 1181541Srgrimes struct ktr_sysret ktp; 1191541Srgrimes struct proc *p = curproc; /* XXX */ 1201541Srgrimes 1211541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1221541Srgrimes kth = ktrgetheader(KTR_SYSRET); 1231541Srgrimes ktp.ktr_code = code; 1241541Srgrimes ktp.ktr_error = error; 1251541Srgrimes ktp.ktr_retval = retval; /* what about val2 ? */ 1261541Srgrimes 12765556Sjasone kth->ktr_buffer = (caddr_t)&ktp; 1281541Srgrimes kth->ktr_len = sizeof(struct ktr_sysret); 1291541Srgrimes 13062378Sgreen ktrwrite(vp, kth, NULL); 13117429Sphk FREE(kth, M_KTRACE); 1321541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1331541Srgrimes} 1341541Srgrimes 1351549Srgrimesvoid 1361541Srgrimesktrnamei(vp, path) 1371541Srgrimes struct vnode *vp; 1381541Srgrimes char *path; 1391541Srgrimes{ 1401541Srgrimes struct ktr_header *kth; 1411541Srgrimes struct proc *p = curproc; /* XXX */ 1421541Srgrimes 1431541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1441541Srgrimes kth = ktrgetheader(KTR_NAMEI); 1451541Srgrimes kth->ktr_len = strlen(path); 14665556Sjasone kth->ktr_buffer = path; 1471541Srgrimes 14862378Sgreen ktrwrite(vp, kth, NULL); 14917429Sphk FREE(kth, M_KTRACE); 1501541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1511541Srgrimes} 1521541Srgrimes 1531549Srgrimesvoid 15462378Sgreenktrgenio(vp, fd, rw, uio, error) 1551541Srgrimes struct vnode *vp; 1561541Srgrimes int fd; 1571541Srgrimes enum uio_rw rw; 15862378Sgreen struct uio *uio; 15962378Sgreen int error; 1601541Srgrimes{ 1611541Srgrimes struct ktr_header *kth; 16262378Sgreen struct ktr_genio ktg; 1631541Srgrimes struct proc *p = curproc; /* XXX */ 1648876Srgrimes 1651541Srgrimes if (error) 1661541Srgrimes return; 1671541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1681541Srgrimes kth = ktrgetheader(KTR_GENIO); 16962378Sgreen ktg.ktr_fd = fd; 17062378Sgreen ktg.ktr_rw = rw; 17165556Sjasone kth->ktr_buffer = (caddr_t)&ktg; 17262378Sgreen kth->ktr_len = sizeof(struct ktr_genio); 17362378Sgreen uio->uio_offset = 0; 17462791Sgreen uio->uio_rw = UIO_WRITE; 1751541Srgrimes 17662378Sgreen ktrwrite(vp, kth, uio); 17717429Sphk FREE(kth, M_KTRACE); 1781541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1791541Srgrimes} 1801541Srgrimes 1811549Srgrimesvoid 1821541Srgrimesktrpsig(vp, sig, action, mask, code) 1831541Srgrimes struct vnode *vp; 18451941Smarcel int sig; 1851541Srgrimes sig_t action; 18651791Smarcel sigset_t *mask; 18751941Smarcel int code; 1881541Srgrimes{ 1891541Srgrimes struct ktr_header *kth; 1901541Srgrimes struct ktr_psig kp; 1911541Srgrimes struct proc *p = curproc; /* XXX */ 1921541Srgrimes 1931541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1941541Srgrimes kth = ktrgetheader(KTR_PSIG); 1951541Srgrimes kp.signo = (char)sig; 1961541Srgrimes kp.action = action; 19751791Smarcel kp.mask = *mask; 1981541Srgrimes kp.code = code; 19965556Sjasone kth->ktr_buffer = (caddr_t)&kp; 2001541Srgrimes kth->ktr_len = sizeof (struct ktr_psig); 2011541Srgrimes 20262378Sgreen ktrwrite(vp, kth, NULL); 20317429Sphk FREE(kth, M_KTRACE); 2041541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2051541Srgrimes} 2061541Srgrimes 2071549Srgrimesvoid 2081541Srgrimesktrcsw(vp, out, user) 2091541Srgrimes struct vnode *vp; 2101541Srgrimes int out, user; 2111541Srgrimes{ 2121541Srgrimes struct ktr_header *kth; 2131541Srgrimes struct ktr_csw kc; 2141541Srgrimes struct proc *p = curproc; /* XXX */ 2151541Srgrimes 2161541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 2171541Srgrimes kth = ktrgetheader(KTR_CSW); 2181541Srgrimes kc.out = out; 2191541Srgrimes kc.user = user; 22065556Sjasone kth->ktr_buffer = (caddr_t)&kc; 2211541Srgrimes kth->ktr_len = sizeof (struct ktr_csw); 2221541Srgrimes 22362378Sgreen ktrwrite(vp, kth, NULL); 22417429Sphk FREE(kth, M_KTRACE); 2251541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2261541Srgrimes} 22713203Swollman#endif 2281541Srgrimes 2291541Srgrimes/* Interface and common routines */ 2301541Srgrimes 2311541Srgrimes/* 2321541Srgrimes * ktrace system call 2331541Srgrimes */ 23412221Sbde#ifndef _SYS_SYSPROTO_H_ 2351541Srgrimesstruct ktrace_args { 2361541Srgrimes char *fname; 2371541Srgrimes int ops; 2381541Srgrimes int facs; 2391541Srgrimes int pid; 2401541Srgrimes}; 24112221Sbde#endif 2421541Srgrimes/* ARGSUSED */ 2431549Srgrimesint 24430994Sphkktrace(curp, uap) 2451541Srgrimes struct proc *curp; 2461541Srgrimes register struct ktrace_args *uap; 2471541Srgrimes{ 24813203Swollman#ifdef KTRACE 2491541Srgrimes register struct vnode *vp = NULL; 2501541Srgrimes register struct proc *p; 2511541Srgrimes struct pgrp *pg; 2521541Srgrimes int facs = uap->facs & ~KTRFAC_ROOT; 2531541Srgrimes int ops = KTROP(uap->ops); 2541541Srgrimes int descend = uap->ops & KTRFLAG_DESCEND; 2551541Srgrimes int ret = 0; 25662550Smckusick int flags, error = 0; 2571541Srgrimes struct nameidata nd; 2581541Srgrimes 2591541Srgrimes curp->p_traceflag |= KTRFAC_ACTIVE; 2601541Srgrimes if (ops != KTROP_CLEAR) { 2611541Srgrimes /* 2621541Srgrimes * an operation which requires a file argument. 2631541Srgrimes */ 26450668Sdima NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, curp); 26562550Smckusick flags = FREAD | FWRITE | O_NOFOLLOW; 26662550Smckusick error = vn_open(&nd, &flags, 0); 2673308Sphk if (error) { 2681541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 2691541Srgrimes return (error); 2701541Srgrimes } 27154655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 2721541Srgrimes vp = nd.ni_vp; 27322521Sdyson VOP_UNLOCK(vp, 0, curp); 2741541Srgrimes if (vp->v_type != VREG) { 2751541Srgrimes (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); 2761541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 2771541Srgrimes return (EACCES); 2781541Srgrimes } 2791541Srgrimes } 2801541Srgrimes /* 2811541Srgrimes * Clear all uses of the tracefile 2821541Srgrimes */ 2831541Srgrimes if (ops == KTROP_CLEARFILE) { 28474927Sjhb sx_slock(&allproc_lock); 28553212Sphk LIST_FOREACH(p, &allproc, p_list) { 2861541Srgrimes if (p->p_tracep == vp) { 2871541Srgrimes if (ktrcanset(curp, p)) { 2881541Srgrimes p->p_tracep = NULL; 2891541Srgrimes p->p_traceflag = 0; 2901541Srgrimes (void) vn_close(vp, FREAD|FWRITE, 2911541Srgrimes p->p_ucred, p); 2921541Srgrimes } else 2931541Srgrimes error = EPERM; 2941541Srgrimes } 2951541Srgrimes } 29674927Sjhb sx_sunlock(&allproc_lock); 2971541Srgrimes goto done; 2981541Srgrimes } 2991541Srgrimes /* 3001541Srgrimes * need something to (un)trace (XXX - why is this here?) 3011541Srgrimes */ 3021541Srgrimes if (!facs) { 3031541Srgrimes error = EINVAL; 3041541Srgrimes goto done; 3051541Srgrimes } 3068876Srgrimes /* 3071541Srgrimes * do it 3081541Srgrimes */ 3091541Srgrimes if (uap->pid < 0) { 3101541Srgrimes /* 3111541Srgrimes * by process group 3121541Srgrimes */ 3131541Srgrimes pg = pgfind(-uap->pid); 3141541Srgrimes if (pg == NULL) { 3151541Srgrimes error = ESRCH; 3161541Srgrimes goto done; 3171541Srgrimes } 31853212Sphk LIST_FOREACH(p, &pg->pg_members, p_pglist) 3191541Srgrimes if (descend) 3201541Srgrimes ret |= ktrsetchildren(curp, p, ops, facs, vp); 3218876Srgrimes else 3221541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 3231541Srgrimes } else { 3241541Srgrimes /* 3251541Srgrimes * by pid 3261541Srgrimes */ 3271541Srgrimes p = pfind(uap->pid); 3281541Srgrimes if (p == NULL) { 3291541Srgrimes error = ESRCH; 3301541Srgrimes goto done; 3311541Srgrimes } 33275893Sjhb PROC_UNLOCK(p); 3331541Srgrimes if (descend) 3341541Srgrimes ret |= ktrsetchildren(curp, p, ops, facs, vp); 3351541Srgrimes else 3361541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 3371541Srgrimes } 3381541Srgrimes if (!ret) 3391541Srgrimes error = EPERM; 3401541Srgrimesdone: 3411541Srgrimes if (vp != NULL) 3421541Srgrimes (void) vn_close(vp, FWRITE, curp->p_ucred, curp); 3431541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 3441541Srgrimes return (error); 34513203Swollman#else 34613203Swollman return ENOSYS; 34713203Swollman#endif 3481541Srgrimes} 3491541Srgrimes 35018398Sphk/* 35118398Sphk * utrace system call 35218398Sphk */ 35318398Sphk/* ARGSUSED */ 35418398Sphkint 35530994Sphkutrace(curp, uap) 35618398Sphk struct proc *curp; 35718398Sphk register struct utrace_args *uap; 35818398Sphk{ 35913203Swollman#ifdef KTRACE 36018398Sphk struct ktr_header *kth; 36118398Sphk struct proc *p = curproc; /* XXX */ 36218398Sphk register caddr_t cp; 36318398Sphk 36418398Sphk if (!KTRPOINT(p, KTR_USER)) 36518398Sphk return (0); 36670792Salfred if (uap->len > KTR_USER_MAXLEN) 36770707Salfred return (EINVAL); 36818398Sphk p->p_traceflag |= KTRFAC_ACTIVE; 36918398Sphk kth = ktrgetheader(KTR_USER); 37018469Sphk MALLOC(cp, caddr_t, uap->len, M_KTRACE, M_WAITOK); 37118398Sphk if (!copyin(uap->addr, cp, uap->len)) { 37265556Sjasone kth->ktr_buffer = cp; 37318469Sphk kth->ktr_len = uap->len; 37462378Sgreen ktrwrite(p->p_tracep, kth, NULL); 37518398Sphk } 37618398Sphk FREE(kth, M_KTRACE); 37718469Sphk FREE(cp, M_KTRACE); 37818398Sphk p->p_traceflag &= ~KTRFAC_ACTIVE; 37918398Sphk 38018398Sphk return (0); 38118398Sphk#else 38218398Sphk return (ENOSYS); 38318398Sphk#endif 38418398Sphk} 38518398Sphk 38618398Sphk#ifdef KTRACE 38712819Sphkstatic int 3881541Srgrimesktrops(curp, p, ops, facs, vp) 3891541Srgrimes struct proc *p, *curp; 3901541Srgrimes int ops, facs; 3911541Srgrimes struct vnode *vp; 3921541Srgrimes{ 3931541Srgrimes 3941541Srgrimes if (!ktrcanset(curp, p)) 3951541Srgrimes return (0); 3961541Srgrimes if (ops == KTROP_SET) { 3978876Srgrimes if (p->p_tracep != vp) { 3981541Srgrimes /* 3991541Srgrimes * if trace file already in use, relinquish 4001541Srgrimes */ 4011541Srgrimes if (p->p_tracep != NULL) 4021541Srgrimes vrele(p->p_tracep); 4031541Srgrimes VREF(vp); 4041541Srgrimes p->p_tracep = vp; 4051541Srgrimes } 4061541Srgrimes p->p_traceflag |= facs; 4071541Srgrimes if (curp->p_ucred->cr_uid == 0) 4081541Srgrimes p->p_traceflag |= KTRFAC_ROOT; 4098876Srgrimes } else { 4101541Srgrimes /* KTROP_CLEAR */ 4111541Srgrimes if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 4121541Srgrimes /* no more tracing */ 4131541Srgrimes p->p_traceflag = 0; 4141541Srgrimes if (p->p_tracep != NULL) { 4151541Srgrimes vrele(p->p_tracep); 4161541Srgrimes p->p_tracep = NULL; 4171541Srgrimes } 4181541Srgrimes } 4191541Srgrimes } 4201541Srgrimes 4211541Srgrimes return (1); 4221541Srgrimes} 4231541Srgrimes 42412819Sphkstatic int 4251541Srgrimesktrsetchildren(curp, top, ops, facs, vp) 4261541Srgrimes struct proc *curp, *top; 4271541Srgrimes int ops, facs; 4281541Srgrimes struct vnode *vp; 4291541Srgrimes{ 4301541Srgrimes register struct proc *p; 4311541Srgrimes register int ret = 0; 4321541Srgrimes 4331541Srgrimes p = top; 43474927Sjhb sx_slock(&proctree_lock); 4351541Srgrimes for (;;) { 4361541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 4371541Srgrimes /* 4381541Srgrimes * If this process has children, descend to them next, 4391541Srgrimes * otherwise do any siblings, and if done with this level, 4401541Srgrimes * follow back up the tree (but not past top). 4411541Srgrimes */ 44253212Sphk if (!LIST_EMPTY(&p->p_children)) 44353212Sphk p = LIST_FIRST(&p->p_children); 4441541Srgrimes else for (;;) { 44570317Sjake if (p == top) { 44674927Sjhb sx_sunlock(&proctree_lock); 4471541Srgrimes return (ret); 44870317Sjake } 44953212Sphk if (LIST_NEXT(p, p_sibling)) { 45053212Sphk p = LIST_NEXT(p, p_sibling); 4511541Srgrimes break; 4521541Srgrimes } 45314529Shsu p = p->p_pptr; 4541541Srgrimes } 4551541Srgrimes } 4561541Srgrimes /*NOTREACHED*/ 4571541Srgrimes} 4581541Srgrimes 45912819Sphkstatic void 46062378Sgreenktrwrite(vp, kth, uio) 4611541Srgrimes struct vnode *vp; 4621541Srgrimes register struct ktr_header *kth; 46362378Sgreen struct uio *uio; 4641541Srgrimes{ 4651541Srgrimes struct uio auio; 4661541Srgrimes struct iovec aiov[2]; 46762976Smckusick struct proc *p = curproc; /* XXX */ 46862976Smckusick struct mount *mp; 4691541Srgrimes int error; 4701541Srgrimes 4711541Srgrimes if (vp == NULL) 4721541Srgrimes return; 4731541Srgrimes auio.uio_iov = &aiov[0]; 4741541Srgrimes auio.uio_offset = 0; 4751541Srgrimes auio.uio_segflg = UIO_SYSSPACE; 4761541Srgrimes auio.uio_rw = UIO_WRITE; 4771541Srgrimes aiov[0].iov_base = (caddr_t)kth; 4781541Srgrimes aiov[0].iov_len = sizeof(struct ktr_header); 4791541Srgrimes auio.uio_resid = sizeof(struct ktr_header); 4801541Srgrimes auio.uio_iovcnt = 1; 48141628Srvb auio.uio_procp = curproc; 4821541Srgrimes if (kth->ktr_len > 0) { 4831541Srgrimes auio.uio_iovcnt++; 48465556Sjasone aiov[1].iov_base = kth->ktr_buffer; 4851541Srgrimes aiov[1].iov_len = kth->ktr_len; 4861541Srgrimes auio.uio_resid += kth->ktr_len; 48762378Sgreen if (uio != NULL) 48862378Sgreen kth->ktr_len += uio->uio_resid; 4891541Srgrimes } 49062976Smckusick vn_start_write(vp, &mp, V_WAIT); 49122521Sdyson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 49262378Sgreen (void)VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 49362378Sgreen error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, p->p_ucred); 49462378Sgreen if (error == 0 && uio != NULL) { 49562378Sgreen (void)VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 49662378Sgreen error = VOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, p->p_ucred); 49762378Sgreen } 49822521Sdyson VOP_UNLOCK(vp, 0, p); 49962976Smckusick vn_finished_write(mp); 5001541Srgrimes if (!error) 5011541Srgrimes return; 5021541Srgrimes /* 5031541Srgrimes * If error encountered, give up tracing on this vnode. 5041541Srgrimes */ 5051541Srgrimes log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", 5061541Srgrimes error); 50774927Sjhb sx_slock(&allproc_lock); 50853212Sphk LIST_FOREACH(p, &allproc, p_list) { 5091541Srgrimes if (p->p_tracep == vp) { 5101541Srgrimes p->p_tracep = NULL; 5111541Srgrimes p->p_traceflag = 0; 5121541Srgrimes vrele(vp); 5131541Srgrimes } 5141541Srgrimes } 51574927Sjhb sx_sunlock(&allproc_lock); 5161541Srgrimes} 5171541Srgrimes 5181541Srgrimes/* 5191541Srgrimes * Return true if caller has permission to set the ktracing state 5201541Srgrimes * of target. Essentially, the target can't possess any 5211541Srgrimes * more permissions than the caller. KTRFAC_ROOT signifies that 5228876Srgrimes * root previously set the tracing status on the target process, and 5231541Srgrimes * so, only root may further change it. 5241541Srgrimes * 52565237Srwatson * XXX: These checks are stronger than for ptrace() 52672786Srwatson * XXX: This check should be p_can(... P_CAN_DEBUG ...); 52765237Srwatson * 5281541Srgrimes * TODO: check groups. use caller effective gid. 5291541Srgrimes */ 53012819Sphkstatic int 5311541Srgrimesktrcanset(callp, targetp) 5321541Srgrimes struct proc *callp, *targetp; 5331541Srgrimes{ 5341541Srgrimes register struct pcred *caller = callp->p_cred; 5351541Srgrimes register struct pcred *target = targetp->p_cred; 5361541Srgrimes 53772786Srwatson if (prison_check(callp->p_ucred, targetp->p_ucred)) 53846155Sphk return (0); 5391541Srgrimes if ((caller->pc_ucred->cr_uid == target->p_ruid && 5401541Srgrimes target->p_ruid == target->p_svuid && 5411541Srgrimes caller->p_rgid == target->p_rgid && /* XXX */ 5421541Srgrimes target->p_rgid == target->p_svgid && 5431541Srgrimes (targetp->p_traceflag & KTRFAC_ROOT) == 0) || 5441541Srgrimes caller->pc_ucred->cr_uid == 0) 5451541Srgrimes return (1); 5461541Srgrimes 5471541Srgrimes return (0); 5481541Srgrimes} 5491541Srgrimes 55013203Swollman#endif /* KTRACE */ 551