[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.63

1.63    ! christos    1: /*     $NetBSD: kern_ktrace.c,v 1.62 2002/12/09 21:29:21 manu 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.55      lukem      37:
                     38: #include <sys/cdefs.h>
1.63    ! christos   39: __KERNEL_RCSID(0, "$NetBSD: kern_ktrace.c,v 1.62 2002/12/09 21:29:21 manu Exp $");
1.29      thorpej    40:
                     41: #include "opt_ktrace.h"
1.62      manu       42: #include "opt_compat_mach.h"
1.1       cgd        43:
1.7       mycroft    44: #include <sys/param.h>
1.13      cgd        45: #include <sys/systm.h>
1.7       mycroft    46: #include <sys/proc.h>
                     47: #include <sys/file.h>
                     48: #include <sys/namei.h>
                     49: #include <sys/vnode.h>
                     50: #include <sys/ktrace.h>
                     51: #include <sys/malloc.h>
                     52: #include <sys/syslog.h>
1.28      christos   53: #include <sys/filedesc.h>
1.42      sommerfe   54: #include <sys/ioctl.h>
1.1       cgd        55:
1.13      cgd        56: #include <sys/mount.h>
                     57: #include <sys/syscallargs.h>
1.22      christos   58:
1.62      manu       59: #ifdef COMPAT_MACH
                     60: #include <compat/mach/mach_types.h>
                     61: #include <compat/mach/mach_message.h>
                     62: #endif
                     63:
1.51      jdolecek   64: #ifdef KTRACE
                     65:
1.47      thorpej    66: int    ktrace_common(struct proc *, int, int, int, struct file *);
                     67: void   ktrinitheader(struct ktr_header *, struct proc *, int);
                     68: int    ktrops(struct proc *, struct proc *, int, int, struct file *);
                     69: int    ktrsetchildren(struct proc *, struct proc *, int, int,
                     70:            struct file *);
                     71: int    ktrwrite(struct proc *, struct ktr_header *);
                     72: int    ktrcanset(struct proc *, struct proc *);
                     73: int    ktrsamefile(struct file *, struct file *);
1.44      sommerfe   74:
                     75: /*
                     76:  * "deep" compare of two files for the purposes of clearing a trace.
                     77:  * Returns true if they're the same open file, or if they point at the
                     78:  * same underlying vnode/socket.
                     79:  */
                     80:
                     81: int
1.62      manu       82: ktrsamefile(f1, f2)
                     83:        struct file *f1;
                     84:        struct file *f2;
1.44      sommerfe   85: {
                     86:        return ((f1 == f2) ||
1.45      sommerfe   87:            ((f1 != NULL) && (f2 != NULL) &&
                     88:                (f1->f_type == f2->f_type) &&
1.44      sommerfe   89:                (f1->f_data == f2->f_data)));
                     90: }
1.22      christos   91:
1.28      christos   92: void
1.62      manu       93: ktrderef(p)
                     94:        struct proc *p;
1.28      christos   95: {
1.42      sommerfe   96:        struct file *fp = p->p_tracep;
                     97:        p->p_traceflag = 0;
                     98:        if (fp == NULL)
1.28      christos   99:                return;
1.42      sommerfe  100:        FILE_USE(fp);
1.59      jdolecek  101:
                    102:        /*
                    103:         * ktrace file descriptor can't be watched (are not visible to
                    104:         * userspace), so no kqueue stuff here
                    105:         */
1.42      sommerfe  106:        closef(fp, NULL);
1.28      christos  107:
                    108:        p->p_tracep = NULL;
                    109: }
                    110:
                    111: void
1.62      manu      112: ktradref(p)
                    113:        struct proc *p;
1.28      christos  114: {
1.42      sommerfe  115:        struct file *fp = p->p_tracep;
1.28      christos  116:
1.42      sommerfe  117:        fp->f_count++;
1.28      christos  118: }
                    119:
1.39      thorpej   120: void
1.62      manu      121: ktrinitheader(kth, p, type)
                    122:        struct ktr_header *kth;
                    123:        struct proc *p;
                    124:        int type;
1.1       cgd       125: {
                    126:
1.39      thorpej   127:        memset(kth, 0, sizeof(*kth));
1.1       cgd       128:        kth->ktr_type = type;
                    129:        microtime(&kth->ktr_time);
                    130:        kth->ktr_pid = p->p_pid;
1.32      perry     131:        memcpy(kth->ktr_comm, p->p_comm, MAXCOMLEN);
1.1       cgd       132: }
                    133:
1.17      cgd       134: void
1.62      manu      135: ktrsyscall(p, code, realcode, args)
                    136:        struct proc *p;
                    137:        register_t code;
                    138:        register_t realcode;
                    139:        register_t args[];
1.1       cgd       140: {
1.39      thorpej   141:        struct ktr_header kth;
                    142:        struct ktr_syscall *ktp;
1.17      cgd       143:        register_t *argp;
1.57      fvdl      144:        int argsize;
                    145:        size_t len;
1.60      thorpej   146:        u_int i;
1.57      fvdl      147:
                    148:        argsize = p->p_emul->e_sysent[code].sy_narg * sizeof (register_t);
                    149:        len = sizeof(struct ktr_syscall) + argsize;
1.1       cgd       150:
1.9       cgd       151:        p->p_traceflag |= KTRFAC_ACTIVE;
1.39      thorpej   152:        ktrinitheader(&kth, p, KTR_SYSCALL);
                    153:        ktp = malloc(len, M_TEMP, M_WAITOK);
1.61      manu      154:        ktp->ktr_code = realcode;
1.17      cgd       155:        ktp->ktr_argsize = argsize;
                    156:        argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall));
