kern_ktrace.c revision 13203
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 3444510Swollman * $Id: kern_ktrace.c,v 1.9 1995/12/14 08:31:23 phk Exp $ 351541Srgrimes */ 361541Srgrimes 37116182Sobrien#include "opt_ktrace.h" 38116182Sobrien 39116182Sobrien#include <sys/param.h> 401541Srgrimes#include <sys/systm.h> 411541Srgrimes#include <sys/sysproto.h> 4233392Sphk#include <sys/proc.h> 43127969Scperciva#include <sys/file.h> 441541Srgrimes#include <sys/namei.h> 4574914Sjhb#include <sys/vnode.h> 4668840Sjhb#include <sys/ktrace.h> 47115810Sphk#include <sys/malloc.h> 481541Srgrimes#include <sys/syslog.h> 49115810Sphk 50115810Sphk#ifdef KTRACE 51115810Sphkstatic struct ktr_header *ktrgetheader __P((int type)); 52115810Sphkstatic void ktrwrite __P((struct vnode *, struct ktr_header *)); 53115810Sphkstatic int ktrcanset __P((struct proc *,struct proc *)); 54115810Sphkstatic int ktrsetchildren __P((struct proc *,struct proc *,int,int,struct vnode *)); 55115810Sphkstatic int ktrops __P((struct proc *,struct proc *,int,int,struct vnode *)); 56115810Sphk 57115810Sphk 5833392Sphkstatic struct ktr_header * 5933392Sphkktrgetheader(type) 6033392Sphk int type; 6133392Sphk{ 6233392Sphk register struct ktr_header *kth; 6333392Sphk struct proc *p = curproc; /* XXX */ 6429680Sgibbs 6529680Sgibbs MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 6629680Sgibbs M_TEMP, M_WAITOK); 6729680Sgibbs kth->ktr_type = type; 6833392Sphk microtime(&kth->ktr_time); 69116606Sphk kth->ktr_pid = p->p_pid; 70122585Smckusick bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN); 71122761Sphk return (kth); 72122585Smckusick} 732112Swollman 7429680Sgibbsvoid 75128024Scpercivaktrsyscall(vp, code, narg, args) 76128024Scperciva struct vnode *vp; 77127969Scperciva int code, narg, args[]; 78127969Scperciva{ 79127969Scperciva struct ktr_header *kth; 80127969Scperciva struct ktr_syscall *ktp; 81127969Scperciva register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); 82128024Scperciva struct proc *p = curproc; /* XXX */ 83128024Scperciva int *argp, i; 84128024Scperciva 85127969Scperciva p->p_traceflag |= KTRFAC_ACTIVE; 86127969Scperciva kth = ktrgetheader(KTR_SYSCALL); 87127969Scperciva MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); 88127969Scperciva ktp->ktr_code = code; 89127969Scperciva ktp->ktr_narg = narg; 90128024Scperciva argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); 91127969Scperciva for (i = 0; i < narg; i++) 92128024Scperciva *argp++ = args[i]; 93128024Scperciva kth->ktr_buf = (caddr_t)ktp; 94127969Scperciva kth->ktr_len = len; 95127969Scperciva ktrwrite(vp, kth); 96127969Scperciva FREE(ktp, M_TEMP); 97127969Scperciva FREE(kth, M_TEMP); 98127969Scperciva p->p_traceflag &= ~KTRFAC_ACTIVE; 99127969Scperciva} 100127969Scperciva 101127969Scpercivavoid 102127969Scpercivaktrsysret(vp, code, error, retval) 1031541Srgrimes struct vnode *vp; 1041541Srgrimes int code, error, retval; 10582127Sdillon{ 10682127Sdillon struct ktr_header *kth; 10782127Sdillon struct ktr_sysret ktp; 10882127Sdillon struct proc *p = curproc; /* XXX */ 10982127Sdillon 11082127Sdillon p->p_traceflag |= KTRFAC_ACTIVE; 11182127Sdillon kth = ktrgetheader(KTR_SYSRET); 11282127Sdillon ktp.ktr_code = code; 11382127Sdillon ktp.ktr_error = error; 11482127Sdillon ktp.ktr_retval = retval; /* what about val2 ? */ 11582127Sdillon 11682127Sdillon kth->ktr_buf = (caddr_t)&ktp; 11782127Sdillon kth->ktr_len = sizeof(struct ktr_sysret); 11882127Sdillon 11982127Sdillon ktrwrite(vp, kth); 12082127Sdillon FREE(kth, M_TEMP); 12182127Sdillon p->p_traceflag &= ~KTRFAC_ACTIVE; 12282127Sdillon} 12382127Sdillon 12482127Sdillonvoid 12582127Sdillonktrnamei(vp, path) 12682127Sdillon struct vnode *vp; 12782127Sdillon char *path; 12882127Sdillon{ 12982127Sdillon struct ktr_header *kth; 13082127Sdillon struct proc *p = curproc; /* XXX */ 13182127Sdillon 13282127Sdillon p->p_traceflag |= KTRFAC_ACTIVE; 13382127Sdillon kth = ktrgetheader(KTR_NAMEI); 13482127Sdillon kth->ktr_len = strlen(path); 13582127Sdillon kth->ktr_buf = path; 13682127Sdillon 13782127Sdillon ktrwrite(vp, kth); 13882127Sdillon FREE(kth, M_TEMP); 13982127Sdillon p->p_traceflag &= ~KTRFAC_ACTIVE; 14082127Sdillon} 14182127Sdillon 14282127Sdillonvoid 14382127Sdillonktrgenio(vp, fd, rw, iov, len, error) 14482127Sdillon struct vnode *vp; 14582127Sdillon int fd; 14682127Sdillon enum uio_rw rw; 14782127Sdillon register struct iovec *iov; 14882127Sdillon int len, error; 14982127Sdillon{ 15093818Sjhb struct ktr_header *kth; 151122585Smckusick register struct ktr_genio *ktp; 152122761Sphk register caddr_t cp; 153122585Smckusick register int resid = len, cnt; 154127969Scperciva struct proc *p = curproc; /* XXX */ 155127969Scperciva 15682127Sdillon if (error) 15782127Sdillon return; 15882127Sdillon p->p_traceflag |= KTRFAC_ACTIVE; 15929680Sgibbs kth = ktrgetheader(KTR_GENIO); 16029680Sgibbs MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, 16129680Sgibbs M_TEMP, M_WAITOK); 16229680Sgibbs ktp->ktr_fd = fd; 16329680Sgibbs ktp->ktr_rw = rw; 16429680Sgibbs cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); 16529680Sgibbs while (resid > 0) { 16629680Sgibbs if ((cnt = iov->iov_len) > resid) 16729680Sgibbs cnt = resid; 16829680Sgibbs if (copyin(iov->iov_base, cp, (unsigned)cnt)) 16932388Sphk goto done; 17029680Sgibbs cp += cnt; 1711541Srgrimes resid -= cnt; 1721541Srgrimes iov++; 1731541Srgrimes } 1741541Srgrimes kth->ktr_buf = (caddr_t)ktp; 17567551Sjhb kth->ktr_len = sizeof (struct ktr_genio) + len; 1761541Srgrimes 177102936Sphk ktrwrite(vp, kth); 178102936Sphkdone: 179102936Sphk FREE(kth, M_TEMP); 180102936Sphk FREE(ktp, M_TEMP); 181115810Sphk p->p_traceflag &= ~KTRFAC_ACTIVE; 182115810Sphk} 183115810Sphk 184127969Scpercivavoid 185122585Smckusickktrpsig(vp, sig, action, mask, code) 186122585Smckusick struct vnode *vp; 187122585Smckusick int sig; 188122585Smckusick sig_t action; 189123254Sphk int mask, code; 190122585Smckusick{ 1911541Srgrimes struct ktr_header *kth; 19233392Sphk struct ktr_psig kp; 19333392Sphk struct proc *p = curproc; /* XXX */ 19433392Sphk 19529680Sgibbs p->p_traceflag |= KTRFAC_ACTIVE; 196115810Sphk kth = ktrgetheader(KTR_PSIG); 197115810Sphk kp.signo = (char)sig; 198115810Sphk kp.action = action; 19929680Sgibbs kp.mask = mask; 20072200Sbmilekic kp.code = code; 20129680Sgibbs kth->ktr_buf = (caddr_t)&kp; 20229805Sgibbs kth->ktr_len = sizeof (struct ktr_psig); 20329805Sgibbs 20429805Sgibbs ktrwrite(vp, kth); 20529805Sgibbs FREE(kth, M_TEMP); 20629805Sgibbs p->p_traceflag &= ~KTRFAC_ACTIVE; 20729805Sgibbs} 20829805Sgibbs 20929805Sgibbsvoid 21029680Sgibbsktrcsw(vp, out, user) 211115810Sphk struct vnode *vp; 21229805Sgibbs int out, user; 21329680Sgibbs{ 21429680Sgibbs struct ktr_header *kth; 21529680Sgibbs struct ktr_csw kc; 21629680Sgibbs struct proc *p = curproc; /* XXX */ 21729805Sgibbs 21872200Sbmilekic p->p_traceflag |= KTRFAC_ACTIVE; 21981370Sjhb kth = ktrgetheader(KTR_CSW); 22072200Sbmilekic kc.out = out; 22129680Sgibbs kc.user = user; 22229680Sgibbs kth->ktr_buf = (caddr_t)&kc; 22329680Sgibbs kth->ktr_len = sizeof (struct ktr_csw); 22429680Sgibbs 22529680Sgibbs ktrwrite(vp, kth); 22629680Sgibbs FREE(kth, M_TEMP); 22768889Sjake p->p_traceflag &= ~KTRFAC_ACTIVE; 22829680Sgibbs} 22929680Sgibbs#endif 23029805Sgibbs 23129680Sgibbs/* Interface and common routines */ 23229680Sgibbs 23368889Sjake/* 23429680Sgibbs * ktrace system call 23544510Swollman */ 23644510Swollman#ifndef _SYS_SYSPROTO_H_ 23744510Swollmanstruct ktrace_args { 23844510Swollman char *fname; 23944510Swollman int ops; 24044510Swollman int facs; 24150673Sjlemon int pid; 24244510Swollman}; 243127969Scperciva#endif 24472200Sbmilekic/* ARGSUSED */ 245115810Sphkint 24672200Sbmilekicktrace(curp, uap, retval) 247115810Sphk struct proc *curp; 248115810Sphk register struct ktrace_args *uap; 249115810Sphk int *retval; 250115810Sphk{ 251122585Smckusick#ifdef KTRACE 252122585Smckusick register struct vnode *vp = NULL; 253122761Sphk register struct proc *p; 254122585Smckusick struct pgrp *pg; 25529680Sgibbs int facs = uap->facs & ~KTRFAC_ROOT; 256122585Smckusick int ops = KTROP(uap->ops); 257122761Sphk int descend = uap->ops & KTRFLAG_DESCEND; 258122585Smckusick int ret = 0; 259122585Smckusick int error = 0; 260122585Smckusick struct nameidata nd; 261123254Sphk 262123254Sphk curp->p_traceflag |= KTRFAC_ACTIVE; 263123254Sphk if (ops != KTROP_CLEAR) { 264123254Sphk /* 265123254Sphk * an operation which requires a file argument. 266123254Sphk */ 267123254Sphk NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, curp); 268123254Sphk error = vn_open(&nd, FREAD|FWRITE, 0); 269123254Sphk if (error) { 270122585Smckusick curp->p_traceflag &= ~KTRFAC_ACTIVE; 271123254Sphk return (error); 272122585Smckusick } 273122585Smckusick vp = nd.ni_vp; 27468889Sjake VOP_UNLOCK(vp); 27572200Sbmilekic if (vp->v_type != VREG) { 27672200Sbmilekic (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); 277127969Scperciva curp->p_traceflag &= ~KTRFAC_ACTIVE; 278127969Scperciva return (EACCES); 279127969Scperciva } 280127969Scperciva } 281127969Scperciva /* 282127969Scperciva * Clear all uses of the tracefile 283127969Scperciva */ 284127969Scperciva if (ops == KTROP_CLEARFILE) { 285127969Scperciva for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { 286127969Scperciva if (p->p_tracep == vp) { 287127969Scperciva if (ktrcanset(curp, p)) { 288127969Scperciva p->p_tracep = NULL; 289127969Scperciva p->p_traceflag = 0; 290127969Scperciva (void) vn_close(vp, FREAD|FWRITE, 291128024Scperciva p->p_ucred, p); 29229680Sgibbs } else 29329680Sgibbs error = EPERM; 29429680Sgibbs } 29529680Sgibbs } 2961541Srgrimes goto done; 297115810Sphk } 298115810Sphk /* 299115810Sphk * need something to (un)trace (XXX - why is this here?) 30029680Sgibbs */ 30172200Sbmilekic if (!facs) { 3021541Srgrimes error = EINVAL; 3031541Srgrimes goto done; 3041541Srgrimes } 3051541Srgrimes /* 3061541Srgrimes * do it 3071541Srgrimes */ 3081541Srgrimes if (uap->pid < 0) { 3091541Srgrimes /* 3101541Srgrimes * by process group 31129680Sgibbs */ 31229680Sgibbs pg = pgfind(-uap->pid); 31329680Sgibbs if (pg == NULL) { 3141541Srgrimes error = ESRCH; 31529680Sgibbs goto done; 31629680Sgibbs } 31729680Sgibbs for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) 31829680Sgibbs if (descend) 3191541Srgrimes ret |= ktrsetchildren(curp, p, ops, facs, vp); 32029680Sgibbs else 32129680Sgibbs ret |= ktrops(curp, p, ops, facs, vp); 32233824Sbde 3231541Srgrimes } else { 32469147Sjlemon /* 3251541Srgrimes * by pid 32629680Sgibbs */ 32729680Sgibbs p = pfind(uap->pid); 3281541Srgrimes if (p == NULL) { 32972200Sbmilekic error = ESRCH; 3301541Srgrimes goto done; 3311541Srgrimes } 33229680Sgibbs if (descend) 33329680Sgibbs ret |= ktrsetchildren(curp, p, ops, facs, vp); 33429680Sgibbs else 3351541Srgrimes ret |= ktrops(curp, p, ops, facs, vp); 33629680Sgibbs } 33744510Swollman if (!ret) 33844510Swollman error = EPERM; 3391541Srgrimesdone: 34044510Swollman if (vp != NULL) 34172200Sbmilekic (void) vn_close(vp, FWRITE, curp->p_ucred, curp); 34229680Sgibbs curp->p_traceflag &= ~KTRFAC_ACTIVE; 3431541Srgrimes return (error); 3441541Srgrimes#else 3451541Srgrimes return ENOSYS; 34629680Sgibbs#endif 34733824Sbde} 3481541Srgrimes 34929680Sgibbs#ifdef KTRACE 3501541Srgrimesstatic int 3511541Srgrimesktrops(curp, p, ops, facs, vp) 35229680Sgibbs struct proc *p, *curp; 35329680Sgibbs int ops, facs; 35429680Sgibbs struct vnode *vp; 35529680Sgibbs{ 35629680Sgibbs 35729680Sgibbs if (!ktrcanset(curp, p)) 35829680Sgibbs return (0); 35929680Sgibbs if (ops == KTROP_SET) { 36072200Sbmilekic if (p->p_tracep != vp) { 36144510Swollman /* 36244510Swollman * if trace file already in use, relinquish 36372200Sbmilekic */ 3641541Srgrimes if (p->p_tracep != NULL) 3651541Srgrimes vrele(p->p_tracep); 36624101Sbde VREF(vp); 36729680Sgibbs p->p_tracep = vp; 36829680Sgibbs } 36929680Sgibbs p->p_traceflag |= facs; 37029680Sgibbs if (curp->p_ucred->cr_uid == 0) 37129680Sgibbs p->p_traceflag |= KTRFAC_ROOT; 37244510Swollman } else { 37344510Swollman /* KTROP_CLEAR */ 37444510Swollman if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 37544510Swollman /* no more tracing */ 37644510Swollman p->p_traceflag = 0; 37744510Swollman if (p->p_tracep != NULL) { 37844510Swollman vrele(p->p_tracep); 37944510Swollman p->p_tracep = NULL; 38050673Sjlemon } 38144510Swollman } 38250673Sjlemon } 38350673Sjlemon 38450673Sjlemon return (1); 38544510Swollman} 38644510Swollman 38769147Sjlemonstatic int 38844510Swollmanktrsetchildren(curp, top, ops, facs, vp) 38944510Swollman struct proc *curp, *top; 39092723Salfred int ops, facs; 39144510Swollman struct vnode *vp; 39244510Swollman{ 39344510Swollman register struct proc *p; 39472200Sbmilekic register int ret = 0; 395127969Scperciva 396127969Scperciva p = top; 397127969Scperciva for (;;) { 398127969Scperciva ret |= ktrops(curp, p, ops, facs, vp); 399127969Scperciva /* 400127969Scperciva * If this process has children, descend to them next, 401127969Scperciva * otherwise do any siblings, and if done with this level, 402127969Scperciva * follow back up the tree (but not past top). 403128024Scperciva */ 40444510Swollman if (p->p_cptr) 40544510Swollman p = p->p_cptr; 40644510Swollman else if (p == top) 40744510Swollman return (ret); 40881370Sjhb else if (p->p_osptr) 40981370Sjhb p = p->p_osptr; 41081370Sjhb else for (;;) { 41144510Swollman p = p->p_pptr; 41244510Swollman if (p == top) 41344510Swollman return (ret); 41444510Swollman if (p->p_osptr) { 41544510Swollman p = p->p_osptr; 41669147Sjlemon break; 41744510Swollman } 41844510Swollman } 41944510Swollman } 42044510Swollman /*NOTREACHED*/ 42172200Sbmilekic} 42244510Swollman 42344510Swollmanstatic void 424128024Scpercivaktrwrite(vp, kth) 425127969Scperciva struct vnode *vp; 42681481Sjhb register struct ktr_header *kth; 42744510Swollman{ 42844510Swollman struct uio auio; 42944510Swollman struct iovec aiov[2]; 43044510Swollman register struct proc *p = curproc; /* XXX */ 431127969Scperciva int error; 432127969Scperciva 433127969Scperciva if (vp == NULL) 434127969Scperciva return; 435127969Scperciva auio.uio_iov = &aiov[0]; 436127969Scperciva auio.uio_offset = 0; 437127969Scperciva auio.uio_segflg = UIO_SYSSPACE; 438127969Scperciva auio.uio_rw = UIO_WRITE; 439127969Scperciva aiov[0].iov_base = (caddr_t)kth; 440127969Scperciva aiov[0].iov_len = sizeof(struct ktr_header); 44172200Sbmilekic auio.uio_resid = sizeof(struct ktr_header); 44244510Swollman auio.uio_iovcnt = 1; 44344510Swollman auio.uio_procp = (struct proc *)0; 44444510Swollman if (kth->ktr_len > 0) { 44544510Swollman auio.uio_iovcnt++; 44650673Sjlemon aiov[1].iov_base = kth->ktr_buf; 447127969Scperciva aiov[1].iov_len = kth->ktr_len; 448128024Scperciva auio.uio_resid += kth->ktr_len; 449127969Scperciva } 450127969Scperciva VOP_LOCK(vp); 451127969Scperciva error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred); 452127969Scperciva VOP_UNLOCK(vp); 453128024Scperciva if (!error) 454127969Scperciva return; 455127969Scperciva /* 456127969Scperciva * If error encountered, give up tracing on this vnode. 457127969Scperciva */ 458127969Scperciva log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", 459127969Scperciva error); 460127969Scperciva for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { 461127969Scperciva if (p->p_tracep == vp) { 462127969Scperciva p->p_tracep = NULL; 463127969Scperciva p->p_traceflag = 0; 464127969Scperciva vrele(vp); 46581481Sjhb } 46644510Swollman } 46750673Sjlemon} 46844510Swollman 46944510Swollman/* 47044510Swollman * Return true if caller has permission to set the ktracing state 47144510Swollman * of target. Essentially, the target can't possess any 47244510Swollman * more permissions than the caller. KTRFAC_ROOT signifies that 47344510Swollman * root previously set the tracing status on the target process, and 47444510Swollman * so, only root may further change it. 47544510Swollman * 47644510Swollman * TODO: check groups. use caller effective gid. 47744510Swollman */ 47872200Sbmilekicstatic int 47981481Sjhbktrcanset(callp, targetp) 48044510Swollman struct proc *callp, *targetp; 48144510Swollman{ 48244510Swollman register struct pcred *caller = callp->p_cred; 48369147Sjlemon register struct pcred *target = targetp->p_cred; 48444510Swollman 48569147Sjlemon if ((caller->pc_ucred->cr_uid == target->p_ruid && 48644510Swollman target->p_ruid == target->p_svuid && 48744527Swollman caller->p_rgid == target->p_rgid && /* XXX */ 48869147Sjlemon target->p_rgid == target->p_svgid && 48969147Sjlemon (targetp->p_traceflag & KTRFAC_ROOT) == 0) || 49044510Swollman caller->pc_ucred->cr_uid == 0) 49144510Swollman return (1); 49231950Snate 49331950Snate return (0); 49431950Snate} 49531950Snate 49631950Snate#endif /* KTRACE */ 49731950Snate