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

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

CVSweb <webmaster@jp.NetBSD.org>