Annotation of kernel/bsd/kern/kern_ktrace.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * Copyright (c) 1989, 1993
                     28:  *     The Regents of the University of California.  All rights reserved.
                     29:  *
                     30:  * Redistribution and use in source and binary forms, with or without
                     31:  * modification, are permitted provided that the following conditions
                     32:  * are met:
                     33:  * 1. Redistributions of source code must retain the above copyright
                     34:  *    notice, this list of conditions and the following disclaimer.
                     35:  * 2. Redistributions in binary form must reproduce the above copyright
                     36:  *    notice, this list of conditions and the following disclaimer in the
                     37:  *    documentation and/or other materials provided with the distribution.
                     38:  * 3. All advertising materials mentioning features or use of this software
                     39:  *    must display the following acknowledgement:
                     40:  *     This product includes software developed by the University of
                     41:  *     California, Berkeley and its contributors.
                     42:  * 4. Neither the name of the University nor the names of its contributors
                     43:  *    may be used to endorse or promote products derived from this software
                     44:  *    without specific prior written permission.
                     45:  *
                     46:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     47:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     48:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     49:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     50:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     51:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     52:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     53:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     54:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     55:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     56:  * SUCH DAMAGE.
                     57:  *
                     58:  *     @(#)kern_ktrace.c       8.2 (Berkeley) 9/23/93
                     59:  */
                     60: 
                     61: 
                     62: #include <sys/param.h>
                     63: #include <sys/systm.h>
                     64: #include <sys/proc.h>
                     65: #include <sys/file.h>
                     66: #include <sys/namei.h>
                     67: #include <sys/vnode.h>
                     68: #include <sys/ktrace.h>
                     69: #include <sys/malloc.h>
                     70: #include <sys/syslog.h>
                     71: 
                     72: #include <sys/mount.h>
                     73: 
                     74: #if KTRACE
                     75: 
                     76: struct ktr_header *
                     77: ktrgetheader(type)
                     78:        int type;
                     79: {
                     80:        register struct ktr_header *kth;
                     81:        struct proc *p = current_proc();        /* XXX */
                     82: 
                     83:        MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 
                     84:                M_TEMP, M_WAITOK);
                     85:        kth->ktr_type = type;
                     86:        microtime(&kth->ktr_time);
                     87:        kth->ktr_pid = p->p_pid;
                     88:        bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN);
                     89:        return (kth);
                     90: }
                     91: 
                     92: void
                     93: ktrsyscall(vp, code, argsize, args)
                     94:        struct vnode *vp;
                     95:        register_t code;
                     96:        size_t argsize;
                     97:        register_t args[];
                     98: {
                     99:        struct  ktr_header *kth;
                    100:        struct  ktr_syscall *ktp;
                    101:        register len = sizeof(struct ktr_syscall) + argsize;
                    102:        struct proc *p = current_proc();        /* XXX */
                    103:        register_t *argp;
                    104:        int i;
                    105: 
                    106:        p->p_traceflag |= KTRFAC_ACTIVE;
                    107:        kth = ktrgetheader(KTR_SYSCALL);
                    108:        MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK);
                    109:        ktp->ktr_code = code;
                    110:        ktp->ktr_argsize = argsize;
                    111:        argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall));
                    112:        for (i = 0; i < (argsize / sizeof *argp); i++)
                    113:                *argp++ = args[i];
                    114:        kth->ktr_buf = (caddr_t)ktp;
                    115:        kth->ktr_len = len;
                    116:        ktrwrite(vp, kth);
                    117:        FREE(ktp, M_TEMP);
                    118:        FREE(kth, M_TEMP);
                    119:        p->p_traceflag &= ~KTRFAC_ACTIVE;
                    120: }
                    121: 
                    122: void
                    123: ktrsysret(vp, code, error, retval)
                    124:        struct vnode *vp;
                    125:        register_t code;
                    126:        int error;
                    127:        register_t retval;
                    128: {
                    129:        struct ktr_header *kth;
                    130:        struct ktr_sysret ktp;
                    131:        struct proc *p = current_proc();        /* XXX */
                    132: 
                    133:        p->p_traceflag |= KTRFAC_ACTIVE;
                    134:        kth = ktrgetheader(KTR_SYSRET);
                    135:        ktp.ktr_code = code;
                    136:        ktp.ktr_error = error;
                    137:        ktp.ktr_retval = retval;                /* what about val2 ? */
                    138: 
                    139:        kth->ktr_buf = (caddr_t)&ktp;
                    140:        kth->ktr_len = sizeof(struct ktr_sysret);
                    141: 
                    142:        ktrwrite(vp, kth);
                    143:        FREE(kth, M_TEMP);
                    144:        p->p_traceflag &= ~KTRFAC_ACTIVE;
                    145: }
                    146: 
                    147: void
                    148: ktrnamei(vp, path)
                    149:        struct vnode *vp;
                    150:        char *path;
                    151: {
                    152:        struct ktr_header *kth;
                    153:        struct proc *p = current_proc();        /* XXX */
                    154: 
                    155:        p->p_traceflag |= KTRFAC_ACTIVE;
                    156:        kth = ktrgetheader(KTR_NAMEI);
                    157:        kth->ktr_len = strlen(path);
                    158:        kth->ktr_buf = path;
                    159: 
                    160:        ktrwrite(vp, kth);
                    161:        FREE(kth, M_TEMP);
                    162:        p->p_traceflag &= ~KTRFAC_ACTIVE;
                    163: }
                    164: 
                    165: void
                    166: ktrgenio(vp, fd, rw, iov, len, error)
                    167:        struct vnode *vp;
                    168:        int fd;
                    169:        enum uio_rw rw;
                    170:        register struct iovec *iov;
                    171:        int len, error;
                    172: {
                    173:        struct ktr_header *kth;
                    174:        register struct ktr_genio *ktp;
                    175:        register caddr_t cp;
                    176:        register int resid = len, cnt;
                    177:        struct proc *p = current_proc();        /* XXX */
                    178:        
                    179:        if (error)
                    180:                return;
                    181:        p->p_traceflag |= KTRFAC_ACTIVE;
                    182:        kth = ktrgetheader(KTR_GENIO);
                    183:        MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len,
                    184:                M_TEMP, M_WAITOK);
                    185:        ktp->ktr_fd = fd;
                    186:        ktp->ktr_rw = rw;
                    187:        cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio));
                    188:        while (resid > 0) {
                    189:                if ((cnt = iov->iov_len) > resid)
                    190:                        cnt = resid;
                    191:                if (copyin(iov->iov_base, cp, (unsigned)cnt))
                    192:                        goto done;
                    193:                cp += cnt;
                    194:                resid -= cnt;
                    195:                iov++;
                    196:        }
                    197:        kth->ktr_buf = (caddr_t)ktp;
                    198:        kth->ktr_len = sizeof (struct ktr_genio) + len;
                    199: 
                    200:        ktrwrite(vp, kth);
                    201: done:
                    202:        FREE(kth, M_TEMP);
                    203:        FREE(ktp, M_TEMP);
                    204:        p->p_traceflag &= ~KTRFAC_ACTIVE;
                    205: }
                    206: 
                    207: void
                    208: ktrpsig(vp, sig, action, mask, code)
                    209:        struct vnode *vp;
                    210:        int sig;
                    211:        sig_t action;
                    212:        int mask, code;
                    213: {
                    214:        struct ktr_header *kth;
                    215:        struct ktr_psig kp;
                    216:        struct proc *p = current_proc();        /* XXX */
                    217: 
                    218:        p->p_traceflag |= KTRFAC_ACTIVE;
                    219:        kth = ktrgetheader(KTR_PSIG);
                    220:        kp.signo = (char)sig;
                    221:        kp.action = action;
                    222:        kp.mask = mask;
                    223:        kp.code = code;
                    224:        kth->ktr_buf = (caddr_t)&kp;
                    225:        kth->ktr_len = sizeof (struct ktr_psig);
                    226: 
                    227:        ktrwrite(vp, kth);
                    228:        FREE(kth, M_TEMP);
                    229:        p->p_traceflag &= ~KTRFAC_ACTIVE;
                    230: }
                    231: 
                    232: void
                    233: ktrcsw(vp, out, user)
                    234:        struct vnode *vp;
                    235:        int out, user;
                    236: {
                    237:        struct ktr_header *kth;
                    238:        struct  ktr_csw kc;
                    239:        struct proc *p = current_proc();        /* XXX */
                    240: 
                    241:        p->p_traceflag |= KTRFAC_ACTIVE;
                    242:        kth = ktrgetheader(KTR_CSW);
                    243:        kc.out = out;
                    244:        kc.user = user;
                    245:        kth->ktr_buf = (caddr_t)&kc;
                    246:        kth->ktr_len = sizeof (struct ktr_csw);
                    247: 
                    248:        ktrwrite(vp, kth);
                    249:        FREE(kth, M_TEMP);
                    250:        p->p_traceflag &= ~KTRFAC_ACTIVE;
                    251: }
                    252: 
                    253: /* Interface and common routines */
                    254: 
                    255: /*
                    256:  * ktrace system call
                    257:  */
                    258: struct ktrace_args {
                    259:        char *  fname;
                    260:        int             ops;
                    261:        int             facs;
                    262:        int             pid;
                    263: };
                    264: /* ARGSUSED */
                    265: int
                    266: ktrace(curp, uap, retval)
                    267:        struct proc *curp;
                    268:        register struct ktrace_args *uap;
                    269:        register_t *retval;
                    270: {
                    271:        register struct vnode *vp = NULL;
                    272:        register struct proc *p;
                    273:        struct pgrp *pg;
                    274:        int facs = SCARG(uap, facs) & ~KTRFAC_ROOT;
                    275:        int ops = KTROP(SCARG(uap, ops));
                    276:        int descend = SCARG(uap, ops) & KTRFLAG_DESCEND;
                    277:        int ret = 0;
                    278:        int error = 0;
                    279:        struct nameidata nd;
                    280: 
                    281:        curp->p_traceflag |= KTRFAC_ACTIVE;
                    282:        if (ops != KTROP_CLEAR) {
                    283:                /*
                    284:                 * an operation which requires a file argument.
                    285:                 */
                    286:                NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname),
                    287:                    curp);
                    288:                if (error = vn_open(&nd, FREAD|FWRITE, 0)) {
                    289:                        curp->p_traceflag &= ~KTRFAC_ACTIVE;
                    290:                        return (error);
                    291:                }
                    292:                vp = nd.ni_vp;
                    293:                VOP_UNLOCK(vp, 0, p);
                    294:                if (vp->v_type != VREG) {
                    295:                        (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
                    296:                        curp->p_traceflag &= ~KTRFAC_ACTIVE;
                    297:                        return (EACCES);
                    298:                }
                    299:        }
                    300:        /*
                    301:         * Clear all uses of the tracefile
                    302:         */
                    303:        if (ops == KTROP_CLEARFILE) {
                    304:                for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
                    305:                        if (p->p_tracep == vp) {
                    306:                                if (ktrcanset(curp, p)) {
                    307:                                        p->p_tracep = NULL;
                    308:                                        p->p_traceflag = 0;
                    309:                                        (void) vn_close(vp, FREAD|FWRITE,
                    310:                                                p->p_ucred, p);
                    311:                                } else
                    312:                                        error = EPERM;
                    313:                        }
                    314:                }
                    315:                goto done;
                    316:        }
                    317:        /*
                    318:         * need something to (un)trace (XXX - why is this here?)
                    319:         */
                    320:        if (!facs) {
                    321:                error = EINVAL;
                    322:                goto done;
                    323:        }
                    324:        /* 
                    325:         * do it
                    326:         */
                    327:        if (SCARG(uap, pid) < 0) {
                    328:                /*
                    329:                 * by process group
                    330:                 */
                    331:                pg = pgfind(-SCARG(uap, pid));
                    332:                if (pg == NULL) {
                    333:                        error = ESRCH;
                    334:                        goto done;
                    335:                }
                    336:                for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next)
                    337:                        if (descend)
                    338:                                ret |= ktrsetchildren(curp, p, ops, facs, vp);
                    339:                        else 
                    340:                                ret |= ktrops(curp, p, ops, facs, vp);
                    341:                                        
                    342:        } else {
                    343:                /*
                    344:                 * by pid
                    345:                 */
                    346:                p = pfind(SCARG(uap, pid));
                    347:                if (p == NULL) {
                    348:                        error = ESRCH;
                    349:                        goto done;
                    350:                }
                    351:                if (descend)
                    352:                        ret |= ktrsetchildren(curp, p, ops, facs, vp);
                    353:                else
                    354:                        ret |= ktrops(curp, p, ops, facs, vp);
                    355:        }
                    356:        if (!ret)
                    357:                error = EPERM;
                    358: done:
                    359:        if (vp != NULL)
                    360:                (void) vn_close(vp, FWRITE, curp->p_ucred, curp);
                    361:        curp->p_traceflag &= ~KTRFAC_ACTIVE;
                    362:        return (error);
                    363: }
                    364: 
                    365: int
                    366: ktrops(curp, p, ops, facs, vp)
                    367:        struct proc *p, *curp;
                    368:        int ops, facs;
                    369:        struct vnode *vp;
                    370: {
                    371: 
                    372:        if (!ktrcanset(curp, p))
                    373:                return (0);
                    374:        if (ops == KTROP_SET) {
                    375:                if (p->p_tracep != vp) { 
                    376:                        /*
                    377:                         * if trace file already in use, relinquish
                    378:                         */
                    379:                        if (p->p_tracep != NULL)
                    380:                                vrele(p->p_tracep);
                    381:                        VREF(vp);
                    382:                        p->p_tracep = vp;
                    383:                }
                    384:                p->p_traceflag |= facs;
                    385:                if (curp->p_ucred->cr_uid == 0)
                    386:                        p->p_traceflag |= KTRFAC_ROOT;
                    387:        } else {        
                    388:                /* KTROP_CLEAR */
                    389:                if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
                    390:                        /* no more tracing */
                    391:                        p->p_traceflag = 0;
                    392:                        if (p->p_tracep != NULL) {
                    393:                                vrele(p->p_tracep);
                    394:                                p->p_tracep = NULL;
                    395:                        }
                    396:                }
                    397:        }
                    398: 
                    399:        return (1);
                    400: }
                    401: 
                    402: ktrsetchildren(curp, top, ops, facs, vp)
                    403:        struct proc *curp, *top;
                    404:        int ops, facs;
                    405:        struct vnode *vp;
                    406: {
                    407:        register struct proc *p;
                    408:        register int ret = 0;
                    409: 
                    410:        p = top;
                    411:        for (;;) {
                    412:                ret |= ktrops(curp, p, ops, facs, vp);
                    413:                /*
                    414:                 * If this process has children, descend to them next,
                    415:                 * otherwise do any siblings, and if done with this level,
                    416:                 * follow back up the tree (but not past top).
                    417:                 */
                    418:                if (p->p_children.lh_first)
                    419:                        p = p->p_children.lh_first;
                    420:                else for (;;) {
                    421:                        if (p == top)
                    422:                                return (ret);
                    423:                        if (p->p_sibling.le_next) {
                    424:                                p = p->p_sibling.le_next;
                    425:                                break;
                    426:                        }
                    427:                        p = p->p_pptr;
                    428:                }
                    429:        }
                    430:        /*NOTREACHED*/
                    431: }
                    432: 
                    433: ktrwrite(vp, kth)
                    434:        struct vnode *vp;
                    435:        register struct ktr_header *kth;
                    436: {
                    437:        struct uio auio;
                    438:        struct iovec aiov[2];
                    439:        register struct proc *p = current_proc();       /* XXX */
                    440:        int error;
                    441: 
                    442:        if (vp == NULL)
                    443:                return;
                    444:        auio.uio_iov = &aiov[0];
                    445:        auio.uio_offset = 0;
                    446:        auio.uio_segflg = UIO_SYSSPACE;
                    447:        auio.uio_rw = UIO_WRITE;
                    448:        aiov[0].iov_base = (caddr_t)kth;
                    449:        aiov[0].iov_len = sizeof(struct ktr_header);
                    450:        auio.uio_resid = sizeof(struct ktr_header);
                    451:        auio.uio_iovcnt = 1;
                    452:        auio.uio_procp = (struct proc *)0;
                    453:        if (kth->ktr_len > 0) {
                    454:                auio.uio_iovcnt++;
                    455:                aiov[1].iov_base = kth->ktr_buf;
                    456:                aiov[1].iov_len = kth->ktr_len;
                    457:                auio.uio_resid += kth->ktr_len;
                    458:        }
                    459:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                    460:        error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred);
                    461:        VOP_UNLOCK(vp, 0, p);
                    462:        if (!error)
                    463:                return;
                    464:        /*
                    465:         * If error encountered, give up tracing on this vnode.
                    466:         */
                    467:        log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
                    468:            error);
                    469:        for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
                    470:                if (p->p_tracep == vp) {
                    471:                        p->p_tracep = NULL;
                    472:                        p->p_traceflag = 0;
                    473:                        vrele(vp);
                    474:                }
                    475:        }
                    476: }
                    477: 
                    478: /*
                    479:  * Return true if caller has permission to set the ktracing state
                    480:  * of target.  Essentially, the target can't possess any
                    481:  * more permissions than the caller.  KTRFAC_ROOT signifies that
                    482:  * root previously set the tracing status on the target process, and 
                    483:  * so, only root may further change it.
                    484:  *
                    485:  * TODO: check groups.  use caller effective gid.
                    486:  */
                    487: ktrcanset(callp, targetp)
                    488:        struct proc *callp, *targetp;
                    489: {
                    490:        register struct pcred *caller = callp->p_cred;
                    491:        register struct pcred *target = targetp->p_cred;
                    492: 
                    493:        if ((caller->pc_ucred->cr_uid == target->p_ruid &&
                    494:             target->p_ruid == target->p_svuid &&
                    495:             caller->p_rgid == target->p_rgid &&        /* XXX */
                    496:             target->p_rgid == target->p_svgid &&
                    497:             (targetp->p_traceflag & KTRFAC_ROOT) == 0) ||
                    498:             caller->pc_ucred->cr_uid == 0)
                    499:                return (1);
                    500: 
                    501:        return (0);
                    502: }
                    503: 
                    504: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.