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

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

unix.superglobalmegacorp.com

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