Annotation of src/sys/kern/kern_ktrace.c, Revision 1.43
1.43 ! sommerfe 1: /* $NetBSD: kern_ktrace.c,v 1.42 2000/05/27 00:40:45 sommerfeld Exp $ */
1.11 cgd 2:
1.1 cgd 3: /*
1.9 cgd 4: * Copyright (c) 1989, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: *
1.25 fvdl 35: * @(#)kern_ktrace.c 8.5 (Berkeley) 5/14/95
1.1 cgd 36: */
1.29 thorpej 37:
38: #include "opt_ktrace.h"
1.1 cgd 39:
1.9 cgd 40: #ifdef KTRACE
41:
1.7 mycroft 42: #include <sys/param.h>
1.13 cgd 43: #include <sys/systm.h>
1.7 mycroft 44: #include <sys/proc.h>
45: #include <sys/file.h>
46: #include <sys/namei.h>
47: #include <sys/vnode.h>
48: #include <sys/ktrace.h>
49: #include <sys/malloc.h>
50: #include <sys/syslog.h>
1.28 christos 51: #include <sys/filedesc.h>
1.42 sommerfe 52: #include <sys/ioctl.h>
1.1 cgd 53:
1.13 cgd 54: #include <sys/mount.h>
55: #include <sys/syscallargs.h>
1.22 christos 56:
1.42 sommerfe 57: int ktrace_common __P((struct proc *, int, int, int, struct file *));
1.39 thorpej 58: void ktrinitheader __P((struct ktr_header *, struct proc *, int));
1.42 sommerfe 59: int ktrops __P((struct proc *, struct proc *, int, int, struct file *));
60: int ktrsetchildren __P((struct proc *, struct proc *, int, int,
61: struct file *));
62: int ktrwrite __P((struct proc *, struct ktr_header *));
1.39 thorpej 63: int ktrcanset __P((struct proc *, struct proc *));
1.22 christos 64:
1.28 christos 65: void
66: ktrderef(p)
67: struct proc *p;
68: {
1.42 sommerfe 69: struct file *fp = p->p_tracep;
70: p->p_traceflag = 0;
71: if (fp == NULL)
1.28 christos 72: return;
1.42 sommerfe 73: FILE_USE(fp);
74: closef(fp, NULL);
1.28 christos 75:
76: p->p_tracep = NULL;
77: }
78:
79: void
80: ktradref(p)
81: struct proc *p;
82: {
1.42 sommerfe 83: struct file *fp = p->p_tracep;
1.28 christos 84:
1.42 sommerfe 85: fp->f_count++;
1.28 christos 86: }
87:
1.39 thorpej 88: void
89: ktrinitheader(kth, p, type)
90: struct ktr_header *kth;
91: struct proc *p;
1.4 andrew 92: int type;
1.1 cgd 93: {
94:
1.39 thorpej 95: memset(kth, 0, sizeof(*kth));
1.1 cgd 96: kth->ktr_type = type;
97: microtime(&kth->ktr_time);
98: kth->ktr_pid = p->p_pid;
1.32 perry 99: memcpy(kth->ktr_comm, p->p_comm, MAXCOMLEN);
1.1 cgd 100: }
101:
1.17 cgd 102: void
1.42 sommerfe 103: ktrsyscall(p, code, argsize, args)
104: struct proc *p;
1.16 mycroft 105: register_t code;
106: size_t argsize;
107: register_t args[];
1.1 cgd 108: {
1.39 thorpej 109: struct ktr_header kth;
110: struct ktr_syscall *ktp;
1.17 cgd 111: register_t *argp;
1.39 thorpej 112: size_t len = sizeof(struct ktr_syscall) + argsize;
1.17 cgd 113: int i;
1.1 cgd 114:
1.9 cgd 115: p->p_traceflag |= KTRFAC_ACTIVE;
1.39 thorpej 116: ktrinitheader(&kth, p, KTR_SYSCALL);
117: ktp = malloc(len, M_TEMP, M_WAITOK);
1.1 cgd 118: ktp->ktr_code = code;
1.17 cgd 119: ktp->ktr_argsize = argsize;
120: argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall));
1.31 perry 121: for (i = 0; i < (argsize / sizeof(*argp)); i++)
1.1 cgd 122: *argp++ = args[i];
1.39 thorpej 123: kth.ktr_buf = (caddr_t)ktp;
124: kth.ktr_len = len;
1.42 sommerfe 125: (void) ktrwrite(p, &kth);
1.39 thorpej 126: free(ktp, M_TEMP);
1.9 cgd 127: p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 128: }
129:
1.17 cgd 130: void
1.42 sommerfe 131: ktrsysret(p, code, error, retval)
132: struct proc *p;
1.16 mycroft 133: register_t code;
134: int error;
135: register_t retval;
1.1 cgd 136: {
1.39 thorpej 137: struct ktr_header kth;
1.1 cgd 138: struct ktr_sysret ktp;
139:
1.9 cgd 140: p->p_traceflag |= KTRFAC_ACTIVE;
1.39 thorpej 141: ktrinitheader(&kth, p, KTR_SYSRET);
1.1 cgd 142: ktp.ktr_code = code;
1.34 kleink 143: ktp.ktr_eosys = 0; /* XXX unused */
1.1 cgd 144: ktp.ktr_error = error;
145: ktp.ktr_retval = retval; /* what about val2 ? */
146:
1.39 thorpej 147: kth.ktr_buf = (caddr_t)&ktp;
148: kth.ktr_len = sizeof(struct ktr_sysret);
1.1 cgd 149:
1.42 sommerfe 150: (void) ktrwrite(p, &kth);
1.9 cgd 151: p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 152: }
153:
1.17 cgd 154: void
1.42 sommerfe 155: ktrnamei(p, path)
156: struct proc *p;
1.1 cgd 157: char *path;
158: {
1.39 thorpej 159: struct ktr_header kth;
1.1 cgd 160:
1.9 cgd 161: p->p_traceflag |= KTRFAC_ACTIVE;
1.39 thorpej 162: ktrinitheader(&kth, p, KTR_NAMEI);
163: kth.ktr_len = strlen(path);
164: kth.ktr_buf = path;
1.18 christos 165:
1.42 sommerfe 166: (void) ktrwrite(p, &kth);
1.18 christos 167: p->p_traceflag &= ~KTRFAC_ACTIVE;
168: }
169:
170: void
1.42 sommerfe 171: ktremul(p)
1.28 christos 172: struct proc *p;
1.18 christos 173: {
1.39 thorpej 174: struct ktr_header kth;
1.42 sommerfe 175: char *emul = p->p_emul->e_name;
1.18 christos 176:
177: p->p_traceflag |= KTRFAC_ACTIVE;
1.39 thorpej 178: ktrinitheader(&kth, p, KTR_EMUL);
179: kth.ktr_len = strlen(emul);
180: kth.ktr_buf = emul;
1.1 cgd 181:
1.42 sommerfe 182: (void) ktrwrite(p, &kth);
1.9 cgd 183: p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 184: }
185:
1.17 cgd 186: void
1.42 sommerfe 187: ktrgenio(p, fd, rw, iov, len, error)
188: struct proc *p;
1.1 cgd 189: int fd;
190: enum uio_rw rw;
1.28 christos 191: struct iovec *iov;
1.4 andrew 192: int len, error;
1.1 cgd 193: {
1.39 thorpej 194: struct ktr_header kth;
1.28 christos 195: struct ktr_genio *ktp;
196: caddr_t cp;
197: int resid = len, cnt;
1.39 thorpej 198: int buflen;
199:
1.1 cgd 200: if (error)
201: return;
1.39 thorpej 202:
1.9 cgd 203: p->p_traceflag |= KTRFAC_ACTIVE;
1.39 thorpej 204:
205: buflen = min(PAGE_SIZE, len + sizeof(struct ktr_genio));
206:
207: ktrinitheader(&kth, p, KTR_GENIO);
208: ktp = malloc(buflen, M_TEMP, M_WAITOK);
1.1 cgd 209: ktp->ktr_fd = fd;
210: ktp->ktr_rw = rw;
1.39 thorpej 211:
212: kth.ktr_buf = (caddr_t)ktp;
213:
1.31 perry 214: cp = (caddr_t)((char *)ktp + sizeof(struct ktr_genio));
1.39 thorpej 215: buflen -= sizeof(struct ktr_genio);
216:
1.1 cgd 217: while (resid > 0) {
1.41 thorpej 218: if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
1.39 thorpej 219: preempt(NULL);
220:
221: cnt = min(iov->iov_len, buflen);
222: if (cnt > resid)
1.1 cgd 223: cnt = resid;
1.39 thorpej 224: if (copyin(iov->iov_base, cp, cnt))
225: break;
226:
227: kth.ktr_len = cnt + sizeof(struct ktr_genio);
228:
1.42 sommerfe 229: if (__predict_false(ktrwrite(p, &kth) != 0))
1.39 thorpej 230: break;
231:
232: iov->iov_base = (caddr_t)iov->iov_base + cnt;
233: iov->iov_len -= cnt;
234:
235: if (iov->iov_len == 0)
236: iov++;
237:
1.1 cgd 238: resid -= cnt;
239: }
240:
1.39 thorpej 241: free(ktp, M_TEMP);
1.9 cgd 242: p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 243: }
244:
1.17 cgd 245: void
1.42 sommerfe 246: ktrpsig(p, sig, action, mask, code)
247: struct proc *p;
1.9 cgd 248: int sig;
249: sig_t action;
1.33 mycroft 250: sigset_t *mask;
251: int code;
1.1 cgd 252: {
1.39 thorpej 253: struct ktr_header kth;
1.1 cgd 254: struct ktr_psig kp;
255:
1.9 cgd 256: p->p_traceflag |= KTRFAC_ACTIVE;
1.39 thorpej 257: ktrinitheader(&kth, p, KTR_PSIG);
1.1 cgd 258: kp.signo = (char)sig;
259: kp.action = action;
1.33 mycroft 260: kp.mask = *mask;
1.1 cgd 261: kp.code = code;
1.39 thorpej 262: kth.ktr_buf = (caddr_t)&kp;
263: kth.ktr_len = sizeof(struct ktr_psig);
1.1 cgd 264:
1.42 sommerfe 265: (void) ktrwrite(p, &kth);
1.9 cgd 266: p->p_traceflag &= ~KTRFAC_ACTIVE;
267: }
268:
1.17 cgd 269: void
1.42 sommerfe 270: ktrcsw(p, out, user)
271: struct proc *p;
1.9 cgd 272: int out, user;
273: {
1.39 thorpej 274: struct ktr_header kth;
275: struct ktr_csw kc;
1.9 cgd 276:
277: p->p_traceflag |= KTRFAC_ACTIVE;
1.39 thorpej 278: ktrinitheader(&kth, p, KTR_CSW);
1.9 cgd 279: kc.out = out;
280: kc.user = user;
1.39 thorpej 281: kth.ktr_buf = (caddr_t)&kc;
282: kth.ktr_len = sizeof(struct ktr_csw);
1.9 cgd 283:
1.42 sommerfe 284: (void) ktrwrite(p, &kth);
1.9 cgd 285: p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 286: }
287:
288: /* Interface and common routines */
289:
1.17 cgd 290: int
1.42 sommerfe 291: ktrace_common (curp, ops, facs, pid, fp)
1.28 christos 292: struct proc *curp;
1.42 sommerfe 293: int ops, facs, pid;
294: struct file *fp;
1.28 christos 295: {
1.42 sommerfe 296: int ret = 0;
297: int error = 0;
298: int one = 1;
299: int descend;
1.28 christos 300: struct proc *p;
301: struct pgrp *pg;
302:
303: curp->p_traceflag |= KTRFAC_ACTIVE;
1.42 sommerfe 304: descend = ops & KTRFLAG_DESCEND;
305: facs = facs & ~((unsigned) KTRFAC_ROOT);
1.28 christos 306:
307: /*
308: * Clear all uses of the tracefile
309: */
310: if (KTROP(ops) == KTROP_CLEARFILE) {
1.37 thorpej 311: proclist_lock_read();
1.39 thorpej 312: for (p = LIST_FIRST(&allproc); p != NULL;
313: p = LIST_NEXT(p, p_list)) {
1.28 christos 314: if (p->p_tracep == fp) {
315: if (ktrcanset(curp, p))
316: ktrderef(p);
317: else
318: error = EPERM;
319: }
320: }
1.36 thorpej 321: proclist_unlock_read();
1.28 christos 322: goto done;
323: }
1.42 sommerfe 324:
325: /*
326: * Mark fp non-blocking, to avoid problems from possible deadlocks.
327: */
328:
1.43 ! sommerfe 329: if (fp != NULL) {
! 330: fp->f_flag |= FNONBLOCK;
! 331: (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&one, curp);
! 332: }
1.42 sommerfe 333:
1.28 christos 334: /*
335: * need something to (un)trace (XXX - why is this here?)
336: */
337: if (!facs) {
338: error = EINVAL;
339: goto done;
340: }
341: /*
342: * do it
343: */
1.42 sommerfe 344: if (pid < 0) {
1.28 christos 345: /*
346: * by process group
347: */
1.42 sommerfe 348: pg = pgfind(-pid);
1.28 christos 349: if (pg == NULL) {
350: error = ESRCH;
351: goto done;
352: }
1.39 thorpej 353: for (p = LIST_FIRST(&pg->pg_members); p != NULL;
354: p = LIST_NEXT(p, p_pglist)) {
1.28 christos 355: if (descend)
356: ret |= ktrsetchildren(curp, p, ops, facs, fp);
357: else
358: ret |= ktrops(curp, p, ops, facs, fp);
1.39 thorpej 359: }
1.28 christos 360:
361: } else {
362: /*
363: * by pid
364: */
1.42 sommerfe 365: p = pfind(pid);
1.28 christos 366: if (p == NULL) {
367: error = ESRCH;
368: goto done;
369: }
370: if (descend)
371: ret |= ktrsetchildren(curp, p, ops, facs, fp);
372: else
373: ret |= ktrops(curp, p, ops, facs, fp);
374: }
375: if (!ret)
376: error = EPERM;
377: done:
378: curp->p_traceflag &= ~KTRFAC_ACTIVE;
379: return (error);
380: }
381:
382: /*
383: * ktrace system call
384: */
385: /* ARGSUSED */
386: int
1.42 sommerfe 387: sys_fktrace(curp, v, retval)
388: struct proc *curp;
389: void *v;
390: register_t *retval;
391: {
392: struct sys_fktrace_args /* {
393: syscallarg(int) fd;
394: syscallarg(int) ops;
395: syscallarg(int) facs;
396: syscallarg(int) pid;
397: } */ *uap = v;
398: struct file *fp = NULL;
399: struct filedesc *fdp = curp->p_fd;
400:
401: if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
402: (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
403: (fp->f_flag & FWRITE) == 0)
404: return (EBADF);
405:
406: return ktrace_common(curp, SCARG(uap, ops),
407: SCARG(uap, facs), SCARG(uap, pid), fp);
408: }
409:
410: /*
411: * ktrace system call
412: */
413: /* ARGSUSED */
414: int
1.20 mycroft 415: sys_ktrace(curp, v, retval)
1.1 cgd 416: struct proc *curp;
1.19 thorpej 417: void *v;
418: register_t *retval;
419: {
1.28 christos 420: struct sys_ktrace_args /* {
1.24 mycroft 421: syscallarg(const char *) fname;
1.13 cgd 422: syscallarg(int) ops;
423: syscallarg(int) facs;
424: syscallarg(int) pid;
1.19 thorpej 425: } */ *uap = v;
1.28 christos 426: struct vnode *vp = NULL;
1.42 sommerfe 427: struct file *fp = NULL;
428: int fd;
429: int ops = SCARG(uap, ops);
1.1 cgd 430: int error = 0;
431: struct nameidata nd;
432:
1.42 sommerfe 433: ops = KTROP(ops) | (ops & KTRFLAG_DESCEND);
434:
1.9 cgd 435: curp->p_traceflag |= KTRFAC_ACTIVE;
1.1 cgd 436: if (ops != KTROP_CLEAR) {
437: /*
438: * an operation which requires a file argument.
439: */
1.13 cgd 440: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname),
441: curp);
1.22 christos 442: if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
1.9 cgd 443: curp->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 444: return (error);
1.9 cgd 445: }
1.1 cgd 446: vp = nd.ni_vp;
1.25 fvdl 447: VOP_UNLOCK(vp, 0);
1.1 cgd 448: if (vp->v_type != VREG) {
449: (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
1.9 cgd 450: curp->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 451: return (EACCES);
452: }
453: /*
1.42 sommerfe 454: * XXX This uses up a file descriptor slot in the
455: * tracing process for the duration of this syscall.
456: * This is not expected to be a problem. If
457: * falloc(NULL, ...) DTRT we could skip that part, but
458: * that would require changing its interface to allow
459: * the caller to pass in a ucred..
460: *
461: * This will FILE_USE the fp it returns, if any.
462: * Keep it in use until we return.
1.1 cgd 463: */
1.42 sommerfe 464: if ((error = falloc(curp, &fp, &fd)) != 0)
1.1 cgd 465: goto done;
1.42 sommerfe 466:
467: fp->f_flag = FWRITE|FAPPEND;
468: fp->f_type = DTYPE_VNODE;
469: fp->f_ops = &vnops;
470: fp->f_data = (caddr_t)vp;
471: vp = NULL;
472: }
473: error = ktrace_common(curp, SCARG(uap, ops), SCARG(uap, facs),
474: SCARG(uap, pid), fp);
475: done:
1.1 cgd 476: if (vp != NULL)
477: (void) vn_close(vp, FWRITE, curp->p_ucred, curp);
1.42 sommerfe 478: if (fp != NULL) {
479: fdrelease(curp, fd); /* release fd table slot */
480: FILE_UNUSE(fp, curp); /* release file */
481: }
1.1 cgd 482: return (error);
483: }
484:
1.4 andrew 485: int
1.42 sommerfe 486: ktrops(curp, p, ops, facs, fp)
1.9 cgd 487: struct proc *p, *curp;
1.4 andrew 488: int ops, facs;
1.42 sommerfe 489: struct file *fp;
1.1 cgd 490: {
491:
492: if (!ktrcanset(curp, p))
493: return (0);
1.28 christos 494: if (KTROP(ops) == KTROP_SET) {
1.42 sommerfe 495: if (p->p_tracep != fp) {
1.1 cgd 496: /*
497: * if trace file already in use, relinquish
498: */
1.28 christos 499: ktrderef(p);
1.42 sommerfe 500: p->p_tracep = fp;
1.28 christos 501: ktradref(p);
1.1 cgd 502: }
503: p->p_traceflag |= facs;
504: if (curp->p_ucred->cr_uid == 0)
505: p->p_traceflag |= KTRFAC_ROOT;
506: } else {
507: /* KTROP_CLEAR */
508: if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
509: /* no more tracing */
1.28 christos 510: ktrderef(p);
1.1 cgd 511: }
512: }
1.21 christos 513:
514: /*
515: * Emit an emulation record, every time there is a ktrace
516: * change/attach request.
517: */
518: if (KTRPOINT(p, KTR_EMUL))
1.42 sommerfe 519: ktremul(p);
1.1 cgd 520:
521: return (1);
522: }
523:
1.22 christos 524: int
1.42 sommerfe 525: ktrsetchildren(curp, top, ops, facs, fp)
1.1 cgd 526: struct proc *curp, *top;
1.4 andrew 527: int ops, facs;
1.42 sommerfe 528: struct file *fp;
1.1 cgd 529: {
1.28 christos 530: struct proc *p;
531: int ret = 0;
1.1 cgd 532:
533: p = top;
534: for (;;) {
1.42 sommerfe 535: ret |= ktrops(curp, p, ops, facs, fp);
1.1 cgd 536: /*
537: * If this process has children, descend to them next,
538: * otherwise do any siblings, and if done with this level,
539: * follow back up the tree (but not past top).
540: */
1.39 thorpej 541: if (LIST_FIRST(&p->p_children) != NULL)
542: p = LIST_FIRST(&p->p_children);
1.1 cgd 543: else for (;;) {
544: if (p == top)
545: return (ret);
1.39 thorpej 546: if (LIST_NEXT(p, p_sibling) != NULL) {
547: p = LIST_NEXT(p, p_sibling);
1.1 cgd 548: break;
549: }
1.12 mycroft 550: p = p->p_pptr;
1.1 cgd 551: }
552: }
553: /*NOTREACHED*/
554: }
555:
1.39 thorpej 556: int
1.42 sommerfe 557: ktrwrite(p, kth)
1.28 christos 558: struct proc *p;
559: struct ktr_header *kth;
1.1 cgd 560: {
561: struct uio auio;
562: struct iovec aiov[2];
1.42 sommerfe 563: int error, tries;
564: struct file *fp = p->p_tracep;
1.1 cgd 565:
1.42 sommerfe 566: if (fp == NULL)
567: return 0;
568:
1.1 cgd 569: auio.uio_iov = &aiov[0];
570: auio.uio_offset = 0;
571: auio.uio_segflg = UIO_SYSSPACE;
572: auio.uio_rw = UIO_WRITE;
573: aiov[0].iov_base = (caddr_t)kth;
574: aiov[0].iov_len = sizeof(struct ktr_header);
575: auio.uio_resid = sizeof(struct ktr_header);
576: auio.uio_iovcnt = 1;
577: auio.uio_procp = (struct proc *)0;
578: if (kth->ktr_len > 0) {
579: auio.uio_iovcnt++;
580: aiov[1].iov_base = kth->ktr_buf;
581: aiov[1].iov_len = kth->ktr_len;
582: auio.uio_resid += kth->ktr_len;
583: }
1.28 christos 584:
1.42 sommerfe 585: FILE_USE(fp);
586:
587: tries = 0;
588: do {
1.30 thorpej 589: error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio,
590: fp->f_cred, FOF_UPDATE_OFFSET);
1.42 sommerfe 591: tries++;
592: if (error == EWOULDBLOCK)
593: yield();
594: } while ((error == EWOULDBLOCK) && (tries < 3));
595: FILE_UNUSE(fp, NULL);
1.28 christos 596:
1.40 thorpej 597: if (__predict_true(error == 0))
1.39 thorpej 598: return (0);
1.1 cgd 599: /*
1.38 darrenr 600: * If error encountered, give up tracing on this vnode. Don't report
601: * EPIPE as this can easily happen with fktrace()/ktruss.
1.1 cgd 602: */
1.38 darrenr 603: if (error != EPIPE)
604: log(LOG_NOTICE,
605: "ktrace write failed, errno %d, tracing stopped\n",
606: error);
1.37 thorpej 607: proclist_lock_read();
1.39 thorpej 608: for (p = LIST_FIRST(&allproc); p != NULL; p = LIST_NEXT(p, p_list)) {
1.42 sommerfe 609: if (p->p_tracep == fp)
1.28 christos 610: ktrderef(p);
1.1 cgd 611: }
1.36 thorpej 612: proclist_unlock_read();
1.39 thorpej 613:
614: return (error);
1.1 cgd 615: }
616:
617: /*
618: * Return true if caller has permission to set the ktracing state
619: * of target. Essentially, the target can't possess any
620: * more permissions than the caller. KTRFAC_ROOT signifies that
621: * root previously set the tracing status on the target process, and
622: * so, only root may further change it.
623: *
624: * TODO: check groups. use caller effective gid.
625: */
1.22 christos 626: int
1.1 cgd 627: ktrcanset(callp, targetp)
628: struct proc *callp, *targetp;
629: {
1.28 christos 630: struct pcred *caller = callp->p_cred;
631: struct pcred *target = targetp->p_cred;
1.1 cgd 632:
633: if ((caller->pc_ucred->cr_uid == target->p_ruid &&
634: target->p_ruid == target->p_svuid &&
635: caller->p_rgid == target->p_rgid && /* XXX */
636: target->p_rgid == target->p_svgid &&
637: (targetp->p_traceflag & KTRFAC_ROOT) == 0) ||
638: caller->pc_ucred->cr_uid == 0)
639: return (1);
640:
641: return (0);
642: }
1.9 cgd 643:
644: #endif
CVSweb <webmaster@jp.NetBSD.org>