1.31      perry     157:        for (i = 0; i < (argsize / sizeof(*argp)); i++)
1.1       cgd       158:                *argp++ = args[i];
1.39      thorpej   159:        kth.ktr_buf = (caddr_t)ktp;
                    160:        kth.ktr_len = len;
1.42      sommerfe  161:        (void) ktrwrite(p, &kth);
1.39      thorpej   162:        free(ktp, M_TEMP);
1.9       cgd       163:        p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1       cgd       164: }
                    165:
1.17      cgd       166: void
1.62      manu      167: ktrsysret(p, code, error, retval)
                    168:        struct proc *p;
                    169:        register_t code;
                    170:        int error;
                    171:        register_t retval;
1.1       cgd       172: {
1.39      thorpej   173:        struct ktr_header kth;
1.1       cgd       174:        struct ktr_sysret ktp;
                    175:
1.9       cgd       176:        p->p_traceflag |= KTRFAC_ACTIVE;
1.39      thorpej   177:        ktrinitheader(&kth, p, KTR_SYSRET);
1.1       cgd       178:        ktp.ktr_code = code;
1.34      kleink    179:        ktp.ktr_eosys = 0;                      /* XXX unused */
1.1       cgd       180:        ktp.ktr_error = error;
                    181:        ktp.ktr_retval = retval;                /* what about val2 ? */
                    182:
1.39      thorpej   183:        kth.ktr_buf = (caddr_t)&ktp;
                    184:        kth.ktr_len = sizeof(struct ktr_sysret);
1.1       cgd       185:
1.42      sommerfe  186:        (void) ktrwrite(p, &kth);
1.9       cgd       187:        p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1       cgd       188: }
                    189:
1.17      cgd       190: void
1.62      manu      191: ktrnamei(p, path)
                    192:        struct proc *p;
                    193:        char *path;
1.1       cgd       194: {
1.39      thorpej   195:        struct ktr_header kth;
1.1       cgd       196:
1.9       cgd       197:        p->p_traceflag |= KTRFAC_ACTIVE;
1.39      thorpej   198:        ktrinitheader(&kth, p, KTR_NAMEI);
                    199:        kth.ktr_len = strlen(path);
                    200:        kth.ktr_buf = path;
1.18      christos  201:
1.42      sommerfe  202:        (void) ktrwrite(p, &kth);
1.18      christos  203:        p->p_traceflag &= ~KTRFAC_ACTIVE;
                    204: }
                    205:
                    206: void
1.62      manu      207: ktremul(p)
                    208:        struct proc *p;
