[BACK]Return to systrace.c CVS log [TXT][DIR] Up to [local] / sys / dev

Annotation of sys/dev/systrace.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: systrace.c,v 1.44 2007/03/15 10:22:30 art Exp $       */
                      2: /*
                      3:  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  * 3. All advertising materials mentioning features or use of this software
                     15:  *    must display the following acknowledgement:
                     16:  *      This product includes software developed by Niels Provos.
                     17:  * 4. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     21:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     22:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     23:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     24:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     25:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     26:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     27:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     28:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     29:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31: #include <sys/param.h>
                     32: #include <sys/systm.h>
                     33: #include <sys/tree.h>
                     34: #include <sys/malloc.h>
                     35: #include <sys/syscall.h>
                     36: #include <sys/vnode.h>
                     37: #include <sys/errno.h>
                     38: #include <sys/conf.h>
                     39: #include <sys/device.h>
                     40: #include <sys/proc.h>
                     41: #include <sys/file.h>
                     42: #include <sys/filedesc.h>
                     43: #include <sys/filio.h>
                     44: #include <sys/signalvar.h>
                     45: #include <sys/rwlock.h>
                     46: #include <sys/pool.h>
                     47: #include <sys/mount.h>
                     48: #include <sys/namei.h>
                     49: #include <sys/poll.h>
                     50: #include <sys/ptrace.h>
                     51:
                     52: #include <compat/common/compat_util.h>
                     53:
                     54: #include <dev/systrace.h>
                     55:
                     56: void   systraceattach(int);
                     57:
                     58: int    systraceopen(dev_t, int, int, struct proc *);
                     59: int    systraceclose(dev_t, int, int, struct proc *);
                     60: int    systraceread(dev_t, struct uio *, int);
                     61: int    systracewrite(dev_t, struct uio *, int);
                     62: int    systraceioctl(dev_t, u_long, caddr_t, int, struct proc *);
                     63: int    systracepoll(dev_t, int, struct proc *);
                     64:
                     65: uid_t  systrace_seteuid(struct proc *,  uid_t);
                     66: gid_t  systrace_setegid(struct proc *,  gid_t);
                     67: int    systracef_read(struct file *, off_t *, struct uio *, struct ucred *);
                     68: int    systracef_write(struct file *, off_t *, struct uio *, struct ucred *);
                     69: int    systracef_ioctl(struct file *, u_long, caddr_t, struct proc *p);
                     70: int    systracef_poll(struct file *, int, struct proc *);
                     71: int    systracef_kqfilter(struct file *, struct knote *);
                     72: int    systracef_stat(struct file *, struct stat *, struct proc *);
                     73: int    systracef_close(struct file *, struct proc *);
                     74:
                     75: struct str_policy {
                     76:        TAILQ_ENTRY(str_policy) next;
                     77:
                     78:        int nr;
                     79:
                     80:        struct emul *emul;      /* Is only valid for this emulation */
                     81:
                     82:        int refcount;
                     83:
                     84:        int nsysent;
                     85:        u_char *sysent;
                     86: };
                     87:
                     88: struct str_inject {
                     89:        caddr_t kaddr;
                     90:        caddr_t uaddr;
                     91:        size_t  len;
                     92: };
                     93:
                     94: #define STR_PROC_ONQUEUE       0x01
                     95: #define STR_PROC_WAITANSWER    0x02
                     96: #define STR_PROC_SYSCALLRES    0x04
                     97: #define STR_PROC_REPORT                0x08    /* Report emulation */
                     98: #define STR_PROC_NEEDSEQNR     0x10    /* Answer must quote seqnr */
                     99: #define STR_PROC_SETEUID       0x20    /* Elevate privileges */
                    100: #define STR_PROC_SETEGID       0x40
                    101:
                    102: struct str_process {
                    103:        TAILQ_ENTRY(str_process) next;
                    104:        TAILQ_ENTRY(str_process) msg_next;
                    105:
                    106:        struct proc *proc;
                    107:        pid_t pid;
                    108:
                    109:        struct fsystrace *parent;
                    110:        struct str_policy *policy;
                    111:
                    112:        struct systrace_replace *replace;
                    113:        char *fname[SYSTR_MAXFNAME];
                    114:        size_t nfname;
                    115:
                    116:        int flags;
                    117:        short answer;
                    118:        short error;
                    119:        u_int16_t seqnr;        /* expected reply sequence number */
                    120:
                    121:        uid_t seteuid;
                    122:        uid_t saveuid;
                    123:        gid_t setegid;
                    124:        gid_t savegid;
                    125:
                    126:        int isscript;
                    127:        char scriptname[MAXPATHLEN];
                    128:
                    129:        struct str_message msg;
                    130:
                    131:        caddr_t sg;
                    132:        struct str_inject injects[SYSTR_MAXINJECTS];
                    133:        int  injectind;
                    134: };
                    135:
                    136: struct rwlock systrace_lck;
                    137:
                    138: static __inline void
                    139: systrace_lock(void)
                    140: {
                    141:        rw_enter_write(&systrace_lck);
                    142: }
                    143:
                    144: static __inline void
                    145: systrace_unlock(void)
                    146: {
                    147:        rw_exit_write(&systrace_lck);
                    148: }
                    149:
                    150: /* Needs to be called with fst locked */
                    151:
                    152: int    systrace_attach(struct fsystrace *, pid_t);
                    153: int    systrace_detach(struct str_process *);
                    154: int    systrace_answer(struct str_process *, struct systrace_answer *);
                    155: int     systrace_setscriptname(struct str_process *,
                    156:            struct systrace_scriptname *);
                    157: int     systrace_prepinject(struct str_process *, struct systrace_inject *);
                    158: int     systrace_inject(struct str_process *, int);
                    159: int    systrace_io(struct str_process *, struct systrace_io *);
                    160: int    systrace_policy(struct fsystrace *, struct systrace_policy *);
                    161: int    systrace_preprepl(struct str_process *, struct systrace_replace *);
                    162: int    systrace_replace(struct str_process *, size_t, register_t []);
                    163: int    systrace_getcwd(struct fsystrace *, struct str_process *);
                    164: int    systrace_fname(struct str_process *, caddr_t, size_t);
                    165: void   systrace_replacefree(struct str_process *);
                    166:
                    167: int    systrace_processready(struct str_process *);
                    168: struct proc *systrace_find(struct str_process *);
                    169: struct str_process *systrace_findpid(struct fsystrace *fst, pid_t pid);
                    170: void   systrace_wakeup(struct fsystrace *);
                    171: void   systrace_closepolicy(struct fsystrace *, struct str_policy *);
                    172: int    systrace_insert_process(struct fsystrace *, struct proc *);
                    173: struct str_policy *systrace_newpolicy(struct fsystrace *, int);
                    174: int    systrace_msg_child(struct fsystrace *, struct str_process *, pid_t);
                    175: int    systrace_msg_policyfree(struct fsystrace *, struct str_policy *);
                    176: int    systrace_msg_ask(struct fsystrace *, struct str_process *,
                    177:            int, size_t, register_t []);
                    178: int    systrace_msg_result(struct fsystrace *, struct str_process *,
                    179:            int, int, size_t, register_t [], register_t []);
                    180: int    systrace_msg_emul(struct fsystrace *, struct str_process *);
                    181: int    systrace_msg_ugid(struct fsystrace *, struct str_process *);
                    182: int    systrace_make_msg(struct str_process *, int);
                    183:
                    184: static struct fileops systracefops = {
                    185:        systracef_read,
                    186:        systracef_write,
                    187:        systracef_ioctl,
                    188:        systracef_poll,
                    189:        systracef_kqfilter,
                    190:        systracef_stat,
                    191:        systracef_close
                    192: };
                    193:
                    194: struct pool systr_proc_pl;
                    195: struct pool systr_policy_pl;
                    196:
                    197: int systrace_debug = 0;
                    198:
                    199: #define DPRINTF(y)     if (systrace_debug) printf y;
                    200:
                    201: /* ARGSUSED */
                    202: int
                    203: systracef_read(fp, poff, uio, cred)
                    204:        struct file *fp;
                    205:        off_t *poff;
                    206:        struct uio *uio;
                    207:        struct ucred *cred;
                    208: {
                    209:        struct fsystrace *fst = (struct fsystrace *)fp->f_data;
                    210:        struct str_process *process;
                    211:        int error = 0;
                    212:
                    213:        if (uio->uio_resid != sizeof(struct str_message))
                    214:                return (EINVAL);
                    215:
                    216:  again:
                    217:        systrace_lock();
                    218:        rw_enter_write(&fst->lock);
                    219:        systrace_unlock();
                    220:        if ((process = TAILQ_FIRST(&fst->messages)) != NULL) {
                    221:                error = uiomove((caddr_t)&process->msg,
                    222:                    sizeof(struct str_message), uio);
                    223:                if (!error) {
                    224:                        TAILQ_REMOVE(&fst->messages, process, msg_next);
                    225:                        CLR(process->flags, STR_PROC_ONQUEUE);
                    226:
                    227:                        if (SYSTR_MSG_NOPROCESS(process))
                    228:                                pool_put(&systr_proc_pl, process);
                    229:
                    230:                }
                    231:        } else if (TAILQ_FIRST(&fst->processes) == NULL) {
                    232:                /* EOF situation */
                    233:                ;
                    234:        } else {
                    235:                if (fp->f_flag & FNONBLOCK)
                    236:                        error = EAGAIN;
                    237:                else {
                    238:                        rw_exit_write(&fst->lock);
                    239:                        error = tsleep(fst, PWAIT|PCATCH, "systrrd", 0);
                    240:                        if (error)
                    241:                                goto out;
                    242:                        goto again;
                    243:                }
                    244:
                    245:        }
                    246:
                    247:        rw_exit_write(&fst->lock);
                    248:  out:
                    249:        return (error);
                    250: }
                    251:
                    252: /* ARGSUSED */
                    253: int
                    254: systracef_write(fp, poff, uio, cred)
                    255:        struct file *fp;
                    256:        off_t *poff;
                    257:        struct uio *uio;
                    258:        struct ucred *cred;
                    259: {
                    260:        return (EIO);
                    261: }
                    262:
                    263: #define POLICY_VALID(x)        ((x) == SYSTR_POLICY_PERMIT || \
                    264:                         (x) == SYSTR_POLICY_ASK || \
                    265:                         (x) == SYSTR_POLICY_NEVER)
                    266:
                    267: /* ARGSUSED */
                    268: int
                    269: systracef_ioctl(fp, cmd, data, p)
                    270:        struct file *fp;
                    271:        u_long cmd;
                    272:        caddr_t data;
                    273:        struct proc *p;
                    274: {
                    275:        int ret = 0;
                    276:        struct fsystrace *fst = (struct fsystrace *)fp->f_data;
                    277:        struct filedesc *fdp;
                    278:        struct str_process *strp;
                    279:        pid_t pid = 0;
                    280:
                    281:        switch (cmd) {
                    282:        case FIONBIO:
                    283:        case FIOASYNC:
                    284:                return (0);
                    285:
                    286:        case STRIOCDETACH:
                    287:        case STRIOCREPORT:
                    288:                pid = *(pid_t *)data;
                    289:                if (!pid)
                    290:                        ret = EINVAL;
                    291:                break;
                    292:        case STRIOCANSWER:
                    293:                pid = ((struct systrace_answer *)data)->stra_pid;
                    294:                if (!pid)
                    295:                        ret = EINVAL;
                    296:                break;
                    297:        case STRIOCIO:
                    298:                pid = ((struct systrace_io *)data)->strio_pid;
                    299:                if (!pid)
                    300:                        ret = EINVAL;
                    301:                break;
                    302:        case STRIOCSCRIPTNAME:
                    303:                pid = ((struct systrace_scriptname *)data)->sn_pid;
                    304:                if (!pid)
                    305:                        ret = EINVAL;
                    306:                break;
                    307:        case STRIOCINJECT:
                    308:                pid = ((struct systrace_inject *)data)->stri_pid;
                    309:                if (!pid)
                    310:                        ret = EINVAL;
                    311:                break;
                    312:        case STRIOCGETCWD:
                    313:                pid = *(pid_t *)data;
                    314:                if (!pid)
                    315:                        ret = EINVAL;
                    316:                break;
                    317:        case STRIOCATTACH:
                    318:        case STRIOCRESCWD:
                    319:        case STRIOCPOLICY:
                    320:                break;
                    321:        case STRIOCREPLACE:
                    322:                pid = ((struct systrace_replace *)data)->strr_pid;
                    323:                if (!pid)
                    324:                        ret = EINVAL;
                    325:                break;
                    326:        default:
                    327:                ret = EINVAL;
                    328:                break;
                    329:        }
                    330:
                    331:        if (ret)
                    332:                return (ret);
                    333:
                    334:        systrace_lock();
                    335:        rw_enter_write(&fst->lock);
                    336:        systrace_unlock();
                    337:        if (pid) {
                    338:                strp = systrace_findpid(fst, pid);
                    339:                if (strp == NULL) {
                    340:                        ret = ESRCH;
                    341:                        goto unlock;
                    342:                }
                    343:        }
                    344:
                    345:        switch (cmd) {
                    346:        case STRIOCATTACH:
                    347:                pid = *(pid_t *)data;
                    348:                if (!pid)
                    349:                        ret = EINVAL;
                    350:                else
                    351:                        ret = systrace_attach(fst, pid);
                    352:                DPRINTF(("%s: attach to %u: %d\n", __func__, pid, ret));
                    353:                break;
                    354:        case STRIOCDETACH:
                    355:                ret = systrace_detach(strp);
                    356:                break;
                    357:        case STRIOCREPORT:
                    358:                SET(strp->flags, STR_PROC_REPORT);
                    359:                break;
                    360:        case STRIOCANSWER:
                    361:                ret = systrace_answer(strp, (struct systrace_answer *)data);
                    362:                break;
                    363:        case STRIOCIO:
                    364:                ret = systrace_io(strp, (struct systrace_io *)data);
                    365:                break;
                    366:        case STRIOCSCRIPTNAME:
                    367:                ret = systrace_setscriptname(strp,
                    368:                    (struct systrace_scriptname *)data);
                    369:                break;
                    370:        case STRIOCINJECT:
                    371:                ret = systrace_prepinject(strp, (struct systrace_inject *)data);
                    372:                break;
                    373:        case STRIOCPOLICY:
                    374:                ret = systrace_policy(fst, (struct systrace_policy *)data);
                    375:                break;
                    376:        case STRIOCREPLACE:
                    377:                ret = systrace_preprepl(strp, (struct systrace_replace *)data);
                    378:                break;
                    379:        case STRIOCRESCWD:
                    380:                if (!fst->fd_pid) {
                    381:                        ret = EINVAL;
                    382:                        break;
                    383:                }
                    384:                fdp = p->p_fd;
                    385:
                    386:                /* Release cwd from other process */
                    387:                if (fdp->fd_cdir)
                    388:                        vrele(fdp->fd_cdir);
                    389:                if (fdp->fd_rdir)
                    390:                        vrele(fdp->fd_rdir);
                    391:                /* This restores the cwd we had before */
                    392:                fdp->fd_cdir = fst->fd_cdir;
                    393:                fdp->fd_rdir = fst->fd_rdir;
                    394:                /* Note that we are normal again */
                    395:                fst->fd_pid = 0;
                    396:                fst->fd_cdir = fst->fd_rdir = NULL;
                    397:                break;
                    398:        case STRIOCGETCWD:
                    399:                ret = systrace_getcwd(fst, strp);
                    400:                break;
                    401:        default:
                    402:                ret = EINVAL;
                    403:                break;
                    404:        }
                    405:
                    406:  unlock:
                    407:        rw_exit_write(&fst->lock);
                    408:        return (ret);
                    409: }
                    410:
                    411: /* ARGSUSED */
                    412: int
                    413: systracef_poll(fp, events, p)
                    414:        struct file *fp;
                    415:        int events;
                    416:        struct proc *p;
                    417: {
                    418:        struct fsystrace *fst = (struct fsystrace *)fp->f_data;
                    419:        int revents = 0;
                    420:
                    421:        if ((events & (POLLIN | POLLRDNORM)) == 0)
                    422:                return (0);
                    423:
                    424:        systrace_lock();
                    425:        rw_enter_write(&fst->lock);
                    426:        systrace_unlock();
                    427:        if (!TAILQ_EMPTY(&fst->messages))
                    428:                revents = events & (POLLIN | POLLRDNORM);
                    429:        else
                    430:                selrecord(p, &fst->si);
                    431:        rw_exit_write(&fst->lock);
                    432:
                    433:        return (revents);
                    434: }
                    435:
                    436: /* ARGSUSED */
                    437: int
                    438: systracef_kqfilter(fp, kn)
                    439:        struct file *fp;
                    440:        struct knote *kn;
                    441: {
                    442:        return (1);
                    443: }
                    444:
                    445: /* ARGSUSED */
                    446: int
                    447: systracef_stat(fp, sb, p)
                    448:        struct file *fp;
                    449:        struct stat *sb;
                    450:        struct proc *p;
                    451: {
                    452:        return (EOPNOTSUPP);
                    453: }
                    454:
                    455: /* ARGSUSED */
                    456: int
                    457: systracef_close(fp, p)
                    458:        struct file *fp;
                    459:        struct proc *p;
                    460: {
                    461:        struct fsystrace *fst = (struct fsystrace *)fp->f_data;
                    462:        struct str_process *strp;
                    463:        struct str_policy *strpol;
                    464:
                    465:        systrace_lock();
                    466:        rw_enter_write(&fst->lock);
                    467:        systrace_unlock();
                    468:
                    469:        /* Untrace all processes */
                    470:        for (strp = TAILQ_FIRST(&fst->processes); strp;
                    471:            strp = TAILQ_FIRST(&fst->processes)) {
                    472:                struct proc *q = strp->proc;
                    473:
                    474:                systrace_detach(strp);
                    475:                psignal(q, SIGKILL);
                    476:        }
                    477:
                    478:        /* Clean up fork and exit messages */
                    479:        for (strp = TAILQ_FIRST(&fst->messages); strp;
                    480:            strp = TAILQ_FIRST(&fst->messages)) {
                    481:                TAILQ_REMOVE(&fst->messages, strp, msg_next);
                    482:                pool_put(&systr_proc_pl, strp);
                    483:        }
                    484:
                    485:        /* Clean up all policies */
                    486:        for (strpol = TAILQ_FIRST(&fst->policies); strpol;
                    487:            strpol = TAILQ_FIRST(&fst->policies))
                    488:                systrace_closepolicy(fst, strpol);
                    489:
                    490:        /* Release vnodes */
                    491:        if (fst->fd_cdir)
                    492:                vrele(fst->fd_cdir);
                    493:        if (fst->fd_rdir)
                    494:                vrele(fst->fd_rdir);
                    495:        rw_exit_write(&fst->lock);
                    496:
                    497:        FREE(fp->f_data, M_XDATA);
                    498:        fp->f_data = NULL;
                    499:
                    500:        return (0);
                    501: }
                    502:
                    503: void
                    504: systraceattach(int n)
                    505: {
                    506:        pool_init(&systr_proc_pl, sizeof(struct str_process), 0, 0, 0,
                    507:            "strprocpl", NULL);
                    508:        pool_init(&systr_policy_pl, sizeof(struct str_policy), 0, 0, 0,
                    509:            "strpolpl", NULL);
                    510:        rw_init(&systrace_lck, "systrace");
                    511: }
                    512:
                    513: int
                    514: systraceopen(dev, flag, mode, p)
                    515:        dev_t   dev;
                    516:        int     flag;
                    517:        int     mode;
                    518:        struct proc *p;
                    519: {
                    520:        return (0);
                    521: }
                    522:
                    523: int
                    524: systraceclose(dev, flag, mode, p)
                    525:        dev_t   dev;
                    526:        int     flag;
                    527:        int     mode;
                    528:        struct proc *p;
                    529: {
                    530:        return (0);
                    531: }
                    532:
                    533: int
                    534: systraceread(dev, uio, ioflag)
                    535:        dev_t   dev;
                    536:        struct uio *uio;
                    537:        int     ioflag;
                    538: {
                    539:        return (EIO);
                    540: }
                    541:
                    542: int
                    543: systracewrite(dev, uio, ioflag)
                    544:        dev_t   dev;
                    545:        struct uio *uio;
                    546:        int     ioflag;
                    547: {
                    548:        return (EIO);
                    549: }
                    550:
                    551: int
                    552: systraceioctl(dev, cmd, data, flag, p)
                    553:        dev_t   dev;
                    554:        u_long  cmd;
                    555:        caddr_t data;
                    556:        int     flag;
                    557:        struct proc *p;
                    558: {
                    559:        struct file *f;
                    560:        struct fsystrace *fst = NULL;
                    561:        int fd, error;
                    562:
                    563:        switch (cmd) {
                    564:        case STRIOCCLONE:
                    565:                MALLOC(fst, struct fsystrace *, sizeof(struct fsystrace),
                    566:                    M_XDATA, M_WAITOK);
                    567:
                    568:                memset(fst, 0, sizeof(struct fsystrace));
                    569:                rw_init(&fst->lock, "systrace");
                    570:                TAILQ_INIT(&fst->processes);
                    571:                TAILQ_INIT(&fst->messages);
                    572:                TAILQ_INIT(&fst->policies);
                    573:
                    574:                if (suser(p, 0) == 0)
                    575:                        fst->issuser = 1;
                    576:                fst->p_ruid = p->p_cred->p_ruid;
                    577:                fst->p_rgid = p->p_cred->p_rgid;
                    578:
                    579:                error = falloc(p, &f, &fd);
                    580:                if (error) {
                    581:                        FREE(fst, M_XDATA);
                    582:                        return (error);
                    583:                }
                    584:                f->f_flag = FREAD | FWRITE;
                    585:                f->f_type = DTYPE_SYSTRACE;
                    586:                f->f_ops = &systracefops;
                    587:                f->f_data = (caddr_t) fst;
                    588:                *(int *)data = fd;
                    589:                FILE_SET_MATURE(f);
                    590:                break;
                    591:        default:
                    592:                error = EINVAL;
                    593:                break;
                    594:        }
                    595:        return (error);
                    596: }
                    597:
                    598: int
                    599: systracepoll(dev, events, p)
                    600:        dev_t   dev;
                    601:        int     events;
                    602:        struct proc *p;
                    603: {
                    604:        return (seltrue(dev, events, p));
                    605: }
                    606:
                    607: void
                    608: systrace_wakeup(struct fsystrace *fst)
                    609: {
                    610:        wakeup((caddr_t)fst);
                    611:        selwakeup(&fst->si);
                    612: }
                    613:
                    614: struct proc *
                    615: systrace_find(struct str_process *strp)
                    616: {
                    617:        struct proc *proc;
                    618:
                    619:        if ((proc = pfind(strp->pid)) == NULL)
                    620:                return (NULL);
                    621:
                    622:        if (proc != strp->proc)
                    623:                return (NULL);
                    624:
                    625:        if (!ISSET(proc->p_flag, P_SYSTRACE))
                    626:                return (NULL);
                    627:
                    628:        return (proc);
                    629: }
                    630:
                    631: void
                    632: systrace_exit(struct proc *proc)
                    633: {
                    634:        struct str_process *strp;
                    635:        struct fsystrace *fst;
                    636:
                    637:        systrace_lock();
                    638:        strp = proc->p_systrace;
                    639:        if (strp != NULL) {
                    640:                fst = strp->parent;
                    641:                rw_enter_write(&fst->lock);
                    642:                systrace_unlock();
                    643:
                    644:                /* Insert Exit message */
                    645:                systrace_msg_child(fst, strp, -1);
                    646:
                    647:                systrace_detach(strp);
                    648:                rw_exit_write(&fst->lock);
                    649:        } else
                    650:                systrace_unlock();
                    651:        atomic_clearbits_int(&proc->p_flag, P_SYSTRACE);
                    652: }
                    653:
                    654: void
                    655: systrace_fork(struct proc *oldproc, struct proc *p)
                    656: {
                    657:        struct str_process *oldstrp, *strp;
                    658:        struct fsystrace *fst;
                    659:
                    660:        systrace_lock();
                    661:        oldstrp = oldproc->p_systrace;
                    662:        if (oldstrp == NULL) {
                    663:                systrace_unlock();
                    664:                return;
                    665:        }
                    666:
                    667:        fst = oldstrp->parent;
                    668:        rw_enter_write(&fst->lock);
                    669:        systrace_unlock();
                    670:
                    671:        if (systrace_insert_process(fst, p))
                    672:                goto out;
                    673:        if ((strp = systrace_findpid(fst, p->p_pid)) == NULL)
                    674:                panic("systrace_fork");
                    675:
                    676:        /* Reference policy */
                    677:        if ((strp->policy = oldstrp->policy) != NULL)
                    678:                strp->policy->refcount++;
                    679:
                    680:        /* Insert fork message */
                    681:        systrace_msg_child(fst, oldstrp, p->p_pid);
                    682:  out:
                    683:        rw_exit_write(&fst->lock);
                    684: }
                    685:
                    686: #define REACQUIRE_LOCK do { \
                    687:        systrace_lock(); \
                    688:        strp = p->p_systrace; \
                    689:        if (strp == NULL) { \
                    690:                systrace_unlock(); \
                    691:                return (error); \
                    692:        } \
                    693:        fst = strp->parent; \
                    694:        rw_enter_write(&fst->lock); \
                    695:        systrace_unlock(); \
                    696: } while (0)
                    697:
                    698: int
                    699: systrace_redirect(int code, struct proc *p, void *v, register_t *retval)
                    700: {
                    701:        struct sysent *callp;
                    702:        struct str_process *strp;
                    703:        struct str_policy *strpolicy;
                    704:        struct fsystrace *fst = NULL;
                    705:        struct emul *oldemul;
                    706:        struct pcred *pc;
                    707:        uid_t olduid;
                    708:        gid_t oldgid;
                    709:        int policy, error = 0, report = 0, maycontrol = 0, issuser = 0;
                    710:
                    711:        systrace_lock();
                    712:        strp = p->p_systrace;
                    713:        if (strp == NULL) {
                    714:                systrace_unlock();
                    715:                return (EINVAL);
                    716:        }
                    717:
                    718:        if (code < 0 || code >= p->p_emul->e_nsysent) {
                    719:                systrace_unlock();
                    720:                return (EINVAL);
                    721:        }
                    722:
                    723:        KASSERT(strp->proc == p);
                    724:
                    725:        fst = strp->parent;
                    726:
                    727:        rw_enter_write(&fst->lock);
                    728:        systrace_unlock();
                    729:
                    730:        /*
                    731:         * We can not monitor a SUID process unless we are root,
                    732:         * but we wait until it executes something unprivileged.
                    733:         * A non-root user may only monitor if the real uid and
                    734:         * real gid match the monitored process.  Changing the
                    735:         * uid or gid causes P_SUGID to be set.
                    736:         */
                    737:        if (fst->issuser) {
                    738:                maycontrol = 1;
                    739:                issuser = 1;
                    740:        } else if (!ISSET(p->p_flag, P_SUGID) &&
                    741:            !ISSET(p->p_flag, P_SUGIDEXEC)) {
                    742:                maycontrol = fst->p_ruid == p->p_cred->p_ruid &&
                    743:                    fst->p_rgid == p->p_cred->p_rgid;
                    744:        }
                    745:
                    746:        if (!maycontrol) {
                    747:                policy = SYSTR_POLICY_PERMIT;
                    748:        } else {
                    749:                /* Find out current policy */
                    750:                if ((strpolicy = strp->policy) == NULL)
                    751:                        policy = SYSTR_POLICY_ASK;
                    752:                else {
                    753:                        if (code >= strpolicy->nsysent)
                    754:                                policy = SYSTR_POLICY_NEVER;
                    755:                        else
                    756:                                policy = strpolicy->sysent[code];
                    757:                }
                    758:        }
                    759:
                    760:        callp = p->p_emul->e_sysent + code;
                    761:
                    762:        /* Fast-path */
                    763:        if (policy != SYSTR_POLICY_ASK) {
                    764:                if (policy != SYSTR_POLICY_PERMIT) {
                    765:                        if (policy > 0)
                    766:                                error = policy;
                    767:                        else
                    768:                                error = EPERM;
                    769:                }
                    770:                systrace_replacefree(strp);
                    771:                rw_exit_write(&fst->lock);
                    772:                if (policy == SYSTR_POLICY_PERMIT)
                    773:                        error = (*callp->sy_call)(p, v, retval);
                    774:                return (error);
                    775:        }
                    776:
                    777:        /*
                    778:         * Reset our stackgap allocation.  Note that when resetting
                    779:         * the stackgap allocation, we expect to get the same address
                    780:         * base; i.e. that stackgap_init() is idempotent.
                    781:         */
                    782:        systrace_inject(strp, 0 /* Just reset internal state */);
                    783:        strp->sg = stackgap_init(p->p_emul);
                    784:
                    785:        /* Puts the current process to sleep, return unlocked */
                    786:        error = systrace_msg_ask(fst, strp, code, callp->sy_argsize, v);
                    787:        /* lock has been released in systrace_msg_ask() */
                    788:
                    789:        if (error)
                    790:                return (error);
                    791:
                    792:        /* We might have detached by now for some reason */
                    793:        systrace_lock();
                    794:        if ((strp = p->p_systrace) == NULL) {
                    795:                systrace_unlock();
                    796:                return (error);
                    797:        }
                    798:
                    799:        fst = strp->parent;
                    800:        rw_enter_write(&fst->lock);
                    801:        systrace_unlock();
                    802:
                    803:        if (strp->answer == SYSTR_POLICY_NEVER) {
                    804:                error = strp->error;
                    805:                systrace_replacefree(strp);
                    806:                goto out_unlock;
                    807:        }
                    808:
                    809:        if (ISSET(strp->flags, STR_PROC_SYSCALLRES)) {
                    810:                CLR(strp->flags, STR_PROC_SYSCALLRES);
                    811:                report = 1;
                    812:        }
                    813:
                    814:        error = systrace_inject(strp, 1/* Perform copies */);
                    815:        /* Replace the arguments if necessary */
                    816:        if (!error && strp->replace != NULL)
                    817:                error = systrace_replace(strp, callp->sy_argsize, v);
                    818:        if (error)
                    819:                goto out_unlock;
                    820:
                    821:        oldemul = p->p_emul;
                    822:        pc = p->p_cred;
                    823:        olduid = pc->p_ruid;
                    824:        oldgid = pc->p_rgid;
                    825:
                    826:        /* Elevate privileges as desired */
                    827:        if (issuser) {
                    828:                if (ISSET(strp->flags, STR_PROC_SETEUID))
                    829:                        strp->saveuid = systrace_seteuid(p, strp->seteuid);
                    830:                if (ISSET(strp->flags, STR_PROC_SETEGID))
                    831:                        strp->savegid = systrace_setegid(p, strp->setegid);
                    832:        } else
                    833:                CLR(strp->flags, STR_PROC_SETEUID|STR_PROC_SETEGID);
                    834:
                    835:        rw_exit_write(&fst->lock);
                    836:
                    837:        error = (*callp->sy_call)(p, v, retval);
                    838:
                    839:        /* Return to old privileges */
                    840:        systrace_lock();
                    841:        if ((strp = p->p_systrace) == NULL) {
                    842:                systrace_unlock();
                    843:                return (error);
                    844:        }
                    845:
                    846:        if (issuser) {
                    847:                if (ISSET(strp->flags, STR_PROC_SETEUID)) {
                    848:                        if (pc->pc_ucred->cr_uid == strp->seteuid)
                    849:                                systrace_seteuid(p, strp->saveuid);
                    850:                        CLR(strp->flags, STR_PROC_SETEUID);
                    851:                }
                    852:                if (ISSET(strp->flags, STR_PROC_SETEGID)) {
                    853:                        if (pc->pc_ucred->cr_gid == strp->setegid)
                    854:                                systrace_setegid(p, strp->savegid);
                    855:                        CLR(strp->flags, STR_PROC_SETEGID);
                    856:                }
                    857:        }
                    858:
                    859:        systrace_replacefree(strp);
                    860:
                    861:        if (ISSET(p->p_flag, P_SUGID) || ISSET(p->p_flag, P_SUGIDEXEC)) {
                    862:                if ((fst = strp->parent) == NULL || !fst->issuser) {
                    863:                        systrace_unlock();
                    864:                        return (error);
                    865:                }
                    866:        }
                    867:
                    868:        /* Report change in emulation */
                    869:
                    870:        /* See if we should force a report */
                    871:        if (ISSET(strp->flags, STR_PROC_REPORT)) {
                    872:                CLR(strp->flags, STR_PROC_REPORT);
                    873:                oldemul = NULL;
                    874:        }
                    875:
                    876:        /* Acquire lock */
                    877:        fst = strp->parent;
                    878:        rw_enter_write(&fst->lock);
                    879:        systrace_unlock();
                    880:
                    881:        if (p->p_emul != oldemul) {
                    882:                /* Old policy is without meaning now */
                    883:                if (strp->policy) {
                    884:                        systrace_closepolicy(fst, strp->policy);
                    885:                        strp->policy = NULL;
                    886:                }
                    887:                systrace_msg_emul(fst, strp);
                    888:
                    889:                REACQUIRE_LOCK;
                    890:        }
                    891:
                    892:        /* Report if effective uid or gid changed */
                    893:        if (olduid != p->p_cred->p_ruid ||
                    894:            oldgid != p->p_cred->p_rgid) {
                    895:                systrace_msg_ugid(fst, strp);
                    896:
                    897:                REACQUIRE_LOCK;
                    898:        }
                    899:
                    900:        /* Report result from system call */
                    901:        if (report) {
                    902:                systrace_msg_result(fst, strp, error, code,
                    903:                    callp->sy_argsize, v, retval);
                    904:
                    905:                /* not locked */
                    906:                goto out;
                    907:        }
                    908:
                    909: out_unlock:
                    910:        rw_exit_write(&fst->lock);
                    911: out:
                    912:        return (error);
                    913: }
                    914:
                    915: uid_t
                    916: systrace_seteuid(struct proc *p,  uid_t euid)
                    917: {
                    918:        struct pcred *pc = p->p_cred;
                    919:        uid_t oeuid = pc->pc_ucred->cr_uid;
                    920:
                    921:        if (pc->pc_ucred->cr_uid == euid)
                    922:                return (oeuid);
                    923:
                    924:        /*
                    925:         * Copy credentials so other references do not see our changes.
                    926:         */
                    927:        pc->pc_ucred = crcopy(pc->pc_ucred);
                    928:        pc->pc_ucred->cr_uid = euid;
                    929:        atomic_setbits_int(&p->p_flag, P_SUGID);
                    930:
                    931:        return (oeuid);
                    932: }
                    933:
                    934: gid_t
                    935: systrace_setegid(struct proc *p,  gid_t egid)
                    936: {
                    937:        struct pcred *pc = p->p_cred;
                    938:        gid_t oegid = pc->pc_ucred->cr_gid;
                    939:
                    940:        if (pc->pc_ucred->cr_gid == egid)
                    941:                return (oegid);
                    942:
                    943:        /*
                    944:         * Copy credentials so other references do not see our changes.
                    945:         */
                    946:        pc->pc_ucred = crcopy(pc->pc_ucred);
                    947:        pc->pc_ucred->cr_gid = egid;
                    948:        atomic_setbits_int(&p->p_flag, P_SUGID);
                    949:
                    950:        return (oegid);
                    951: }
                    952:
                    953: /* Called with fst locked */
                    954:
                    955: int
                    956: systrace_answer(struct str_process *strp, struct systrace_answer *ans)
                    957: {
                    958:        int error = 0;
                    959:
                    960:        DPRINTF(("%s: %u: policy %d\n", __func__,
                    961:            ans->stra_pid, ans->stra_policy));
                    962:
                    963:        if (!POLICY_VALID(ans->stra_policy)) {
                    964:                error = EINVAL;
                    965:                goto out;
                    966:        }
                    967:
                    968:        /* Check if answer is in sync with us */
                    969:        if (ans->stra_seqnr != strp->seqnr) {
                    970:                error = ESRCH;
                    971:                goto out;
                    972:        }
                    973:
                    974:        if ((error = systrace_processready(strp)) != 0)
                    975:                goto out;
                    976:
                    977:        strp->answer = ans->stra_policy;
                    978:        strp->error = ans->stra_error;
                    979:        if (!strp->error)
                    980:                strp->error = EPERM;
                    981:        if (ISSET(ans->stra_flags, SYSTR_FLAGS_RESULT))
                    982:                SET(strp->flags, STR_PROC_SYSCALLRES);
                    983:
                    984:        /* See if we should elevate privileges for this system call */
                    985:        if (ISSET(ans->stra_flags, SYSTR_FLAGS_SETEUID)) {
                    986:                SET(strp->flags, STR_PROC_SETEUID);
                    987:                strp->seteuid = ans->stra_seteuid;
                    988:        }
                    989:        if (ISSET(ans->stra_flags, SYSTR_FLAGS_SETEGID)) {
                    990:                SET(strp->flags, STR_PROC_SETEGID);
                    991:                strp->setegid = ans->stra_setegid;
                    992:        }
                    993:
                    994:        /* Clearing the flag indicates to the process that it woke up */
                    995:        CLR(strp->flags, STR_PROC_WAITANSWER);
                    996:        wakeup(strp);
                    997:  out:
                    998:
                    999:        return (error);
                   1000: }
                   1001:
                   1002: int
                   1003: systrace_setscriptname(struct str_process *strp, struct systrace_scriptname *ans)
                   1004: {
                   1005:        strlcpy(strp->scriptname,
                   1006:            ans->sn_scriptname, sizeof(strp->scriptname));
                   1007:
                   1008:        return (0);
                   1009: }
                   1010:
                   1011: int
                   1012: systrace_inject(struct str_process *strp, int docopy)
                   1013: {
                   1014:        int ind, ret = 0;
                   1015:
                   1016:        for (ind = 0; ind < strp->injectind; ind++) {
                   1017:                struct str_inject *inject = &strp->injects[ind];
                   1018:                if (!ret && docopy &&
                   1019:                    copyout(inject->kaddr, inject->uaddr, inject->len))
                   1020:                        ret = EINVAL;
                   1021:                free(inject->kaddr, M_XDATA);
                   1022:        }
                   1023:
                   1024:        strp->injectind = 0;
                   1025:        return (ret);
                   1026: }
                   1027:
                   1028: int
                   1029: systrace_prepinject(struct str_process *strp, struct systrace_inject *inj)
                   1030: {
                   1031:        caddr_t udata, kaddr = NULL;
                   1032:        int ret = 0;
                   1033:        struct str_inject *inject;
                   1034:
                   1035:        if (strp->injectind >= SYSTR_MAXINJECTS)
                   1036:                return (ENOBUFS);
                   1037:
                   1038:        udata = stackgap_alloc(&strp->sg, inj->stri_len);
                   1039:        if (udata == NULL)
                   1040:                return (ENOMEM);
                   1041:
                   1042:        /*
                   1043:         * We have infact forced a maximum length on stri_len because
                   1044:         * of the stackgap.
                   1045:         */
                   1046:
                   1047:        kaddr = malloc(inj->stri_len, M_XDATA, M_WAITOK);
                   1048:        ret = copyin(inj->stri_addr, kaddr, inj->stri_len);
                   1049:        if (ret) {
                   1050:                free(kaddr, M_XDATA);
                   1051:                return (ret);
                   1052:        }
                   1053:
                   1054:        inject = &strp->injects[strp->injectind++];
                   1055:        inject->kaddr = kaddr;
                   1056:        inject->uaddr = inj->stri_addr = udata;
                   1057:        inject->len = inj->stri_len;
                   1058:
                   1059:        return (0);
                   1060: }
                   1061:
                   1062: int
                   1063: systrace_policy(struct fsystrace *fst, struct systrace_policy *pol)
                   1064: {
                   1065:        struct str_policy *strpol;
                   1066:        struct str_process *strp;
                   1067:
                   1068:        switch(pol->strp_op) {
                   1069:        case SYSTR_POLICY_NEW:
                   1070:                DPRINTF(("%s: new, ents %d\n", __func__,
                   1071:                            pol->strp_maxents));
                   1072:                if (pol->strp_maxents <= 0 || pol->strp_maxents > 1024)
                   1073:                        return (EINVAL);
                   1074:                strpol = systrace_newpolicy(fst, pol->strp_maxents);
                   1075:                if (strpol == NULL)
                   1076:                        return (ENOBUFS);
                   1077:                pol->strp_num = strpol->nr;
                   1078:                break;
                   1079:        case SYSTR_POLICY_ASSIGN:
                   1080:                DPRINTF(("%s: %d -> pid %d\n", __func__,
                   1081:                            pol->strp_num, pol->strp_pid));
                   1082:
                   1083:                /* Find right policy by number */
                   1084:                TAILQ_FOREACH(strpol, &fst->policies, next)
                   1085:                    if (strpol->nr == pol->strp_num)
                   1086:                            break;
                   1087:                if (strpol == NULL)
                   1088:                        return (EINVAL);
                   1089:
                   1090:                strp = systrace_findpid(fst, pol->strp_pid);
                   1091:                if (strp == NULL)
                   1092:                        return (EINVAL);
                   1093:
                   1094:                /* Check that emulation matches */
                   1095:                if (strpol->emul && strpol->emul != strp->proc->p_emul)
                   1096:                        return (EINVAL);
                   1097:
                   1098:                if (strp->policy)
                   1099:                        systrace_closepolicy(fst, strp->policy);
                   1100:                strp->policy = strpol;
                   1101:
                   1102:                /* LRU for policy use */
                   1103:                TAILQ_REMOVE(&fst->policies, strpol, next);
                   1104:                TAILQ_INSERT_TAIL(&fst->policies, strpol, next);
                   1105:                strpol->refcount++;
                   1106:
                   1107:                /* Record emulation for this policy */
                   1108:                if (strpol->emul == NULL)
                   1109:                        strpol->emul = strp->proc->p_emul;
                   1110:
                   1111:                break;
                   1112:        case SYSTR_POLICY_MODIFY:
                   1113:                DPRINTF(("%s: %d: code %d -> policy %d\n", __func__,
                   1114:                    pol->strp_num, pol->strp_code, pol->strp_policy));
                   1115:                if (!POLICY_VALID(pol->strp_policy))
                   1116:                        return (EINVAL);
                   1117:                TAILQ_FOREACH(strpol, &fst->policies, next)
                   1118:                    if (strpol->nr == pol->strp_num)
                   1119:                            break;
                   1120:                if (strpol == NULL)
                   1121:                        return (EINVAL);
                   1122:                if (pol->strp_code < 0 || pol->strp_code >= strpol->nsysent)
                   1123:                        return (EINVAL);
                   1124:                strpol->sysent[pol->strp_code] = pol->strp_policy;
                   1125:                break;
                   1126:        default:
                   1127:                return (EINVAL);
                   1128:        }
                   1129:
                   1130:        return (0);
                   1131: }
                   1132:
                   1133: int
                   1134: systrace_processready(struct str_process *strp)
                   1135: {
                   1136:        if (ISSET(strp->flags, STR_PROC_ONQUEUE))
                   1137:                return (EBUSY);
                   1138:
                   1139:        if (!ISSET(strp->flags, STR_PROC_WAITANSWER))
                   1140:                return (EBUSY);
                   1141:
                   1142:        if (strp->proc->p_stat != SSLEEP)
                   1143:                return (EBUSY);
                   1144:
                   1145:        return (0);
                   1146: }
                   1147:
                   1148: int
                   1149: systrace_getcwd(struct fsystrace *fst, struct str_process *strp)
                   1150: {
                   1151:        struct filedesc *myfdp, *fdp;
                   1152:        int error;
                   1153:
                   1154:        DPRINTF(("%s: %d\n", __func__, strp->pid));
                   1155:
                   1156:        error = systrace_processready(strp);
                   1157:        if (error)
                   1158:                return (error);
                   1159:
                   1160:        myfdp = curproc->p_fd;
                   1161:        fdp = strp->proc->p_fd;
                   1162:        if (myfdp == NULL || fdp == NULL)
                   1163:                return (EINVAL);
                   1164:
                   1165:        /* Store our current values */
                   1166:        fst->fd_pid = strp->pid;
                   1167:        fst->fd_cdir = myfdp->fd_cdir;
                   1168:        fst->fd_rdir = myfdp->fd_rdir;
                   1169:
                   1170:        if ((myfdp->fd_cdir = fdp->fd_cdir) != NULL)
                   1171:                VREF(myfdp->fd_cdir);
                   1172:        if ((myfdp->fd_rdir = fdp->fd_rdir) != NULL)
                   1173:                VREF(myfdp->fd_rdir);
                   1174:
                   1175:        return (0);
                   1176: }
                   1177:
                   1178: int
                   1179: systrace_io(struct str_process *strp, struct systrace_io *io)
                   1180: {
                   1181:        struct proc *p = curproc, *t = strp->proc;
                   1182:        struct uio uio;
                   1183:        struct iovec iov;
                   1184:        int error = 0;
                   1185:
                   1186:        DPRINTF(("%s: %u: %p(%lu)\n", __func__,
                   1187:            io->strio_pid, io->strio_offs, (u_long)io->strio_len));
                   1188:
                   1189:        switch (io->strio_op) {
                   1190:        case SYSTR_READ:
                   1191:                uio.uio_rw = UIO_READ;
                   1192:                break;
                   1193:        case SYSTR_WRITE:
                   1194:                uio.uio_rw = UIO_WRITE;
                   1195:                break;
                   1196:        default:
                   1197:                return (EINVAL);
                   1198:        }
                   1199:
                   1200:        error = systrace_processready(strp);
                   1201:        if (error)
                   1202:                goto out;
                   1203:
                   1204:        iov.iov_base = io->strio_addr;
                   1205:        iov.iov_len = io->strio_len;
                   1206:        uio.uio_iov = &iov;
                   1207:        uio.uio_iovcnt = 1;
                   1208:        uio.uio_offset = (off_t)(u_long)io->strio_offs;
                   1209:        uio.uio_resid = io->strio_len;
                   1210:        uio.uio_segflg = UIO_USERSPACE;
                   1211:        uio.uio_procp = p;
                   1212:
                   1213:        error = process_domem(p, t, &uio, PT_WRITE_I);
                   1214:        io->strio_len -= uio.uio_resid;
                   1215:  out:
                   1216:
                   1217:        return (error);
                   1218: }
                   1219:
                   1220: int
                   1221: systrace_attach(struct fsystrace *fst, pid_t pid)
                   1222: {
                   1223:        int error = 0;
                   1224:        struct proc *proc, *p = curproc;
                   1225:
                   1226:        if ((proc = pfind(pid)) == NULL) {
                   1227:                error = ESRCH;
                   1228:                goto out;
                   1229:        }
                   1230:
                   1231:        if (ISSET(proc->p_flag, P_INEXEC)) {
                   1232:                error = EAGAIN;
                   1233:                goto out;
                   1234:        }
                   1235:
                   1236:        /*
                   1237:         * You can't attach to a process if:
                   1238:         *      (1) it's the process that's doing the attaching,
                   1239:         */
                   1240:        if (proc->p_pid == p->p_pid) {
                   1241:                error = EINVAL;
                   1242:                goto out;
                   1243:        }
                   1244:
                   1245:        /*
                   1246:         *      (2) it's a system process
                   1247:         */
                   1248:        if (ISSET(proc->p_flag, P_SYSTEM)) {
                   1249:                error = EPERM;
                   1250:                goto out;
                   1251:        }
                   1252:
                   1253:        /*
                   1254:         *      (3) it's being traced already
                   1255:         */
                   1256:        if (ISSET(proc->p_flag, P_SYSTRACE)) {
                   1257:                error = EBUSY;
                   1258:                goto out;
                   1259:        }
                   1260:
                   1261:        /*
                   1262:         *      (4) it's not owned by you, or the last exec
                   1263:         *          gave us setuid/setgid privs (unless
                   1264:         *          you're root), or...
                   1265:         *
                   1266:         *      [Note: once P_SUGID or P_SUGIDEXEC gets set in execve(),
                   1267:         *      it stays set until the process does another execve(). Hence
                   1268:         *      this prevents a setuid process which revokes its
                   1269:         *      special privileges using setuid() from being
                   1270:         *      traced. This is good security.]
                   1271:         */
                   1272:        if ((proc->p_cred->p_ruid != p->p_cred->p_ruid ||
                   1273:                ISSET(proc->p_flag, P_SUGID) ||
                   1274:                ISSET(proc->p_flag, P_SUGIDEXEC)) &&
                   1275:            (error = suser(p, 0)) != 0)
                   1276:                goto out;
                   1277:
                   1278:        /*
                   1279:         *      (5) ...it's init, which controls the security level
                   1280:         *          of the entire system, and the system was not
                   1281:         *          compiled with permanently insecure mode turned
                   1282:         *          on.
                   1283:         */
                   1284:        if ((proc->p_pid == 1) && (securelevel > -1)) {
                   1285:                error = EPERM;
                   1286:                goto out;
                   1287:        }
                   1288:
                   1289:        error = systrace_insert_process(fst, proc);
                   1290:
                   1291:  out:
                   1292:        return (error);
                   1293: }
                   1294:
                   1295: void
                   1296: systrace_execve0(struct proc *p)
                   1297: {
                   1298:        struct str_process *strp;
                   1299:
                   1300:        systrace_lock();
                   1301:        strp = p->p_systrace;
                   1302:        strp->isscript = 0;
                   1303:        systrace_unlock();
                   1304: }
                   1305:
                   1306: void
                   1307: systrace_execve1(char *path, struct proc *p)
                   1308: {
                   1309:        struct str_process *strp;
                   1310:        struct fsystrace *fst;
                   1311:        struct str_msg_execve *msg_execve;
                   1312:
                   1313:        do {
                   1314:                systrace_lock();
                   1315:                strp = p->p_systrace;
                   1316:                if (strp == NULL) {
                   1317:                        systrace_unlock();
                   1318:                        return;
                   1319:                }
                   1320:
                   1321:                msg_execve = &strp->msg.msg_data.msg_execve;
                   1322:                fst = strp->parent;
                   1323:                rw_enter_write(&fst->lock);
                   1324:                systrace_unlock();
                   1325:
                   1326:                /*
                   1327:                 * susers will get the execve call anyway.  Also, if
                   1328:                 * we're not allowed to control the process, escape.
                   1329:                 */
                   1330:
                   1331:                if (fst->issuser ||
                   1332:                    fst->p_ruid != p->p_cred->p_ruid ||
                   1333:                    fst->p_rgid != p->p_cred->p_rgid) {
                   1334:                        rw_exit_write(&fst->lock);
                   1335:                        return;
                   1336:                }
                   1337:                strlcpy(msg_execve->path, path, MAXPATHLEN);
                   1338:        } while (systrace_make_msg(strp, SYSTR_MSG_EXECVE) != 0);
                   1339: }
                   1340:
                   1341: /* Prepare to replace arguments */
                   1342:
                   1343: int
                   1344: systrace_preprepl(struct str_process *strp, struct systrace_replace *repl)
                   1345: {
                   1346:        size_t len;
                   1347:        int i, ret = 0;
                   1348:
                   1349:        ret = systrace_processready(strp);
                   1350:        if (ret)
                   1351:                return (ret);
                   1352:
                   1353:        if (strp->replace != NULL) {
                   1354:                free(strp->replace, M_XDATA);
                   1355:                strp->replace = NULL;
                   1356:        }
                   1357:
                   1358:        if (repl->strr_nrepl < 0 || repl->strr_nrepl > SYSTR_MAXARGS)
                   1359:                return (EINVAL);
                   1360:
                   1361:        for (i = 0, len = 0; i < repl->strr_nrepl; i++) {
                   1362:                if (repl->strr_argind[i] < 0 ||
                   1363:                    repl->strr_argind[i] >= SYSTR_MAXARGS)
                   1364:                        return (EINVAL);
                   1365:                if (repl->strr_offlen[i] == 0)
                   1366:                        continue;
                   1367:                len += repl->strr_offlen[i];
                   1368:                if (repl->strr_offlen[i] > SYSTR_MAXREPLEN ||
                   1369:                    repl->strr_off[i] > SYSTR_MAXREPLEN ||
                   1370:                    len > SYSTR_MAXREPLEN)
                   1371:                        return (EINVAL);
                   1372:                if (repl->strr_offlen[i] + repl->strr_off[i] > len)
                   1373:                        return (EINVAL);
                   1374:        }
                   1375:
                   1376:        /* Make sure that the length adds up */
                   1377:        if (repl->strr_len != len)
                   1378:                return (EINVAL);
                   1379:
                   1380:        /* Check against a maximum length */
                   1381:        if (repl->strr_len > SYSTR_MAXREPLEN)
                   1382:                return (EINVAL);
                   1383:
                   1384:        strp->replace = (struct systrace_replace *)
                   1385:            malloc(sizeof(struct systrace_replace) + len, M_XDATA, M_WAITOK);
                   1386:
                   1387:        memcpy(strp->replace, repl, sizeof(struct systrace_replace));
                   1388:        ret = copyin(repl->strr_base, strp->replace + 1, len);
                   1389:        if (ret) {
                   1390:                free(strp->replace, M_XDATA);
                   1391:                strp->replace = NULL;
                   1392:                return (ret);
                   1393:        }
                   1394:
                   1395:        /* Adjust the offset */
                   1396:        repl = strp->replace;
                   1397:        repl->strr_base = (caddr_t)(repl + 1);
                   1398:
                   1399:        return (0);
                   1400: }
                   1401:
                   1402: /*
                   1403:  * Replace the arguments with arguments from the monitoring process.
                   1404:  */
                   1405:
                   1406: int
                   1407: systrace_replace(struct str_process *strp, size_t argsize, register_t args[])
                   1408: {
                   1409:        struct systrace_replace *repl = strp->replace;
                   1410:        caddr_t kdata, kbase;
                   1411:        caddr_t udata, ubase;
                   1412:        int i, maxarg, ind, ret = 0;
                   1413:
                   1414:        maxarg = argsize/sizeof(register_t);
                   1415:        ubase = stackgap_alloc(&strp->sg, repl->strr_len);
                   1416:        if (ubase == NULL) {
                   1417:                ret = EINVAL;
                   1418:                goto out;
                   1419:        }
                   1420:
                   1421:        kbase = repl->strr_base;
                   1422:        for (i = 0; i < maxarg && i < repl->strr_nrepl; i++) {
                   1423:                ind = repl->strr_argind[i];
                   1424:                if (ind < 0 || ind >= maxarg) {
                   1425:                        ret = EINVAL;
                   1426:                        goto out;
                   1427:                }
                   1428:                if (repl->strr_offlen[i] == 0) {
                   1429:                        args[ind] = repl->strr_off[i];
                   1430:                        continue;
                   1431:                }
                   1432:                kdata = kbase + repl->strr_off[i];
                   1433:                if (repl->strr_flags[i] & SYSTR_NOLINKS) {
                   1434:                        ret = systrace_fname(strp, kdata, repl->strr_offlen[i]);
                   1435:                        if (ret != 0)
                   1436:                                goto out;
                   1437:                }
                   1438:                udata = ubase + repl->strr_off[i];
                   1439:                if (copyout(kdata, udata, repl->strr_offlen[i])) {
                   1440:                        ret = EINVAL;
                   1441:                        goto out;
                   1442:                }
                   1443:
                   1444:                /* Replace the argument with the new address */
                   1445:                args[ind] = (register_t)udata;
                   1446:        }
                   1447:
                   1448:  out:
                   1449:        return (ret);
                   1450: }
                   1451:
                   1452: int
                   1453: systrace_fname(struct str_process *strp, caddr_t kdata, size_t len)
                   1454: {
                   1455:        if (strp->nfname >= SYSTR_MAXFNAME || len < 1)
                   1456:                return EINVAL;
                   1457:
                   1458:        strp->fname[strp->nfname] = kdata;
                   1459:        strp->fname[strp->nfname][len - 1] = '\0';
                   1460:        strp->nfname++;
                   1461:
                   1462:        return 0;
                   1463: }
                   1464:
                   1465: void
                   1466: systrace_replacefree(struct str_process *strp)
                   1467: {
                   1468:        if (strp->replace != NULL) {
                   1469:                free(strp->replace, M_XDATA);
                   1470:                strp->replace = NULL;
                   1471:        }
                   1472:        while (strp->nfname > 0) {
                   1473:                strp->nfname--;
                   1474:                strp->fname[strp->nfname] = NULL;
                   1475:        }
                   1476: }
                   1477: int
                   1478: systrace_scriptname(struct proc *p, char *dst)
                   1479: {
                   1480:        struct str_process *strp;
                   1481:        struct fsystrace *fst;
                   1482:        int error = 0;
                   1483:
                   1484:        systrace_lock();
                   1485:        strp = p->p_systrace;
                   1486:        fst = strp->parent;
                   1487:
                   1488:        rw_enter_write(&fst->lock);
                   1489:        systrace_unlock();
                   1490:
                   1491:        if (!fst->issuser && (ISSET(p->p_flag, P_SUGID) ||
                   1492:                ISSET(p->p_flag, P_SUGIDEXEC) ||
                   1493:                fst->p_ruid != p->p_cred->p_ruid ||
                   1494:                fst->p_rgid != p->p_cred->p_rgid)) {
                   1495:                error = EPERM;
                   1496:                goto out;
                   1497:        }
                   1498:
                   1499:        if (strp != NULL) {
                   1500:                if (strp->scriptname[0] == '\0') {
                   1501:                        error = ENOENT;
                   1502:                        goto out;
                   1503:                }
                   1504:
                   1505:                strlcpy(dst, strp->scriptname, MAXPATHLEN);
                   1506:                strp->isscript = 1;
                   1507:        }
                   1508:
                   1509:  out:
                   1510:        strp->scriptname[0] = '\0';
                   1511:        rw_exit_write(&fst->lock);
                   1512:
                   1513:        return (error);
                   1514: }
                   1515:
                   1516: void
                   1517: systrace_namei(struct nameidata *ndp)
                   1518: {
                   1519:        struct str_process *strp;
                   1520:        struct fsystrace *fst;
                   1521:        struct componentname *cnp = &ndp->ni_cnd;
                   1522:        size_t i;
                   1523:        int hamper = 0;
                   1524:
                   1525:        systrace_lock();
                   1526:        strp = cnp->cn_proc->p_systrace;
                   1527:        if (strp != NULL) {
                   1528:                fst = strp->parent;
                   1529:                rw_enter_write(&fst->lock);
                   1530:                systrace_unlock();
                   1531:
                   1532:                for (i = 0; i < strp->nfname; i++)
                   1533:                        if (strcmp(cnp->cn_pnbuf, strp->fname[i]) == 0) {
                   1534:                                hamper = 1;
                   1535:                                break;
                   1536:                        }
                   1537:
                   1538:                if (!hamper && strp->isscript &&
                   1539:                    strcmp(cnp->cn_pnbuf, strp->scriptname) == 0)
                   1540:                        hamper = 1;
                   1541:
                   1542:                rw_exit_write(&fst->lock);
                   1543:        } else
                   1544:                systrace_unlock();
                   1545:
                   1546:        if (hamper) {
                   1547:                /* ELOOP if namei() tries to readlink */
                   1548:                ndp->ni_loopcnt = MAXSYMLINKS;
                   1549:                cnp->cn_flags &= ~FOLLOW;
                   1550:                cnp->cn_flags |= NOFOLLOW;
                   1551:        }
                   1552: }
                   1553:
                   1554: struct str_process *
                   1555: systrace_findpid(struct fsystrace *fst, pid_t pid)
                   1556: {
                   1557:        struct str_process *strp;
                   1558:        struct proc *proc = NULL;
                   1559:
                   1560:        TAILQ_FOREACH(strp, &fst->processes, next)
                   1561:            if (strp->pid == pid)
                   1562:                    break;
                   1563:
                   1564:        if (strp == NULL)
                   1565:                return (NULL);
                   1566:
                   1567:        proc = systrace_find(strp);
                   1568:
                   1569:        return (proc ? strp : NULL);
                   1570: }
                   1571:
                   1572: int
                   1573: systrace_detach(struct str_process *strp)
                   1574: {
                   1575:        struct proc *proc;
                   1576:        struct fsystrace *fst = NULL;
                   1577:        int error = 0;
                   1578:
                   1579:        DPRINTF(("%s: Trying to detach from %d\n", __func__, strp->pid));
                   1580:
                   1581:        if ((proc = systrace_find(strp)) != NULL) {
                   1582:                atomic_clearbits_int(&proc->p_flag, P_SYSTRACE);
                   1583:                proc->p_systrace = NULL;
                   1584:        } else
                   1585:                error = ESRCH;
                   1586:
                   1587:        if (ISSET(strp->flags, STR_PROC_WAITANSWER)) {
                   1588:                CLR(strp->flags, STR_PROC_WAITANSWER);
                   1589:                wakeup(strp);
                   1590:        }
                   1591:
                   1592:        fst = strp->parent;
                   1593:        systrace_wakeup(fst);
                   1594:
                   1595:        if (ISSET(strp->flags, STR_PROC_ONQUEUE))
                   1596:                TAILQ_REMOVE(&fst->messages, strp, msg_next);
                   1597:
                   1598:        TAILQ_REMOVE(&fst->processes, strp, next);
                   1599:        fst->nprocesses--;
                   1600:
                   1601:        if (strp->policy)
                   1602:                systrace_closepolicy(fst, strp->policy);
                   1603:        systrace_replacefree(strp);
                   1604:        pool_put(&systr_proc_pl, strp);
                   1605:
                   1606:        return (error);
                   1607: }
                   1608:
                   1609: void
                   1610: systrace_closepolicy(struct fsystrace *fst, struct str_policy *policy)
                   1611: {
                   1612:        if (--policy->refcount)
                   1613:                return;
                   1614:
                   1615:        fst->npolicies--;
                   1616:
                   1617:        if (policy->nsysent)
                   1618:                free(policy->sysent, M_XDATA);
                   1619:
                   1620:        TAILQ_REMOVE(&fst->policies, policy, next);
                   1621:
                   1622:        pool_put(&systr_policy_pl, policy);
                   1623: }
                   1624:
                   1625:
                   1626: int
                   1627: systrace_insert_process(struct fsystrace *fst, struct proc *proc)
                   1628: {
                   1629:        struct str_process *strp;
                   1630:
                   1631:        strp = pool_get(&systr_proc_pl, PR_NOWAIT);
                   1632:        if (strp == NULL)
                   1633:                return (ENOBUFS);
                   1634:
                   1635:        memset((caddr_t)strp, 0, sizeof(struct str_process));
                   1636:        strp->pid = proc->p_pid;
                   1637:        strp->proc = proc;
                   1638:        strp->parent = fst;
                   1639:
                   1640:        TAILQ_INSERT_TAIL(&fst->processes, strp, next);
                   1641:        fst->nprocesses++;
                   1642:
                   1643:        proc->p_systrace = strp;
                   1644:        atomic_setbits_int(&proc->p_flag, P_SYSTRACE);
                   1645:
                   1646:        return (0);
                   1647: }
                   1648:
                   1649: struct str_policy *
                   1650: systrace_newpolicy(struct fsystrace *fst, int maxents)
                   1651: {
                   1652:        struct str_policy *pol;
                   1653:        int i;
                   1654:
                   1655:        if (fst->npolicies > SYSTR_MAX_POLICIES && !fst->issuser) {
                   1656:                struct str_policy *tmp;
                   1657:
                   1658:                /* Try to find a policy for freeing */
                   1659:                TAILQ_FOREACH(tmp, &fst->policies, next) {
                   1660:                        if (tmp->refcount == 1)
                   1661:                                break;
                   1662:                }
                   1663:
                   1664:                if (tmp == NULL)
                   1665:                        return (NULL);
                   1666:
                   1667:                /* Notify userland about freed policy */
                   1668:                systrace_msg_policyfree(fst, tmp);
                   1669:                /* Free this policy */
                   1670:                systrace_closepolicy(fst, tmp);
                   1671:        }
                   1672:
                   1673:        pol = pool_get(&systr_policy_pl, PR_NOWAIT);
                   1674:        if (pol == NULL)
                   1675:                return (NULL);
                   1676:
                   1677:        DPRINTF(("%s: allocating %d -> %lu\n", __func__,
                   1678:                     maxents, (u_long)maxents * sizeof(int)));
                   1679:
                   1680:        memset((caddr_t)pol, 0, sizeof(struct str_policy));
                   1681:
                   1682:        pol->sysent = (u_char *)malloc(maxents * sizeof(u_char),
                   1683:            M_XDATA, M_WAITOK);
                   1684:        pol->nsysent = maxents;
                   1685:        for (i = 0; i < maxents; i++)
                   1686:                pol->sysent[i] = SYSTR_POLICY_ASK;
                   1687:
                   1688:        fst->npolicies++;
                   1689:        pol->nr = fst->npolicynr++;
                   1690:        pol->refcount = 1;
                   1691:
                   1692:        TAILQ_INSERT_TAIL(&fst->policies, pol, next);
                   1693:
                   1694:        return (pol);
                   1695: }
                   1696:
                   1697: int
                   1698: systrace_msg_ask(struct fsystrace *fst, struct str_process *strp,
                   1699:     int code, size_t argsize, register_t args[])
                   1700: {
                   1701:        struct str_msg_ask *msg_ask = &strp->msg.msg_data.msg_ask;
                   1702:        int i;
                   1703:
                   1704:        msg_ask->code = code;
                   1705:        msg_ask->argsize = argsize;
                   1706:        for (i = 0; i < (argsize/sizeof(register_t)) && i < SYSTR_MAXARGS; i++)
                   1707:                msg_ask->args[i] = args[i];
                   1708:
                   1709:        return (systrace_make_msg(strp, SYSTR_MSG_ASK));
                   1710: }
                   1711:
                   1712: int
                   1713: systrace_msg_result(struct fsystrace *fst, struct str_process *strp,
                   1714:     int error, int code, size_t argsize, register_t args[], register_t rval[])
                   1715: {
                   1716:        struct str_msg_ask *msg_ask = &strp->msg.msg_data.msg_ask;
                   1717:        int i;
                   1718:
                   1719:        msg_ask->code = code;
                   1720:        msg_ask->argsize = argsize;
                   1721:        msg_ask->result = error;
                   1722:        for (i = 0; i < (argsize/sizeof(register_t)) && i < SYSTR_MAXARGS; i++)
                   1723:                msg_ask->args[i] = args[i];
                   1724:
                   1725:        msg_ask->rval[0] = rval[0];
                   1726:        msg_ask->rval[1] = rval[1];
                   1727:
                   1728:        return (systrace_make_msg(strp, SYSTR_MSG_RES));
                   1729: }
                   1730:
                   1731: int
                   1732: systrace_msg_emul(struct fsystrace *fst, struct str_process *strp)
                   1733: {
                   1734:        struct str_msg_emul *msg_emul = &strp->msg.msg_data.msg_emul;
                   1735:        struct proc *p = strp->proc;
                   1736:
                   1737:        memcpy(msg_emul->emul, p->p_emul->e_name, SYSTR_EMULEN);
                   1738:
                   1739:        return (systrace_make_msg(strp, SYSTR_MSG_EMUL));
                   1740: }
                   1741:
                   1742: int
                   1743: systrace_msg_ugid(struct fsystrace *fst, struct str_process *strp)
                   1744: {
                   1745:        struct str_msg_ugid *msg_ugid = &strp->msg.msg_data.msg_ugid;
                   1746:        struct proc *p = strp->proc;
                   1747:
                   1748:        msg_ugid->uid = p->p_cred->p_ruid;
                   1749:        msg_ugid->gid = p->p_cred->p_rgid;
                   1750:
                   1751:        return (systrace_make_msg(strp, SYSTR_MSG_UGID));
                   1752: }
                   1753:
                   1754: int
                   1755: systrace_make_msg(struct str_process *strp, int type)
                   1756: {
                   1757:        struct str_message *msg = &strp->msg;
                   1758:        struct fsystrace *fst = strp->parent;
                   1759:        int st, pri;
                   1760:
                   1761:        pri = PWAIT|PCATCH;
                   1762:        if (type == SYSTR_MSG_EXECVE)
                   1763:                pri &= ~PCATCH;
                   1764:
                   1765:        msg->msg_seqnr = ++strp->seqnr;
                   1766:        msg->msg_type = type;
                   1767:        msg->msg_pid = strp->pid;
                   1768:        if (strp->policy)
                   1769:                msg->msg_policy = strp->policy->nr;
                   1770:        else
                   1771:                msg->msg_policy = -1;
                   1772:
                   1773:        SET(strp->flags, STR_PROC_WAITANSWER);
                   1774:        if (ISSET(strp->flags, STR_PROC_ONQUEUE))
                   1775:                goto out;
                   1776:
                   1777:        TAILQ_INSERT_TAIL(&fst->messages, strp, msg_next);
                   1778:        SET(strp->flags, STR_PROC_ONQUEUE);
                   1779:
                   1780:  out:
                   1781:        systrace_wakeup(fst);
                   1782:
                   1783:        /* Release the lock - XXX */
                   1784:        rw_exit_write(&fst->lock);
                   1785:
                   1786:        while (1) {
                   1787:                st = tsleep(strp, pri, "systrmsg", 0);
                   1788:                if (st != 0)
                   1789:                        return (ERESTART);
                   1790:                /* If we detach, then everything is permitted */
                   1791:                if ((strp = curproc->p_systrace) == NULL)
                   1792:                        return (0);
                   1793:                if (!ISSET(strp->flags, STR_PROC_WAITANSWER))
                   1794:                        break;
                   1795:        }
                   1796:
                   1797:        return (0);
                   1798: }
                   1799:
                   1800: int
                   1801: systrace_msg_child(struct fsystrace *fst, struct str_process *strp, pid_t npid)
                   1802: {
                   1803:        struct str_process *nstrp;
                   1804:        struct str_message *msg;
                   1805:        struct str_msg_child *msg_child;
                   1806:
                   1807:        nstrp = pool_get(&systr_proc_pl, PR_WAITOK);
                   1808:        memset(nstrp, 0, sizeof(struct str_process));
                   1809:
                   1810:        DPRINTF(("%s: %p: pid %d -> pid %d\n", __func__,
                   1811:                    nstrp, strp->pid, npid));
                   1812:
                   1813:        msg = &nstrp->msg;
                   1814:        msg_child = &msg->msg_data.msg_child;
                   1815:
                   1816:        msg->msg_type = SYSTR_MSG_CHILD;
                   1817:        msg->msg_pid = strp->pid;
                   1818:        if (strp->policy)
                   1819:                msg->msg_policy = strp->policy->nr;
                   1820:        else
                   1821:                msg->msg_policy = -1;
                   1822:        msg_child->new_pid = npid;
                   1823:
                   1824:        TAILQ_INSERT_TAIL(&fst->messages, nstrp, msg_next);
                   1825:
                   1826:        systrace_wakeup(fst);
                   1827:
                   1828:        return (0);
                   1829: }
                   1830:
                   1831: int
                   1832: systrace_msg_policyfree(struct fsystrace *fst, struct str_policy *strpol)
                   1833: {
                   1834:        struct str_process *nstrp;
                   1835:        struct str_message *msg;
                   1836:
                   1837:        nstrp = pool_get(&systr_proc_pl, PR_WAITOK);
                   1838:        memset(nstrp, 0, sizeof(struct str_process));
                   1839:
                   1840:        DPRINTF(("%s: free %d\n", __func__, strpol->nr));
                   1841:
                   1842:        msg = &nstrp->msg;
                   1843:
                   1844:        msg->msg_type = SYSTR_MSG_POLICYFREE;
                   1845:        msg->msg_policy = strpol->nr;
                   1846:
                   1847:        TAILQ_INSERT_TAIL(&fst->messages, nstrp, msg_next);
                   1848:
                   1849:        systrace_wakeup(fst);
                   1850:
                   1851:        return (0);
                   1852: }

CVSweb