kern_ktrace.c revision 91406
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 91406 2002-02-27 18:32:23Z 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 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 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; 18485397Sdillon /* 18585397Sdillon * don't let p_tracep get ripped out from under us 18685397Sdillon */ 18785397Sdillon if (vp) 18885397Sdillon VREF(vp); 1891541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 1901541Srgrimes kth = ktrgetheader(KTR_GENIO); 19162378Sgreen ktg.ktr_fd = fd; 19262378Sgreen ktg.ktr_rw = rw; 19365556Sjasone kth->ktr_buffer = (caddr_t)&ktg; 19462378Sgreen kth->ktr_len = sizeof(struct ktr_genio); 19562378Sgreen uio->uio_offset = 0; 19662791Sgreen uio->uio_rw = UIO_WRITE; 1971541Srgrimes 19862378Sgreen ktrwrite(vp, kth, uio); 19985397Sdillon if (vp) 20085397Sdillon vrele(vp); 20117429Sphk FREE(kth, M_KTRACE); 2021541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2031541Srgrimes} 2041541Srgrimes 2051549Srgrimesvoid 2061541Srgrimesktrpsig(vp, sig, action, mask, code) 2071541Srgrimes struct vnode *vp; 20851941Smarcel int sig; 2091541Srgrimes sig_t action; 21051791Smarcel sigset_t *mask; 21151941Smarcel int code; 2121541Srgrimes{ 2131541Srgrimes struct ktr_header *kth; 2141541Srgrimes struct ktr_psig kp; 2151541Srgrimes struct proc *p = curproc; /* XXX */ 2161541Srgrimes 21785397Sdillon /* 21885397Sdillon * don't let vp get ripped out from under us 21985397Sdillon */ 22085397Sdillon if (vp) 22185397Sdillon VREF(vp); 2221541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 2231541Srgrimes kth = ktrgetheader(KTR_PSIG); 2241541Srgrimes kp.signo = (char)sig; 2251541Srgrimes kp.action = action; 22651791Smarcel kp.mask = *mask; 2271541Srgrimes kp.code = code; 22865556Sjasone kth->ktr_buffer = (caddr_t)&kp; 2291541Srgrimes kth->ktr_len = sizeof (struct ktr_psig); 2301541Srgrimes 23162378Sgreen ktrwrite(vp, kth, NULL); 23285397Sdillon if (vp) 23385397Sdillon vrele(vp); 23417429Sphk FREE(kth, M_KTRACE); 2351541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2361541Srgrimes} 2371541Srgrimes 2381549Srgrimesvoid 2391541Srgrimesktrcsw(vp, out, user) 2401541Srgrimes struct vnode *vp; 2411541Srgrimes int out, user; 2421541Srgrimes{ 2431541Srgrimes struct ktr_header *kth; 2441541Srgrimes struct ktr_csw kc; 2451541Srgrimes struct proc *p = curproc; /* XXX */ 2461541Srgrimes 24785397Sdillon /* 24885397Sdillon * don't let vp get ripped out from under us 24985397Sdillon */ 25085397Sdillon if (vp) 25185397Sdillon VREF(vp); 2521541Srgrimes p->p_traceflag |= KTRFAC_ACTIVE; 2531541Srgrimes kth = ktrgetheader(KTR_CSW); 2541541Srgrimes kc.out = out; 2551541Srgrimes kc.user = user; 25665556Sjasone kth->ktr_buffer = (caddr_t)&kc; 2571541Srgrimes kth->ktr_len = sizeof (struct ktr_csw); 2581541Srgrimes 25962378Sgreen ktrwrite(vp, kth, NULL); 26085397Sdillon if (vp) 26185397Sdillon vrele(vp); 26217429Sphk FREE(kth, M_KTRACE); 2631541Srgrimes p->p_traceflag &= ~KTRFAC_ACTIVE; 2641541Srgrimes} 26513203Swollman#endif 2661541Srgrimes 2671541Srgrimes/* Interface and common routines */ 2681541Srgrimes 2691541Srgrimes/* 2701541Srgrimes * ktrace system call 2711541Srgrimes */ 27212221Sbde#ifndef _SYS_SYSPROTO_H_ 2731541Srgrimesstruct ktrace_args { 2741541Srgrimes char *fname; 2751541Srgrimes int ops; 2761541Srgrimes int facs; 2771541Srgrimes int pid; 2781541Srgrimes}; 27912221Sbde#endif 2801541Srgrimes/* ARGSUSED */ 2811549Srgrimesint 28283366Sjulianktrace(td, uap) 28383366Sjulian struct thread *td; 2841541Srgrimes register struct ktrace_args *uap; 2851541Srgrimes{ 28613203Swollman#ifdef KTRACE 28783366Sjulian struct proc *curp = td->td_proc; 2881541Srgrimes register struct vnode *vp = NULL; 2891541Srgrimes register struct proc *p; 2901541Srgrimes struct pgrp *pg; 2911541Srgrimes int facs = uap->facs & ~KTRFAC_ROOT; 2921541Srgrimes int ops = KTROP(uap->ops); 2931541Srgrimes int descend = uap->ops & KTRFLAG_DESCEND; 2941541Srgrimes int ret = 0; 29562550Smckusick int flags, error = 0; 2961541Srgrimes struct nameidata nd; 2971541Srgrimes 2981541Srgrimes curp->p_traceflag |= KTRFAC_ACTIVE; 2991541Srgrimes if (ops != KTROP_CLEAR) { 3001541Srgrimes /* 3011541Srgrimes * an operation which requires a file argument. 3021541Srgrimes */ 30383366Sjulian NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, td); 30462550Smckusick flags = FREAD | FWRITE | O_NOFOLLOW; 30562550Smckusick error = vn_open(&nd, &flags, 0); 3063308Sphk if (error) { 3071541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 3081541Srgrimes return (error); 3091541Srgrimes } 31054655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 3111541Srgrimes vp = nd.ni_vp; 31283366Sjulian VOP_UNLOCK(vp, 0, td); 3131541Srgrimes if (vp->v_type != VREG) { 31491406Sjhb (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); 3151541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 3161541Srgrimes return (EACCES); 3171541Srgrimes } 3181541Srgrimes } 3191541Srgrimes /* 32085397Sdillon * Clear all uses of the tracefile. 3211541Srgrimes */ 3221541Srgrimes if (ops == KTROP_CLEARFILE) { 32374927Sjhb sx_slock(&allproc_lock); 32453212Sphk LIST_FOREACH(p, &allproc, p_list) { 3251541Srgrimes if (p->p_tracep == vp) { 32685397Sdillon if (ktrcanset(curp, p) && p->p_tracep == vp) { 3271541Srgrimes p->p_tracep = NULL; 3281541Srgrimes p->p_traceflag = 0; 3291541Srgrimes (void) vn_close(vp, FREAD|FWRITE, 33091406Sjhb td->td_ucred, td); 33185397Sdillon } else { 3321541Srgrimes error = EPERM; 33385397Sdillon } 3341541Srgrimes } 3351541Srgrimes } 33674927Sjhb sx_sunlock(&allproc_lock); 3371541Srgrimes goto done; 3381541Srgrimes } 3391541Srgrimes /* 3401541Srgrimes * need something to (un)trace (XXX - why is this here?) 3411541Srgrimes */ 3421541Srgrimes if (!facs) { 3431541Srgrimes error = EINVAL; 3441541Srgrimes goto done; 3451541Srgrimes } 3468876Srgrimes /* 3471541Srgrimes * do it 3481541Srgrimes */ 3491541Srgrimes if (uap->pid < 0) { 3501541Srgrimes /* 3511541Srgrimes * by process group 3521541Srgrimes */ 35391140Stanimura PGRPSESS_SLOCK(); 3541541Srgrimes pg = pgfind(-uap->pid); 3551541Srgrimes if (pg == NULL) { 35691140Stanimura PGRPSESS_SUNLOCK(); 3571541Srgrimes error = ESRCH; 3581541Srgrimes goto done; 3591541Srgrimes } 36091140Stanimura /* 36191140Stanimura * ktrops() may call vrele(). Lock pg_members 36291140Stanimura * by the pgrpsess_lock rather than pg_mtx. 36391140Stanimura */ 36491140Stanimura PGRP_UNLOCK(pg); 36553212Sphk LIST_FOREACH(p, &pg->pg_members, p_pglist) 3661541Srgrimes if (descend) 3671541Srgrimes ret |= ktrsetchildren(curp, p, ops, facs, vp); 3688876Srgrimes else 3691541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 37091140Stanimura PGRPSESS_SUNLOCK(); 3711541Srgrimes } else { 3721541Srgrimes /* 3731541Srgrimes * by pid 3741541Srgrimes */ 3751541Srgrimes p = pfind(uap->pid); 3761541Srgrimes if (p == NULL) { 3771541Srgrimes error = ESRCH; 3781541Srgrimes goto done; 3791541Srgrimes } 38075893Sjhb PROC_UNLOCK(p); 3811541Srgrimes if (descend) 3821541Srgrimes ret |= ktrsetchildren(curp, p, ops, facs, vp); 3831541Srgrimes else 3841541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 3851541Srgrimes } 3861541Srgrimes if (!ret) 3871541Srgrimes error = EPERM; 3881541Srgrimesdone: 3891541Srgrimes if (vp != NULL) 39091406Sjhb (void) vn_close(vp, FWRITE, td->td_ucred, td); 3911541Srgrimes curp->p_traceflag &= ~KTRFAC_ACTIVE; 3921541Srgrimes return (error); 39313203Swollman#else 39413203Swollman return ENOSYS; 39513203Swollman#endif 3961541Srgrimes} 3971541Srgrimes 39818398Sphk/* 39918398Sphk * utrace system call 40018398Sphk */ 40118398Sphk/* ARGSUSED */ 40218398Sphkint 40383366Sjulianutrace(td, uap) 40483366Sjulian struct thread *td; 40518398Sphk register struct utrace_args *uap; 40618398Sphk{ 40783366Sjulian 40813203Swollman#ifdef KTRACE 40918398Sphk struct ktr_header *kth; 41018398Sphk struct proc *p = curproc; /* XXX */ 41185397Sdillon struct vnode *vp; 41218398Sphk register caddr_t cp; 41318398Sphk 41418398Sphk if (!KTRPOINT(p, KTR_USER)) 41518398Sphk return (0); 41670792Salfred if (uap->len > KTR_USER_MAXLEN) 41770707Salfred return (EINVAL); 41818398Sphk p->p_traceflag |= KTRFAC_ACTIVE; 41985397Sdillon if ((vp = p->p_tracep) != NULL) 42085397Sdillon VREF(vp); 42118398Sphk kth = ktrgetheader(KTR_USER); 42218469Sphk MALLOC(cp, caddr_t, uap->len, M_KTRACE, M_WAITOK); 42318398Sphk if (!copyin(uap->addr, cp, uap->len)) { 42465556Sjasone kth->ktr_buffer = cp; 42518469Sphk kth->ktr_len = uap->len; 42685397Sdillon ktrwrite(vp, kth, NULL); 42718398Sphk } 42885397Sdillon if (vp) 42985397Sdillon vrele(vp); 43018398Sphk FREE(kth, M_KTRACE); 43118469Sphk FREE(cp, M_KTRACE); 43218398Sphk p->p_traceflag &= ~KTRFAC_ACTIVE; 43318398Sphk 43418398Sphk return (0); 43518398Sphk#else 43618398Sphk return (ENOSYS); 43718398Sphk#endif 43818398Sphk} 43918398Sphk 44018398Sphk#ifdef KTRACE 44112819Sphkstatic int 4421541Srgrimesktrops(curp, p, ops, facs, vp) 4431541Srgrimes struct proc *p, *curp; 4441541Srgrimes int ops, facs; 4451541Srgrimes struct vnode *vp; 4461541Srgrimes{ 4471541Srgrimes 4481541Srgrimes if (!ktrcanset(curp, p)) 4491541Srgrimes return (0); 4501541Srgrimes if (ops == KTROP_SET) { 4518876Srgrimes if (p->p_tracep != vp) { 45285397Sdillon struct vnode *vtmp; 45385397Sdillon 4541541Srgrimes /* 4551541Srgrimes * if trace file already in use, relinquish 4561541Srgrimes */ 4571541Srgrimes VREF(vp); 45885397Sdillon while ((vtmp = p->p_tracep) != NULL) { 45985397Sdillon p->p_tracep = NULL; 46085397Sdillon vrele(vtmp); 46185397Sdillon } 4621541Srgrimes p->p_tracep = vp; 4631541Srgrimes } 4641541Srgrimes p->p_traceflag |= facs; 4651541Srgrimes if (curp->p_ucred->cr_uid == 0) 4661541Srgrimes p->p_traceflag |= KTRFAC_ROOT; 4678876Srgrimes } else { 4681541Srgrimes /* KTROP_CLEAR */ 4691541Srgrimes if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 47085397Sdillon struct vnode *vtmp; 47185397Sdillon 4721541Srgrimes /* no more tracing */ 4731541Srgrimes p->p_traceflag = 0; 47485397Sdillon if ((vtmp = p->p_tracep) != NULL) { 4751541Srgrimes p->p_tracep = NULL; 47685397Sdillon vrele(vtmp); 4771541Srgrimes } 4781541Srgrimes } 4791541Srgrimes } 4801541Srgrimes 4811541Srgrimes return (1); 4821541Srgrimes} 4831541Srgrimes 48412819Sphkstatic int 4851541Srgrimesktrsetchildren(curp, top, ops, facs, vp) 4861541Srgrimes struct proc *curp, *top; 4871541Srgrimes int ops, facs; 4881541Srgrimes struct vnode *vp; 4891541Srgrimes{ 4901541Srgrimes register struct proc *p; 4911541Srgrimes register int ret = 0; 4921541Srgrimes 4931541Srgrimes p = top; 49474927Sjhb sx_slock(&proctree_lock); 4951541Srgrimes for (;;) { 4961541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 4971541Srgrimes /* 4981541Srgrimes * If this process has children, descend to them next, 4991541Srgrimes * otherwise do any siblings, and if done with this level, 5001541Srgrimes * follow back up the tree (but not past top). 5011541Srgrimes */ 50253212Sphk if (!LIST_EMPTY(&p->p_children)) 50353212Sphk p = LIST_FIRST(&p->p_children); 5041541Srgrimes else for (;;) { 50570317Sjake if (p == top) { 50674927Sjhb sx_sunlock(&proctree_lock); 5071541Srgrimes return (ret); 50870317Sjake } 50953212Sphk if (LIST_NEXT(p, p_sibling)) { 51053212Sphk p = LIST_NEXT(p, p_sibling); 5111541Srgrimes break; 5121541Srgrimes } 51314529Shsu p = p->p_pptr; 5141541Srgrimes } 5151541Srgrimes } 5161541Srgrimes /*NOTREACHED*/ 5171541Srgrimes} 5181541Srgrimes 51912819Sphkstatic void 52062378Sgreenktrwrite(vp, kth, uio) 5211541Srgrimes struct vnode *vp; 5221541Srgrimes register struct ktr_header *kth; 52362378Sgreen struct uio *uio; 5241541Srgrimes{ 5251541Srgrimes struct uio auio; 5261541Srgrimes struct iovec aiov[2]; 52783366Sjulian struct thread *td = curthread; /* XXX */ 52883366Sjulian struct proc *p = td->td_proc; /* XXX */ 52962976Smckusick struct mount *mp; 5301541Srgrimes int error; 5311541Srgrimes 5321541Srgrimes if (vp == NULL) 5331541Srgrimes return; 5341541Srgrimes auio.uio_iov = &aiov[0]; 5351541Srgrimes auio.uio_offset = 0; 5361541Srgrimes auio.uio_segflg = UIO_SYSSPACE; 5371541Srgrimes auio.uio_rw = UIO_WRITE; 5381541Srgrimes aiov[0].iov_base = (caddr_t)kth; 5391541Srgrimes aiov[0].iov_len = sizeof(struct ktr_header); 5401541Srgrimes auio.uio_resid = sizeof(struct ktr_header); 5411541Srgrimes auio.uio_iovcnt = 1; 54283366Sjulian auio.uio_td = curthread; 5431541Srgrimes if (kth->ktr_len > 0) { 5441541Srgrimes auio.uio_iovcnt++; 54565556Sjasone aiov[1].iov_base = kth->ktr_buffer; 5461541Srgrimes aiov[1].iov_len = kth->ktr_len; 5471541Srgrimes auio.uio_resid += kth->ktr_len; 54862378Sgreen if (uio != NULL) 54962378Sgreen kth->ktr_len += uio->uio_resid; 5501541Srgrimes } 55162976Smckusick vn_start_write(vp, &mp, V_WAIT); 55283366Sjulian vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 55391406Sjhb (void)VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 55491406Sjhb error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, td->td_ucred); 55562378Sgreen if (error == 0 && uio != NULL) { 55691406Sjhb (void)VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 55791406Sjhb error = VOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, td->td_ucred); 55862378Sgreen } 55983366Sjulian VOP_UNLOCK(vp, 0, td); 56062976Smckusick vn_finished_write(mp); 5611541Srgrimes if (!error) 5621541Srgrimes return; 5631541Srgrimes /* 56485397Sdillon * If error encountered, give up tracing on this vnode. XXX what 56585397Sdillon * happens to the loop if vrele() blocks? 5661541Srgrimes */ 5671541Srgrimes log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", 5681541Srgrimes error); 56974927Sjhb sx_slock(&allproc_lock); 57053212Sphk LIST_FOREACH(p, &allproc, p_list) { 5711541Srgrimes if (p->p_tracep == vp) { 5721541Srgrimes p->p_tracep = NULL; 5731541Srgrimes p->p_traceflag = 0; 5741541Srgrimes vrele(vp); 5751541Srgrimes } 5761541Srgrimes } 57774927Sjhb sx_sunlock(&allproc_lock); 5781541Srgrimes} 5791541Srgrimes 5801541Srgrimes/* 5811541Srgrimes * Return true if caller has permission to set the ktracing state 5821541Srgrimes * of target. Essentially, the target can't possess any 5831541Srgrimes * more permissions than the caller. KTRFAC_ROOT signifies that 5848876Srgrimes * root previously set the tracing status on the target process, and 5851541Srgrimes * so, only root may further change it. 5861541Srgrimes */ 58712819Sphkstatic int 5881541Srgrimesktrcanset(callp, targetp) 5891541Srgrimes struct proc *callp, *targetp; 5901541Srgrimes{ 5911541Srgrimes 59279335Srwatson if (targetp->p_traceflag & KTRFAC_ROOT && 59379335Srwatson suser_xxx(NULL, callp, PRISON_ROOT)) 59446155Sphk return (0); 5951541Srgrimes 59679335Srwatson if (p_candebug(callp, targetp) != 0) 59779335Srwatson return (0); 59879335Srwatson 59979335Srwatson return (1); 6001541Srgrimes} 6011541Srgrimes 60213203Swollman#endif /* KTRACE */ 603