1.18      christos  209: {
1.39      thorpej   210:        struct ktr_header kth;
1.50      scw       211:        const char *emul = p->p_emul->e_name;
1.18      christos  212:
                    213:        p->p_traceflag |= KTRFAC_ACTIVE;
1.39      thorpej   214:        ktrinitheader(&kth, p, KTR_EMUL);
                    215:        kth.ktr_len = strlen(emul);
1.50      scw       216:        kth.ktr_buf = (caddr_t)emul;
1.1       cgd       217:
1.42      sommerfe  218:        (void) ktrwrite(p, &kth);
1.9       cgd       219:        p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1       cgd       220: }
                    221:
1.17      cgd       222: void
1.62      manu      223: ktrgenio(p, fd, rw, iov, len, error)
                    224:        struct proc *p;
                    225:        int fd;
                    226:        enum uio_rw rw;
                    227:        struct iovec *iov;
                    228:        int len;
                    229:        int error;
1.1       cgd       230: {
1.39      thorpej   231:        struct ktr_header kth;
1.28      christos  232:        struct ktr_genio *ktp;
                    233:        caddr_t cp;
                    234:        int resid = len, cnt;
1.39      thorpej   235:        int buflen;
                    236:
1.1       cgd       237:        if (error)
                    238:                return;
1.39      thorpej   239:
1.9       cgd       240:        p->p_traceflag |= KTRFAC_ACTIVE;
1.39      thorpej   241:
                    242:        buflen = min(PAGE_SIZE, len + sizeof(struct ktr_genio));
                    243:
                    244:        ktrinitheader(&kth, p, KTR_GENIO);
                    245:        ktp = malloc(buflen, M_TEMP, M_WAITOK);
1.1       cgd       246:        ktp->ktr_fd = fd;
                    247:        ktp->ktr_rw = rw;
1.39      thorpej   248:
                    249:        kth.ktr_buf = (caddr_t)ktp;
                    250:
1.31      perry     251:        cp = (caddr_t)((char *)ktp + sizeof(struct ktr_genio));
1.39      thorpej   252:        buflen -= sizeof(struct ktr_genio);
                    253:
1.1       cgd       254:        while (resid > 0) {
1.46      thorpej   255:                KDASSERT(p->p_cpu != NULL);
                    256:                KDASSERT(p->p_cpu == curcpu());
                    257:                if (p->p_cpu->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
1.39      thorpej   258:                        preempt(NULL);
                    259:
                    260:                cnt = min(iov->iov_len, buflen);
                    261:                if (cnt > resid)
1.1       cgd       262:                        cnt = resid;
1.39      thorpej   263:                if (copyin(iov->iov_base, cp, cnt))
                    264:                        break;
                    265:
                    266:                kth.ktr_len = cnt + sizeof(struct ktr_genio);
                    267:
1.42      sommerfe  268:                if (__predict_false(ktrwrite(p, &kth) != 0))
1.39      thorpej   269:                        break;
                    270:
                    271:                iov->iov_base = (caddr_t)iov->iov_base + cnt;
                    272:                iov->iov_len -= cnt;
                    273:
                    274:                if (iov->iov_len == 0)
                    275:                        iov++;
                    276:
1.1       cgd       277:                resid -= cnt;
                    278:        }
                    279:
1.39      thorpej   280:        free(ktp, M_TEMP);
1.9       cgd       281:        p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1       cgd       282: }
                    283:
1.17      cgd       284: void
1.62      manu      285: ktrpsig(p, sig, action, mask, code)
                    286:        struct proc *p;
                    287:        int sig;
                    288:        sig_t action;
                    289:        sigset_t *mask;
                    290:        int code;
1.1       cgd       291: {
1.39      thorpej   292:        struct ktr_header kth;
1.1       cgd       293:        struct ktr_psig kp;
                    294:
1.9       cgd       295:        p->p_traceflag |= KTRFAC_ACTIVE;
1.39      thorpej   296:        ktrinitheader(&kth, p, KTR_PSIG);
1.1       cgd       297:        kp.signo = (char)sig;
                    298:        kp.action = action;
1.33      mycroft   299:        kp.mask = *mask;
1.1       cgd       300:        kp.code = code;
1.39      thorpej   301:        kth.ktr_buf = (caddr_t)&kp;
                    302:        kth.ktr_len = sizeof(struct ktr_psig);
1.1       cgd       303:
1.42      sommerfe  304:        (void) ktrwrite(p, &kth);
1.9       cgd       305:        p->p_traceflag &= ~KTRFAC_ACTIVE;
                    306: }
                    307:
1.17      cgd       308: void
1.62      manu      309: ktrcsw(p, out, user)
                    310:        struct proc *p;
                    311:        int out;
                    312:        int user;
1.9       cgd       313: {
1.39      thorpej   314:        struct ktr_header kth;
                    315:        struct ktr_csw kc;
1.9       cgd       316:
                    317:        p->p_traceflag |= KTRFAC_ACTIVE;
1.39      thorpej   318:        ktrinitheader(&kth, p, KTR_CSW);
1.9       cgd       319:        kc.out = out;
                    320:        kc.user = user;
1.39      thorpej   321:        kth.ktr_buf = (caddr_t)&kc;
                    322:        kth.ktr_len = sizeof(struct ktr_csw);
1.9       cgd       323:
1.42      sommerfe  324:        (void) ktrwrite(p, &kth);
1.9       cgd       325:        p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1       cgd       326: }
                    327:
1.51      jdolecek  328: void
                    329: ktruser(p, id, addr, len, ustr)
                    330:        struct proc *p;
                    331:        const char *id;
                    332:        void *addr;
                    333:        size_t len;
                    334:        int ustr;
                    335: {
                    336:        struct ktr_header kth;
                    337:        struct ktr_user *ktp;
                    338:        caddr_t user_dta;
                    339:
                    340:        p->p_traceflag |= KTRFAC_ACTIVE;
                    341:        ktrinitheader(&kth, p, KTR_USER);
                    342:        ktp = malloc(sizeof(struct ktr_user) + len, M_TEMP, M_WAITOK);
                    343:        if (ustr) {
                    344:                if (copyinstr(id, ktp->ktr_id, KTR_USER_MAXIDLEN, NULL) != 0)
                    345:                        ktp->ktr_id[0] = '\0';
                    346:        } else
                    347:                strncpy(ktp->ktr_id, id, KTR_USER_MAXIDLEN);
                    348:        ktp->ktr_id[KTR_USER_MAXIDLEN-1] = '\0';
                    349:
                    350:        user_dta = (caddr_t) ((char *)ktp + sizeof(struct ktr_user));
                    351:        if (copyin(addr, (void *) user_dta, len) != 0)
                    352:                len = 0;
                    353:
                    354:        kth.ktr_buf = (void *)ktp;
                    355:        kth.ktr_len = sizeof(struct ktr_user) + len;
                    356:        (void) ktrwrite(p, &kth);
                    357:
                    358:        free(ktp, M_TEMP);
                    359:        p->p_traceflag &= ~KTRFAC_ACTIVE;
                    360:
                    361: }
                    362:
1.62      manu      363: void
                    364: ktrmmsg(p, msgh, size)
                    365:        struct proc *p;
1.63    ! christos  366:        const void *msgh;
1.62      manu      367:        size_t size;
                    368: {
                    369:        struct ktr_header kth;
                    370:        struct ktr_mmsg *kp;
                    371:        int error;
                    372:
                    373:        p->p_traceflag |= KTRFAC_ACTIVE;
                    374:        ktrinitheader(&kth, p, KTR_MMSG);
                    375:
                    376:        kp = (struct ktr_mmsg *)malloc(size, M_TEMP, M_WAITOK);
                    377:        if ((error = copyin(msgh, kp, size)) != 0)
                    378:                size = 0; /* Still log a message, but empty */
                    379:
                    380:        kth.ktr_buf = (caddr_t)kp;
                    381:        kth.ktr_len = size;
                    382:        (void) ktrwrite(p, &kth);
                    383:        free(kp, M_TEMP);
                    384:        p->p_traceflag &= ~KTRFAC_ACTIVE;
                    385: }
                    386:
1.1       cgd       387: /* Interface and common routines */
                    388:
1.17      cgd       389: int
1.62      manu      390: ktrace_common(curp, ops, facs, pid, fp)
                    391:        struct proc *curp;
                    392:        int ops;
                    393:        int facs;
                    394:        int pid;
                    395:        struct file *fp;
1.28      christos  396: {
1.42      sommerfe  397:        int ret = 0;
                    398:        int error = 0;
                    399:        int one = 1;
                    400:        int descend;
1.28      christos  401:        struct proc *p;
                    402:        struct pgrp *pg;
                    403:
                    404:        curp->p_traceflag |= KTRFAC_ACTIVE;
1.42      sommerfe  405:        descend = ops & KTRFLAG_DESCEND;
                    406:        facs = facs & ~((unsigned) KTRFAC_ROOT);
1.28      christos  407:
                    408:        /*
                    409:         * Clear all uses of the tracefile
                    410:         */
                    411:        if (KTROP(ops) == KTROP_CLEARFILE) {
1.37      thorpej   412:                proclist_lock_read();
1.39      thorpej   413:                for (p = LIST_FIRST(&allproc); p != NULL;
                    414:                     p = LIST_NEXT(p, p_list)) {
1.44      sommerfe  415:                        if (ktrsamefile(p->p_tracep, fp)) {
1.28      christos  416:                                if (ktrcanset(curp, p))
                    417:                                        ktrderef(p);
                    418:                                else
                    419:                                        error = EPERM;
                    420:                        }
                    421:                }
1.36      thorpej   422:                proclist_unlock_read();
1.28      christos  423:                goto done;
                    424:        }
1.42      sommerfe  425:
                    426:        /*
                    427:         * Mark fp non-blocking, to avoid problems from possible deadlocks.
                    428:         */
                    429:
1.43      sommerfe  430:        if (fp != NULL) {
                    431:                fp->f_flag |= FNONBLOCK;
                    432:                (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&one, curp);
                    433:        }
1.42      sommerfe  434:
1.28      christos  435:        /*
                    436:         * need something to (un)trace (XXX - why is this here?)
                    437:         */
                    438:        if (!facs) {
                    439:                error = EINVAL;
                    440:                goto done;
                    441:        }
                    442:        /*
                    443:         * do it
                    444:         */
1.42      sommerfe  445:        if (pid < 0) {
1.28      christos  446:                /*
                    447:                 * by process group
                    448:                 */
1.42      sommerfe  449:                pg = pgfind(-pid);
1.28      christos  450:                if (pg == NULL) {
                    451:                        error = ESRCH;
                    452:                        goto done;
                    453:                }
1.39      thorpej   454:                for (p = LIST_FIRST(&pg->pg_members); p != NULL;
                    455:                     p = LIST_NEXT(p, p_pglist)) {
1.28      christos  456:                        if (descend)
                    457:                                ret |= ktrsetchildren(curp, p, ops, facs, fp);
                    458:                        else
                    459:                                ret |= ktrops(curp, p, ops, facs, fp);
1.39      thorpej   460:                }
1.28      christos  461:
                    462:        } else {
                    463:                /*
                    464:                 * by pid
                    465:                 */
1.42      sommerfe  466:                p = pfind(pid);
1.28      christos  467:                if (p == NULL) {
                    468:                        error = ESRCH;
                    469:                        goto done;
                    470:                }
                    471:                if (descend)
                    472:                        ret |= ktrsetchildren(curp, p, ops, facs, fp);
                    473:                else
                    474:                        ret |= ktrops(curp, p, ops, facs, fp);
                    475:        }
                    476:        if (!ret)
                    477:                error = EPERM;
                    478: done:
                    479:        curp->p_traceflag &= ~KTRFAC_ACTIVE;
                    480:        return (error);
                    481: }
                    482:
                    483: /*
                    484:  * ktrace system call
                    485:  */
                    486: /* ARGSUSED */
                    487: int
1.62      manu      488: sys_fktrace(curp, v, retval)
                    489:        struct proc *curp;
                    490:        void *v;
                    491:        register_t *retval;
1.42      sommerfe  492: {
                    493:        struct sys_fktrace_args /* {
                    494:                syscallarg(int) fd;
                    495:                syscallarg(int) ops;
                    496:                syscallarg(int) facs;
                    497:                syscallarg(int) pid;
                    498:        } */ *uap = v;
                    499:        struct file *fp = NULL;
                    500:        struct filedesc *fdp = curp->p_fd;
                    501:
1.54      thorpej   502:        if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
                    503:                return (EBADF);
                    504:
                    505:        if ((fp->f_flag & FWRITE) == 0)
1.42      sommerfe  506:                return (EBADF);
                    507:
                    508:        return ktrace_common(curp, SCARG(uap, ops),
                    509:            SCARG(uap, facs), SCARG(uap, pid), fp);
                    510: }
                    511:
                    512: /*
                    513:  * ktrace system call
                    514:  */
                    515: /* ARGSUSED */
                    516: int
1.62      manu      517: sys_ktrace(curp, v, retval)
                    518:        struct proc *curp;
                    519:        void *v;
                    520:        register_t *retval;
1.19      thorpej   521: {
1.28      christos  522:        struct sys_ktrace_args /* {
1.24      mycroft   523:                syscallarg(const char *) fname;
1.13      cgd       524:                syscallarg(int) ops;
                    525:                syscallarg(int) facs;
                    526:                syscallarg(int) pid;
1.19      thorpej   527:        } */ *uap = v;
1.28      christos  528:        struct vnode *vp = NULL;
1.42      sommerfe  529:        struct file *fp = NULL;
                    530:        int fd;
                    531:        int ops = SCARG(uap, ops);
1.1       cgd       532:        int error = 0;
                    533:        struct nameidata nd;
                    534:
1.42      sommerfe  535:        ops = KTROP(ops) | (ops & KTRFLAG_DESCEND);
                    536:
1.9       cgd       537:        curp->p_traceflag |= KTRFAC_ACTIVE;
1.1       cgd       538:        if (ops != KTROP_CLEAR) {
                    539:                /*
                    540:                 * an operation which requires a file argument.
                    541:                 */
1.13      cgd       542:                NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname),
                    543:                    curp);
1.22      christos  544:                if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
1.9       cgd       545:                        curp->p_traceflag &= ~KTRFAC_ACTIVE;
1.1       cgd       546:                        return (error);
1.9       cgd       547:                }
1.1       cgd       548:                vp = nd.ni_vp;
1.25      fvdl      549:                VOP_UNLOCK(vp, 0);
1.1       cgd       550:                if (vp->v_type != VREG) {
                    551:                        (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
1.9       cgd       552:                        curp->p_traceflag &= ~KTRFAC_ACTIVE;
1.1       cgd       553:                        return (EACCES);
                    554:                }
                    555:                /*
1.42      sommerfe  556:                 * XXX This uses up a file descriptor slot in the
                    557:                 * tracing process for the duration of this syscall.
                    558:                 * This is not expected to be a problem.  If
                    559:                 * falloc(NULL, ...) DTRT we could skip that part, but
                    560:                 * that would require changing its interface to allow
                    561:                 * the caller to pass in a ucred..
                    562:                 *
                    563:                 * This will FILE_USE the fp it returns, if any.
                    564:                 * Keep it in use until we return.
1.1       cgd       565:                 */
1.42      sommerfe  566:                if ((error = falloc(curp, &fp, &fd)) != 0)
1.1       cgd       567:                        goto done;
1.42      sommerfe  568:
                    569:                fp->f_flag = FWRITE|FAPPEND;
                    570:                fp->f_type = DTYPE_VNODE;
                    571:                fp->f_ops = &vnops;
                    572:                fp->f_data = (caddr_t)vp;
1.54      thorpej   573:                FILE_SET_MATURE(fp);
1.42      sommerfe  574:                vp = NULL;
                    575:        }
                    576:        error = ktrace_common(curp, SCARG(uap, ops), SCARG(uap, facs),
                    577:            SCARG(uap, pid), fp);
                    578: done:
