kern_ktrace.c revision 94861
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 94861 2002-04-16 17:11:34Z jhb $ 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 5892723Salfredstatic struct ktr_header *ktrgetheader(int type); 5992723Salfredstatic void ktrwrite(struct vnode *, struct ktr_header *, struct uio *); 6094618Sjhbstatic int ktrcanset(struct thread *, struct proc *); 6194618Sjhbstatic int ktrsetchildren(struct thread *, struct proc *, int, int, struct vnode *); 6294618Sjhbstatic int ktrops(struct thread *, 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 8182585Sdillon/* 8282585Sdillon * MPSAFE 8382585Sdillon */ 841549Srgrimesvoid 851541Srgrimesktrsyscall(vp, code, narg, args) 861541Srgrimes struct vnode *vp; 8747955Sdt int code, narg; 8847955Sdt register_t args[]; 891541Srgrimes{ 901541Srgrimes struct ktr_header *kth; 911541Srgrimes struct ktr_syscall *ktp; 9247955Sdt register int len = offsetof(struct ktr_syscall, ktr_args) + 9347955Sdt (narg * sizeof(register_t)); 941541Srgrimes struct proc *p = curproc; /* XXX */ 9547955Sdt register_t *argp; 9647955Sdt int i; 971541Srgrimes 9882585Sdillon mtx_lock(&Giant); 991541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1001541Srgrimes kth = ktrgetheader(KTR_SYSCALL); 10117429Sphk MALLOC(ktp, struct ktr_syscall *, len, M_KTRACE, M_WAITOK); 1021541Srgrimes ktp->ktr_code = code; 1031541Srgrimes ktp->ktr_narg = narg; 10447955Sdt argp = &ktp->ktr_args[0]; 1051541Srgrimes for (i = 0; i < narg; i++) 1061541Srgrimes *argp++ = args[i]; 10765556Sjasone kth->ktr_buffer = (caddr_t)ktp; 1081541Srgrimes kth->ktr_len = len; 10962378Sgreen ktrwrite(vp, kth, NULL); 11017429Sphk FREE(ktp, M_KTRACE); 11117429Sphk FREE(kth, M_KTRACE); 1121541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 11382585Sdillon mtx_unlock(&Giant); 1141541Srgrimes} 1151541Srgrimes 11682585Sdillon/* 11782585Sdillon * MPSAFE 11882585Sdillon */ 1191549Srgrimesvoid 1201541Srgrimesktrsysret(vp, code, error, retval) 1211541Srgrimes struct vnode *vp; 12247955Sdt int code, error; 12347955Sdt register_t retval; 1241541Srgrimes{ 1251541Srgrimes struct ktr_header *kth; 1261541Srgrimes struct ktr_sysret ktp; 1271541Srgrimes struct proc *p = curproc; /* XXX */ 1281541Srgrimes 12982585Sdillon mtx_lock(&Giant); 1301541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1311541Srgrimes kth = ktrgetheader(KTR_SYSRET); 1321541Srgrimes ktp.ktr_code = code; 1331541Srgrimes ktp.ktr_error = error; 1341541Srgrimes ktp.ktr_retval = retval; /* what about val2 ? */ 1351541Srgrimes 13665556Sjasone kth->ktr_buffer = (caddr_t)&ktp; 1371541Srgrimes kth->ktr_len = sizeof(struct ktr_sysret); 1381541Srgrimes 13962378Sgreen ktrwrite(vp, kth, NULL); 14017429Sphk FREE(kth, M_KTRACE); 1411541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 14282585Sdillon mtx_unlock(&Giant); 1431541Srgrimes} 1441541Srgrimes 1451549Srgrimesvoid 1461541Srgrimesktrnamei(vp, path) 1471541Srgrimes struct vnode *vp; 1481541Srgrimes char *path; 1491541Srgrimes{ 1501541Srgrimes struct ktr_header *kth; 1511541Srgrimes struct proc *p = curproc; /* XXX */ 1521541Srgrimes 15385397Sdillon /* 15485397Sdillon * don't let p_tracep get ripped out from under us 15585397Sdillon */ 15685397Sdillon if (vp) 15785397Sdillon VREF(vp); 1581541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1591541Srgrimes kth = ktrgetheader(KTR_NAMEI); 1601541Srgrimes kth->ktr_len = strlen(path); 16165556Sjasone kth->ktr_buffer = path; 1621541Srgrimes 16362378Sgreen ktrwrite(vp, kth, NULL); 16485397Sdillon if (vp) 16585397Sdillon vrele(vp); 16617429Sphk FREE(kth, M_KTRACE); 1671541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 1681541Srgrimes} 1691541Srgrimes 1701549Srgrimesvoid 17162378Sgreenktrgenio(vp, fd, rw, uio, error) 1721541Srgrimes struct vnode *vp; 1731541Srgrimes int fd; 1741541Srgrimes enum uio_rw rw; 17562378Sgreen struct uio *uio; 17662378Sgreen int error; 1771541Srgrimes{ 1781541Srgrimes struct ktr_header *kth; 17962378Sgreen struct ktr_genio ktg; 1801541Srgrimes struct proc *p = curproc; /* XXX */ 1818876Srgrimes 1821541Srgrimes if (error) 1831541Srgrimes return; 18492310Salfred 18592310Salfred mtx_lock(&Giant); 18685397Sdillon /* 18785397Sdillon * don't let p_tracep get ripped out from under us 18885397Sdillon */ 18985397Sdillon if (vp) 19085397Sdillon VREF(vp); 1911541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1921541Srgrimes kth = ktrgetheader(KTR_GENIO); 19362378Sgreen ktg.ktr_fd = fd; 19462378Sgreen ktg.ktr_rw = rw; 19565556Sjasone kth->ktr_buffer = (caddr_t)&ktg; 19662378Sgreen kth->ktr_len = sizeof(struct ktr_genio); 19762378Sgreen uio->uio_offset = 0; 19862791Sgreen uio->uio_rw = UIO_WRITE; 1991541Srgrimes 20062378Sgreen ktrwrite(vp, kth, uio); 20185397Sdillon if (vp) 20285397Sdillon vrele(vp); 20317429Sphk FREE(kth, M_KTRACE); 2041541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 20592310Salfred mtx_unlock(&Giant); 2061541Srgrimes} 2071541Srgrimes 2081549Srgrimesvoid 2091541Srgrimesktrpsig(vp, sig, action, mask, code) 2101541Srgrimes struct vnode *vp; 21151941Smarcel int sig; 2121541Srgrimes sig_t action; 21351791Smarcel sigset_t *mask; 21451941Smarcel int code; 2151541Srgrimes{ 2161541Srgrimes struct ktr_header *kth; 2171541Srgrimes struct ktr_psig kp; 2181541Srgrimes struct proc *p = curproc; /* XXX */ 2191541Srgrimes 22085397Sdillon /* 22185397Sdillon * don't let vp get ripped out from under us 22285397Sdillon */ 22385397Sdillon if (vp) 22485397Sdillon VREF(vp); 2251541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 2261541Srgrimes kth = ktrgetheader(KTR_PSIG); 2271541Srgrimes kp.signo = (char)sig; 2281541Srgrimes kp.action = action; 22951791Smarcel kp.mask = *mask; 2301541Srgrimes kp.code = code; 23165556Sjasone kth->ktr_buffer = (caddr_t)&kp; 2321541Srgrimes kth->ktr_len = sizeof (struct ktr_psig); 2331541Srgrimes 23462378Sgreen ktrwrite(vp, kth, NULL); 23585397Sdillon if (vp) 23685397Sdillon vrele(vp); 23717429Sphk FREE(kth, M_KTRACE); 2381541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2391541Srgrimes} 2401541Srgrimes 2411549Srgrimesvoid 2421541Srgrimesktrcsw(vp, out, user) 2431541Srgrimes struct vnode *vp; 2441541Srgrimes int out, user; 2451541Srgrimes{ 2461541Srgrimes struct ktr_header *kth; 2471541Srgrimes struct ktr_csw kc; 2481541Srgrimes struct proc *p = curproc; /* XXX */ 2491541Srgrimes 25085397Sdillon /* 25185397Sdillon * don't let vp get ripped out from under us 25285397Sdillon */ 25385397Sdillon if (vp) 25485397Sdillon VREF(vp); 2551541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 2561541Srgrimes kth = ktrgetheader(KTR_CSW); 2571541Srgrimes kc.out = out; 2581541Srgrimes kc.user = user; 25965556Sjasone kth->ktr_buffer = (caddr_t)&kc; 2601541Srgrimes kth->ktr_len = sizeof (struct ktr_csw); 2611541Srgrimes 26262378Sgreen ktrwrite(vp, kth, NULL); 26385397Sdillon if (vp) 26485397Sdillon vrele(vp); 26517429Sphk FREE(kth, M_KTRACE); 2661541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2671541Srgrimes} 26813203Swollman#endif 2691541Srgrimes 2701541Srgrimes/* Interface and common routines */ 2711541Srgrimes 2721541Srgrimes/* 2731541Srgrimes * ktrace system call 2741541Srgrimes */ 27512221Sbde#ifndef _SYS_SYSPROTO_H_ 2761541Srgrimesstruct ktrace_args { 2771541Srgrimes char *fname; 2781541Srgrimes int ops; 2791541Srgrimes int facs; 2801541Srgrimes int pid; 2811541Srgrimes}; 28212221Sbde#endif 2831541Srgrimes/* ARGSUSED */ 2841549Srgrimesint 28583366Sjulianktrace(td, uap) 28683366Sjulian struct thread *td; 2871541Srgrimes register struct ktrace_args *uap; 2881541Srgrimes{ 28913203Swollman#ifdef KTRACE 29083366Sjulian struct proc *curp = td->td_proc; 2911541Srgrimes register struct vnode *vp = NULL; 2921541Srgrimes register struct proc *p; 2931541Srgrimes struct pgrp *pg; 2941541Srgrimes int facs = uap->facs & ~KTRFAC_ROOT; 2951541Srgrimes int ops = KTROP(uap->ops); 2961541Srgrimes int descend = uap->ops & KTRFLAG_DESCEND; 2971541Srgrimes int ret = 0; 29862550Smckusick int flags, error = 0; 2991541Srgrimes struct nameidata nd; 3001541Srgrimes 3011541Srgrimes curp->p_traceflag |= KTRFAC_ACTIVE; 3021541Srgrimes if (ops != KTROP_CLEAR) { 3031541Srgrimes /* 3041541Srgrimes * an operation which requires a file argument. 3051541Srgrimes */ 30683366Sjulian NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, td); 30762550Smckusick flags = FREAD | FWRITE | O_NOFOLLOW; 30862550Smckusick error = vn_open(&nd, &flags, 0); 3093308Sphk if (error) { 3101541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 3111541Srgrimes return (error); 3121541Srgrimes } 31354655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 3141541Srgrimes vp = nd.ni_vp; 31583366Sjulian VOP_UNLOCK(vp, 0, td); 3161541Srgrimes if (vp->v_type != VREG) { 31791406Sjhb (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); 3181541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 3191541Srgrimes return (EACCES); 3201541Srgrimes } 3211541Srgrimes } 3221541Srgrimes /* 32385397Sdillon * Clear all uses of the tracefile. 3241541Srgrimes */ 3251541Srgrimes if (ops == KTROP_CLEARFILE) { 32674927Sjhb sx_slock(&allproc_lock); 32753212Sphk LIST_FOREACH(p, &allproc, p_list) { 32894618Sjhb PROC_LOCK(p); 3291541Srgrimes if (p->p_tracep == vp) { 33094618Sjhb if (ktrcanset(td, p) && p->p_tracep == vp) { 3311541Srgrimes p->p_tracep = NULL; 3321541Srgrimes p->p_traceflag = 0; 33394618Sjhb PROC_UNLOCK(p); 3341541Srgrimes (void) vn_close(vp, FREAD|FWRITE, 33591406Sjhb td->td_ucred, td); 33685397Sdillon } else { 33794618Sjhb PROC_UNLOCK(p); 3381541Srgrimes error = EPERM; 33985397Sdillon } 34094618Sjhb } else 34194618Sjhb PROC_UNLOCK(p); 3421541Srgrimes } 34374927Sjhb sx_sunlock(&allproc_lock); 3441541Srgrimes goto done; 3451541Srgrimes } 3461541Srgrimes /* 3471541Srgrimes * need something to (un)trace (XXX - why is this here?) 3481541Srgrimes */ 3491541Srgrimes if (!facs) { 3501541Srgrimes error = EINVAL; 3511541Srgrimes goto done; 3521541Srgrimes } 3538876Srgrimes /* 3541541Srgrimes * do it 3551541Srgrimes */ 3561541Srgrimes if (uap->pid < 0) { 3571541Srgrimes /* 3581541Srgrimes * by process group 3591541Srgrimes */ 36094861Sjhb sx_slock(&proctree_lock); 3611541Srgrimes pg = pgfind(-uap->pid); 3621541Srgrimes if (pg == NULL) { 36394861Sjhb sx_sunlock(&proctree_lock); 3641541Srgrimes error = ESRCH; 3651541Srgrimes goto done; 3661541Srgrimes } 36791140Stanimura /* 36891140Stanimura * ktrops() may call vrele(). Lock pg_members 36994861Sjhb * by the proctree_lock rather than pg_mtx. 37091140Stanimura */ 37191140Stanimura PGRP_UNLOCK(pg); 37253212Sphk LIST_FOREACH(p, &pg->pg_members, p_pglist) 3731541Srgrimes if (descend) 37494618Sjhb ret |= ktrsetchildren(td, p, ops, facs, vp); 3758876Srgrimes else 37694618Sjhb ret |= ktrops(td, p, ops, facs, vp); 37794861Sjhb sx_sunlock(&proctree_lock); 3781541Srgrimes } else { 3791541Srgrimes /* 3801541Srgrimes * by pid 3811541Srgrimes */ 3821541Srgrimes p = pfind(uap->pid); 3831541Srgrimes if (p == NULL) { 3841541Srgrimes error = ESRCH; 3851541Srgrimes goto done; 3861541Srgrimes } 38775893Sjhb PROC_UNLOCK(p); 38894618Sjhb /* XXX: UNLOCK above has a race */ 3891541Srgrimes if (descend) 39094618Sjhb ret |= ktrsetchildren(td, p, ops, facs, vp); 3911541Srgrimes else 39294618Sjhb ret |= ktrops(td, p, ops, facs, vp); 3931541Srgrimes } 3941541Srgrimes if (!ret) 3951541Srgrimes error = EPERM; 3961541Srgrimesdone: 3971541Srgrimes if (vp != NULL) 39891406Sjhb (void) vn_close(vp, FWRITE, td->td_ucred, td); 3991541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 4001541Srgrimes return (error); 40113203Swollman#else 40213203Swollman return ENOSYS; 40313203Swollman#endif 4041541Srgrimes} 4051541Srgrimes 40618398Sphk/* 40718398Sphk * utrace system call 40818398Sphk */ 40918398Sphk/* ARGSUSED */ 41018398Sphkint 41183366Sjulianutrace(td, uap) 41283366Sjulian struct thread *td; 41318398Sphk register struct utrace_args *uap; 41418398Sphk{ 41583366Sjulian 41613203Swollman#ifdef KTRACE 41718398Sphk struct ktr_header *kth; 41818398Sphk struct proc *p = curproc; /* XXX */ 41985397Sdillon struct vnode *vp; 42018398Sphk register caddr_t cp; 42118398Sphk 42218398Sphk if (!KTRPOINT(p, KTR_USER)) 42318398Sphk return (0); 42470792Salfred if (uap->len > KTR_USER_MAXLEN) 42570707Salfred return (EINVAL); 42618398Sphk p->p_traceflag |= KTRFAC_ACTIVE; 42785397Sdillon if ((vp = p->p_tracep) != NULL) 42885397Sdillon VREF(vp); 42918398Sphk kth = ktrgetheader(KTR_USER); 43018469Sphk MALLOC(cp, caddr_t, uap->len, M_KTRACE, M_WAITOK); 43118398Sphk if (!copyin(uap->addr, cp, uap->len)) { 43265556Sjasone kth->ktr_buffer = cp; 43318469Sphk kth->ktr_len = uap->len; 43485397Sdillon ktrwrite(vp, kth, NULL); 43518398Sphk } 43685397Sdillon if (vp) 43785397Sdillon vrele(vp); 43818398Sphk FREE(kth, M_KTRACE); 43918469Sphk FREE(cp, M_KTRACE); 44018398Sphk p->p_traceflag &= ~KTRFAC_ACTIVE; 44118398Sphk 44218398Sphk return (0); 44318398Sphk#else 44418398Sphk return (ENOSYS); 44518398Sphk#endif 44618398Sphk} 44718398Sphk 44818398Sphk#ifdef KTRACE 44912819Sphkstatic int 45094618Sjhbktrops(td, p, ops, facs, vp) 45194618Sjhb struct thread *td; 45294618Sjhb struct proc *p; 4531541Srgrimes int ops, facs; 4541541Srgrimes struct vnode *vp; 4551541Srgrimes{ 45694618Sjhb struct vnode *vtmp = NULL, *newvp = NULL; 4571541Srgrimes 45894618Sjhb PROC_LOCK(p); 45994618Sjhb if (!ktrcanset(td, p)) { 46094618Sjhb PROC_UNLOCK(p); 4611541Srgrimes return (0); 46294618Sjhb } 4631541Srgrimes if (ops == KTROP_SET) { 4648876Srgrimes if (p->p_tracep != vp) { 46585397Sdillon struct vnode *vtmp; 46685397Sdillon 4671541Srgrimes /* 46894618Sjhb * if trace file already in use, relinquish below 4691541Srgrimes */ 47094618Sjhb newvp = vp; 47194618Sjhb vtmp = p->p_tracep; 47294618Sjhb p->p_tracep = NULL; 4731541Srgrimes } 4741541Srgrimes p->p_traceflag |= facs; 47594618Sjhb if (td->td_ucred->cr_uid == 0) 4761541Srgrimes p->p_traceflag |= KTRFAC_ROOT; 4778876Srgrimes } else { 4781541Srgrimes /* KTROP_CLEAR */ 4791541Srgrimes if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 48085397Sdillon struct vnode *vtmp; 48185397Sdillon 4821541Srgrimes /* no more tracing */ 4831541Srgrimes p->p_traceflag = 0; 48494618Sjhb vtmp = p->p_tracep; 48594618Sjhb p->p_tracep = NULL; 4861541Srgrimes } 4871541Srgrimes } 48894618Sjhb PROC_UNLOCK(p); 4891541Srgrimes 49094618Sjhb /* Release old trace file if requested. */ 49194618Sjhb if (vtmp != NULL) 49294618Sjhb vrele(vtmp); 49394618Sjhb 49494618Sjhb /* Setup new trace file if requested. */ 49594618Sjhb /* 49694618Sjhb * XXX: Doing this before the PROC_UNLOCK above would result in 49794618Sjhb * fewer lock operations but would break old behavior where the 49894618Sjhb * above vrele() would not be traced when changing trace files. 49994618Sjhb */ 50094618Sjhb if (newvp != NULL) { 50194618Sjhb VREF(newvp); 50294618Sjhb PROC_LOCK(p); 50394618Sjhb p->p_tracep = newvp; 50494618Sjhb PROC_UNLOCK(p); 50594618Sjhb } 50694618Sjhb 5071541Srgrimes return (1); 5081541Srgrimes} 5091541Srgrimes 51012819Sphkstatic int 51194618Sjhbktrsetchildren(td, top, ops, facs, vp) 51294618Sjhb struct thread *td; 51394618Sjhb struct proc *top; 5141541Srgrimes int ops, facs; 5151541Srgrimes struct vnode *vp; 5161541Srgrimes{ 5171541Srgrimes register struct proc *p; 5181541Srgrimes register int ret = 0; 5191541Srgrimes 5201541Srgrimes p = top; 52174927Sjhb sx_slock(&proctree_lock); 5221541Srgrimes for (;;) { 52394618Sjhb ret |= ktrops(td, p, ops, facs, vp); 5241541Srgrimes /* 5251541Srgrimes * If this process has children, descend to them next, 5261541Srgrimes * otherwise do any siblings, and if done with this level, 5271541Srgrimes * follow back up the tree (but not past top). 5281541Srgrimes */ 52953212Sphk if (!LIST_EMPTY(&p->p_children)) 53053212Sphk p = LIST_FIRST(&p->p_children); 5311541Srgrimes else for (;;) { 53270317Sjake if (p == top) { 53374927Sjhb sx_sunlock(&proctree_lock); 5341541Srgrimes return (ret); 53570317Sjake } 53653212Sphk if (LIST_NEXT(p, p_sibling)) { 53753212Sphk p = LIST_NEXT(p, p_sibling); 5381541Srgrimes break; 5391541Srgrimes } 54014529Shsu p = p->p_pptr; 5411541Srgrimes } 5421541Srgrimes } 5431541Srgrimes /*NOTREACHED*/ 5441541Srgrimes} 5451541Srgrimes 54612819Sphkstatic void 54762378Sgreenktrwrite(vp, kth, uio) 5481541Srgrimes struct vnode *vp; 5491541Srgrimes register struct ktr_header *kth; 55062378Sgreen struct uio *uio; 5511541Srgrimes{ 5521541Srgrimes struct uio auio; 5531541Srgrimes struct iovec aiov[2]; 55483366Sjulian struct thread *td = curthread; /* XXX */ 55583366Sjulian struct proc *p = td->td_proc; /* XXX */ 55662976Smckusick struct mount *mp; 5571541Srgrimes int error; 5581541Srgrimes 5591541Srgrimes if (vp == NULL) 5601541Srgrimes return; 5611541Srgrimes auio.uio_iov = &aiov[0]; 5621541Srgrimes auio.uio_offset = 0; 5631541Srgrimes auio.uio_segflg = UIO_SYSSPACE; 5641541Srgrimes auio.uio_rw = UIO_WRITE; 5651541Srgrimes aiov[0].iov_base = (caddr_t)kth; 5661541Srgrimes aiov[0].iov_len = sizeof(struct ktr_header); 5671541Srgrimes auio.uio_resid = sizeof(struct ktr_header); 5681541Srgrimes auio.uio_iovcnt = 1; 56983366Sjulian auio.uio_td = curthread; 5701541Srgrimes if (kth->ktr_len > 0) { 5711541Srgrimes auio.uio_iovcnt++; 57265556Sjasone aiov[1].iov_base = kth->ktr_buffer; 5731541Srgrimes aiov[1].iov_len = kth->ktr_len; 5741541Srgrimes auio.uio_resid += kth->ktr_len; 57562378Sgreen if (uio != NULL) 57662378Sgreen kth->ktr_len += uio->uio_resid; 5771541Srgrimes } 57862976Smckusick vn_start_write(vp, &mp, V_WAIT); 57983366Sjulian vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 58091406Sjhb (void)VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 58191406Sjhb error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, td->td_ucred); 58262378Sgreen if (error == 0 && uio != NULL) { 58391406Sjhb (void)VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 58491406Sjhb error = VOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, td->td_ucred); 58562378Sgreen } 58683366Sjulian VOP_UNLOCK(vp, 0, td); 58762976Smckusick vn_finished_write(mp); 5881541Srgrimes if (!error) 5891541Srgrimes return; 5901541Srgrimes /* 59185397Sdillon * If error encountered, give up tracing on this vnode. XXX what 59285397Sdillon * happens to the loop if vrele() blocks? 5931541Srgrimes */ 5941541Srgrimes log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", 5951541Srgrimes error); 59674927Sjhb sx_slock(&allproc_lock); 59753212Sphk LIST_FOREACH(p, &allproc, p_list) { 5981541Srgrimes if (p->p_tracep == vp) { 5991541Srgrimes p->p_tracep = NULL; 6001541Srgrimes p->p_traceflag = 0; 6011541Srgrimes vrele(vp); 6021541Srgrimes } 6031541Srgrimes } 60474927Sjhb sx_sunlock(&allproc_lock); 6051541Srgrimes} 6061541Srgrimes 6071541Srgrimes/* 6081541Srgrimes * Return true if caller has permission to set the ktracing state 6091541Srgrimes * of target. Essentially, the target can't possess any 6101541Srgrimes * more permissions than the caller. KTRFAC_ROOT signifies that 6118876Srgrimes * root previously set the tracing status on the target process, and 6121541Srgrimes * so, only root may further change it. 6131541Srgrimes */ 61412819Sphkstatic int 61594618Sjhbktrcanset(td, targetp) 61694618Sjhb struct thread *td; 61794618Sjhb struct proc *targetp; 6181541Srgrimes{ 6191541Srgrimes 62094618Sjhb PROC_LOCK_ASSERT(targetp, MA_OWNED); 62179335Srwatson if (targetp->p_traceflag & KTRFAC_ROOT && 62294618Sjhb suser_cred(td->td_ucred, PRISON_ROOT)) 62346155Sphk return (0); 6241541Srgrimes 62594618Sjhb if (p_candebug(td->td_proc, targetp) != 0) 62679335Srwatson return (0); 62779335Srwatson 62879335Srwatson return (1); 6291541Srgrimes} 6301541Srgrimes 63113203Swollman#endif /* KTRACE */ 632