[BACK]Return to kern_ktrace.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

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>