1.1       cgd       579:        if (vp != NULL)
                    580:                (void) vn_close(vp, FWRITE, curp->p_ucred, curp);
1.42      sommerfe  581:        if (fp != NULL) {
1.44      sommerfe  582:                FILE_UNUSE(fp, curp);   /* release file */
1.42      sommerfe  583:                fdrelease(curp, fd);    /* release fd table slot */
                    584:        }
1.1       cgd       585:        return (error);
                    586: }
                    587:
1.4       andrew    588: int
1.62      manu      589: ktrops(curp, p, ops, facs, fp)
                    590:        struct proc *curp;
                    591:        struct proc *p;
                    592:        int ops;
                    593:        int facs;
                    594:        struct file *fp;
1.1       cgd       595: {
                    596:
                    597:        if (!ktrcanset(curp, p))
                    598:                return (0);
1.28      christos  599:        if (KTROP(ops) == KTROP_SET) {
1.42      sommerfe  600:                if (p->p_tracep != fp) {
1.1       cgd       601:                        /*
                    602:                         * if trace file already in use, relinquish
                    603:                         */
1.28      christos  604:                        ktrderef(p);
1.42      sommerfe  605:                        p->p_tracep = fp;
1.28      christos  606:                        ktradref(p);
1.1       cgd       607:                }
                    608:                p->p_traceflag |= facs;
                    609:                if (curp->p_ucred->cr_uid == 0)
                    610:                        p->p_traceflag |= KTRFAC_ROOT;
                    611:        } else {
                    612:                /* KTROP_CLEAR */
                    613:                if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
                    614:                        /* no more tracing */
1.28      christos  615:                        ktrderef(p);
1.1       cgd       616:                }
                    617:        }
