root/dev/systrace.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. systrace_lock
  2. systrace_unlock
  3. systracef_read
  4. systracef_write
  5. systracef_ioctl
  6. systracef_poll
  7. systracef_kqfilter
  8. systracef_stat
  9. systracef_close
  10. systraceattach
  11. systraceopen
  12. systraceclose
  13. systraceread
  14. systracewrite
  15. systraceioctl
  16. systracepoll
  17. systrace_wakeup
  18. systrace_find
  19. systrace_exit
  20. systrace_fork
  21. systrace_redirect
  22. systrace_seteuid
  23. systrace_setegid
  24. systrace_answer
  25. systrace_setscriptname
  26. systrace_inject
  27. systrace_prepinject
  28. systrace_policy
  29. systrace_processready
  30. systrace_getcwd
  31. systrace_io
  32. systrace_attach
  33. systrace_execve0
  34. systrace_execve1
  35. systrace_preprepl
  36. systrace_replace
  37. systrace_fname
  38. systrace_replacefree
  39. systrace_scriptname
  40. systrace_namei
  41. systrace_findpid
  42. systrace_detach
  43. systrace_closepolicy
  44. systrace_insert_process
  45. systrace_newpolicy
  46. systrace_msg_ask
  47. systrace_msg_result
  48. systrace_msg_emul
  49. systrace_msg_ugid
  50. systrace_make_msg
  51. systrace_msg_child
  52. systrace_msg_policyfree

    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 }

/* [<][>][^][v][top][bottom][index][help] */