1.21      christos  618:
                    619:        /*
                    620:         * Emit an emulation record, every time there is a ktrace
                    621:         * change/attach request.
                    622:         */
                    623:        if (KTRPOINT(p, KTR_EMUL))
1.42      sommerfe  624:                ktremul(p);
1.49      martin    625: #ifdef __HAVE_SYSCALL_INTERN
1.48      mycroft   626:        (*p->p_emul->e_syscall_intern)(p);
1.49      martin    627: #endif
1.1       cgd       628:
                    629:        return (1);
                    630: }
                    631:
1.22      christos  632: int
1.62      manu      633: ktrsetchildren(curp, top, ops, facs, fp)
                    634:        struct proc *curp;
                    635:        struct proc *top;
                    636:        int ops;
                    637:        int facs;
                    638:        struct file *fp;
1.1       cgd       639: {
1.28      christos  640:        struct proc *p;
                    641:        int ret = 0;
1.1       cgd       642:
                    643:        p = top;
                    644:        for (;;) {
1.42      sommerfe  645:                ret |= ktrops(curp, p, ops, facs, fp);
1.1       cgd       646:                /*
                    647:                 * If this process has children, descend to them next,
                    648:                 * otherwise do any siblings, and if done with this level,
                    649:                 * follow back up the tree (but not past top).
                    650:                 */
1.39      thorpej   651:                if (LIST_FIRST(&p->p_children) != NULL)
                    652:                        p = LIST_FIRST(&p->p_children);
1.1       cgd       653:                else for (;;) {
                    654:                        if (p == top)
                    655:                                return (ret);
1.39      thorpej   656:                        if (LIST_NEXT(p, p_sibling) != NULL) {
                    657:                                p = LIST_NEXT(p, p_sibling);
1.1       cgd       658:                                break;
                    659:                        }
1.12      mycroft   660:                        p = p->p_pptr;
1.1       cgd       661:                }
                    662:        }
                    663:        /*NOTREACHED*/
                    664: }
                    665:
1.39      thorpej   666: int
1.62      manu      667: ktrwrite(p, kth)
                    668:        struct proc *p;
                    669:        struct ktr_header *kth;
1.1       cgd       670: {
                    671:        struct uio auio;
                    672:        struct iovec aiov[2];
1.42      sommerfe  673:        int error, tries;
                    674:        struct file *fp = p->p_tracep;
1.1       cgd       675:
1.42      sommerfe  676:        if (fp == NULL)
                    677:                return 0;
                    678:
1.1       cgd       679:        auio.uio_iov = &aiov[0];
                    680:        auio.uio_offset = 0;
                    681:        auio.uio_segflg = UIO_SYSSPACE;
                    682:        auio.uio_rw = UIO_WRITE;
                    683:        aiov[0].iov_base = (caddr_t)kth;
                    684:        aiov[0].iov_len = sizeof(struct ktr_header);
                    685:        auio.uio_resid = sizeof(struct ktr_header);
                    686:        auio.uio_iovcnt = 1;
                    687:        auio.uio_procp = (struct proc *)0;
                    688:        if (kth->ktr_len > 0) {
                    689:                auio.uio_iovcnt++;
                    690:                aiov[1].iov_base = kth->ktr_buf;
                    691:                aiov[1].iov_len = kth->ktr_len;
                    692:                auio.uio_resid += kth->ktr_len;
                    693:        }
1.28      christos  694:
1.42      sommerfe  695:        FILE_USE(fp);
                    696:
                    697:        tries = 0;
                    698:        do {
1.30      thorpej   699:                error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio,
                    700:                    fp->f_cred, FOF_UPDATE_OFFSET);
1.42      sommerfe  701:                tries++;
                    702:                if (error == EWOULDBLOCK)
                    703:                        yield();
                    704:        } while ((error == EWOULDBLOCK) && (tries < 3));
                    705:        FILE_UNUSE(fp, NULL);
1.28      christos  706:
1.40      thorpej   707:        if (__predict_true(error == 0))
1.39      thorpej   708:                return (0);
1.1       cgd       709:        /*
1.38      darrenr   710:         * If error encountered, give up tracing on this vnode.  Don't report
                    711:         * EPIPE as this can easily happen with fktrace()/ktruss.
1.1       cgd       712:         */
1.38      darrenr   713:        if (error != EPIPE)
                    714:                log(LOG_NOTICE,
                    715:                    "ktrace write failed, errno %d, tracing stopped\n",
                    716:                    error);
1.37      thorpej   717:        proclist_lock_read();
1.39      thorpej   718:        for (p = LIST_FIRST(&allproc); p != NULL; p = LIST_NEXT(p, p_list)) {
1.44      sommerfe  719:                if (ktrsamefile(p->p_tracep, fp))
1.28      christos  720:                        ktrderef(p);
1.1       cgd       721:        }
1.36      thorpej   722:        proclist_unlock_read();
1.39      thorpej   723:
                    724:        return (error);
1.1       cgd       725: }
                    726:
                    727: /*
                    728:  * Return true if caller has permission to set the ktracing state
                    729:  * of target.  Essentially, the target can't possess any
                    730:  * more permissions than the caller.  KTRFAC_ROOT signifies that
                    731:  * root previously set the tracing status on the target process, and
                    732:  * so, only root may further change it.
                    733:  *
                    734:  * TODO: check groups.  use caller effective gid.
                    735:  */
1.22      christos  736: int
1.62      manu      737: ktrcanset(callp, targetp)
                    738:        struct proc *callp;
                    739:        struct proc *targetp;
1.1       cgd       740: {
1.28      christos  741:        struct pcred *caller = callp->p_cred;
                    742:        struct pcred *target = targetp->p_cred;
1.1       cgd       743:
                    744:        if ((caller->pc_ucred->cr_uid == target->p_ruid &&
                    745:             target->p_ruid == target->p_svuid &&
                    746:             caller->p_rgid == target->p_rgid &&        /* XXX */
                    747:             target->p_rgid == target->p_svgid &&
1.58      itojun    748:             (targetp->p_traceflag & KTRFAC_ROOT) == 0 &&
                    749:             (targetp->p_flag & P_SUGID) == 0) ||
1.1       cgd       750:             caller->pc_ucred->cr_uid == 0)
                    751:                return (1);
                    752:
                    753:        return (0);
                    754: }
1.47      thorpej   755: #endif /* KTRACE */
1.51      jdolecek  756:
                    757: /*
                    758:  * Put user defined entry to ktrace records.
                    759:  */
                    760: int
                    761: sys_utrace(p, v, retval)
                    762:        struct proc *p;
                    763:        void *v;
                    764:        register_t *retval;
                    765: {
                    766: #ifdef KTRACE
                    767:        struct sys_utrace_args /* {
1.52      jdolecek  768:                syscallarg(const char *) label;
1.51      jdolecek  769:                syscallarg(void *) addr;
                    770:                syscallarg(size_t) len;
                    771:        } */ *uap = v;
                    772:
                    773:        if (!KTRPOINT(p, KTR_USER))
                    774:                return (0);
1.53      jdolecek  775:
                    776:        if (SCARG(uap, len) > KTR_USER_MAXLEN)
                    777:                return (EINVAL);
1.51      jdolecek  778:
1.52      jdolecek  779:        ktruser(p, SCARG(uap, label), SCARG(uap, addr), SCARG(uap, len), 1);
1.51      jdolecek  780:
                    781:        return (0);
                    782: #else /* !KTRACE */
                    783:        return ENOSYS;
                    784: #endif /* KTRACE */
                    785: }

CVSweb <webmaster@jp.NetBSD.org>