The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/filemon/filemon_wrapper.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2011, David E. O'Brien.
    3  * Copyright (c) 2009-2011, Juniper Networks, Inc.
    4  * Copyright (c) 2015-2016, EMC Corp.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY JUNIPER NETWORKS AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED. IN NO EVENT SHALL JUNIPER NETWORKS OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/11.2/sys/dev/filemon/filemon_wrapper.c 331722 2018-03-29 02:50:57Z eadler $");
   31 
   32 #include <sys/eventhandler.h>
   33 #include <sys/filedesc.h>
   34 #include <sys/imgact.h>
   35 #include <sys/priv.h>
   36 #include <sys/sx.h>
   37 #include <sys/sysent.h>
   38 #include <sys/vnode.h>
   39 
   40 #include "opt_compat.h"
   41 
   42 static eventhandler_tag filemon_exec_tag;
   43 static eventhandler_tag filemon_exit_tag;
   44 static eventhandler_tag filemon_fork_tag;
   45 
   46 static void
   47 filemon_output(struct filemon *filemon, char *msg, size_t len)
   48 {
   49         struct uio auio;
   50         struct iovec aiov;
   51         int error;
   52 
   53         if (filemon->fp == NULL)
   54                 return;
   55 
   56         aiov.iov_base = msg;
   57         aiov.iov_len = len;
   58         auio.uio_iov = &aiov;
   59         auio.uio_iovcnt = 1;
   60         auio.uio_resid = len;
   61         auio.uio_segflg = UIO_SYSSPACE;
   62         auio.uio_rw = UIO_WRITE;
   63         auio.uio_td = curthread;
   64         auio.uio_offset = (off_t) -1;
   65 
   66         if (filemon->fp->f_type == DTYPE_VNODE)
   67                 bwillwrite();
   68 
   69         error = fo_write(filemon->fp, &auio, filemon->cred, 0, curthread);
   70         if (error != 0 && filemon->error == 0)
   71                 filemon->error = error;
   72 }
   73 
   74 static int
   75 filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
   76 {
   77         int error, ret;
   78         size_t len;
   79         struct filemon *filemon;
   80 
   81         if ((ret = sys_chdir(td, uap)) == 0) {
   82                 if ((filemon = filemon_proc_get(curproc)) != NULL) {
   83                         if ((error = copyinstr(uap->path, filemon->fname1,
   84                             sizeof(filemon->fname1), NULL)) != 0) {
   85                                 filemon->error = error;
   86                                 goto copyfail;
   87                         }
   88 
   89                         len = snprintf(filemon->msgbufr,
   90                             sizeof(filemon->msgbufr), "C %d %s\n",
   91                             curproc->p_pid, filemon->fname1);
   92 
   93                         filemon_output(filemon, filemon->msgbufr, len);
   94 copyfail:
   95                         filemon_drop(filemon);
   96                 }
   97         }
   98 
   99         return (ret);
  100 }
  101 
  102 static void
  103 filemon_event_process_exec(void *arg __unused, struct proc *p,
  104     struct image_params *imgp)
  105 {
  106         struct filemon *filemon;
  107         size_t len;
  108 
  109         if ((filemon = filemon_proc_get(p)) != NULL) {
  110                 len = snprintf(filemon->msgbufr,
  111                     sizeof(filemon->msgbufr), "E %d %s\n",
  112                     p->p_pid,
  113                     imgp->execpath != NULL ? imgp->execpath : "<unknown>");
  114 
  115                 filemon_output(filemon, filemon->msgbufr, len);
  116 
  117                 /* If the credentials changed then cease tracing. */
  118                 if (imgp->newcred != NULL &&
  119                     imgp->credential_setid &&
  120                     priv_check_cred(filemon->cred,
  121                     PRIV_DEBUG_DIFFCRED, 0) != 0) {
  122                         /*
  123                          * It may have changed to NULL already, but
  124                          * will not be re-attached by anything else.
  125                          */
  126                         if (p->p_filemon != NULL) {
  127                                 KASSERT(p->p_filemon == filemon,
  128                                     ("%s: proc %p didn't have expected"
  129                                     " filemon %p", __func__, p, filemon));
  130                                 filemon_proc_drop(p);
  131                         }
  132                 }
  133 
  134 
  135                 filemon_drop(filemon);
  136         }
  137 }
  138 
  139 static void
  140 _filemon_wrapper_openat(struct thread *td, char *upath, int flags, int fd)
  141 {
  142         int error;
  143         size_t len;
  144         struct file *fp;
  145         struct filemon *filemon;
  146         char *atpath, *freepath;
  147         cap_rights_t rights;
  148 
  149         if ((filemon = filemon_proc_get(curproc)) != NULL) {
  150                 atpath = "";
  151                 freepath = NULL;
  152                 fp = NULL;
  153 
  154                 if ((error = copyinstr(upath, filemon->fname1,
  155                     sizeof(filemon->fname1), NULL)) != 0) {
  156                         filemon->error = error;
  157                         goto copyfail;
  158                 }
  159 
  160                 if (filemon->fname1[0] != '/' && fd != AT_FDCWD) {
  161                         /*
  162                          * rats - we cannot do too much about this.
  163                          * the trace should show a dir we read
  164                          * recently.. output an A record as a clue
  165                          * until we can do better.
  166                          * XXX: This may be able to come out with
  167                          * the namecache lookup now.
  168                          */
  169                         len = snprintf(filemon->msgbufr,
  170                             sizeof(filemon->msgbufr), "A %d %s\n",
  171                             curproc->p_pid, filemon->fname1);
  172                         filemon_output(filemon, filemon->msgbufr, len);
  173                         /*
  174                          * Try to resolve the path from the vnode using the
  175                          * namecache.  It may be inaccurate, but better
  176                          * than nothing.
  177                          */
  178                         if (getvnode(td, fd,
  179                             cap_rights_init(&rights, CAP_LOOKUP), &fp) == 0) {
  180                                 vn_fullpath(td, fp->f_vnode, &atpath,
  181                                     &freepath);
  182                         }
  183                 }
  184                 if (flags & O_RDWR) {
  185                         /*
  186                          * We'll get the W record below, but need
  187                          * to also output an R to distinguish from
  188                          * O_WRONLY.
  189                          */
  190                         len = snprintf(filemon->msgbufr,
  191                             sizeof(filemon->msgbufr), "R %d %s%s%s\n",
  192                             curproc->p_pid, atpath,
  193                             atpath[0] != '\0' ? "/" : "", filemon->fname1);
  194                         filemon_output(filemon, filemon->msgbufr, len);
  195                 }
  196 
  197                 len = snprintf(filemon->msgbufr,
  198                     sizeof(filemon->msgbufr), "%c %d %s%s%s\n",
  199                     (flags & O_ACCMODE) ? 'W':'R',
  200                     curproc->p_pid, atpath,
  201                     atpath[0] != '\0' ? "/" : "", filemon->fname1);
  202                 filemon_output(filemon, filemon->msgbufr, len);
  203 copyfail:
  204                 filemon_drop(filemon);
  205                 if (fp != NULL)
  206                         fdrop(fp, td);
  207                 free(freepath, M_TEMP);
  208         }
  209 }
  210 
  211 static int
  212 filemon_wrapper_open(struct thread *td, struct open_args *uap)
  213 {
  214         int ret;
  215 
  216         if ((ret = sys_open(td, uap)) == 0)
  217                 _filemon_wrapper_openat(td, uap->path, uap->flags, AT_FDCWD);
  218 
  219         return (ret);
  220 }
  221 
  222 static int
  223 filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
  224 {
  225         int ret;
  226 
  227         if ((ret = sys_openat(td, uap)) == 0)
  228                 _filemon_wrapper_openat(td, uap->path, uap->flag, uap->fd);
  229 
  230         return (ret);
  231 }
  232 
  233 static int
  234 filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
  235 {
  236         int error, ret;
  237         size_t len;
  238         struct filemon *filemon;
  239 
  240         if ((ret = sys_rename(td, uap)) == 0) {
  241                 if ((filemon = filemon_proc_get(curproc)) != NULL) {
  242                         if (((error = copyinstr(uap->from, filemon->fname1,
  243                              sizeof(filemon->fname1), NULL)) != 0) ||
  244                             ((error = copyinstr(uap->to, filemon->fname2,
  245                              sizeof(filemon->fname2), NULL)) != 0)) {
  246                                 filemon->error = error;
  247                                 goto copyfail;
  248                         }
  249 
  250                         len = snprintf(filemon->msgbufr,
  251                             sizeof(filemon->msgbufr), "M %d '%s' '%s'\n",
  252                             curproc->p_pid, filemon->fname1, filemon->fname2);
  253 
  254                         filemon_output(filemon, filemon->msgbufr, len);
  255 copyfail:
  256                         filemon_drop(filemon);
  257                 }
  258         }
  259 
  260         return (ret);
  261 }
  262 
  263 static void
  264 _filemon_wrapper_link(struct thread *td, char *upath1, char *upath2)
  265 {
  266         struct filemon *filemon;
  267         size_t len;
  268         int error;
  269 
  270         if ((filemon = filemon_proc_get(curproc)) != NULL) {
  271                 if (((error = copyinstr(upath1, filemon->fname1,
  272                      sizeof(filemon->fname1), NULL)) != 0) ||
  273                     ((error = copyinstr(upath2, filemon->fname2,
  274                      sizeof(filemon->fname2), NULL)) != 0)) {
  275                         filemon->error = error;
  276                         goto copyfail;
  277                 }
  278 
  279                 len = snprintf(filemon->msgbufr,
  280                     sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
  281                     curproc->p_pid, filemon->fname1, filemon->fname2);
  282 
  283                 filemon_output(filemon, filemon->msgbufr, len);
  284 copyfail:
  285                 filemon_drop(filemon);
  286         }
  287 }
  288 
  289 static int
  290 filemon_wrapper_link(struct thread *td, struct link_args *uap)
  291 {
  292         int ret;
  293 
  294         if ((ret = sys_link(td, uap)) == 0)
  295                 _filemon_wrapper_link(td, uap->path, uap->link);
  296 
  297         return (ret);
  298 }
  299 
  300 static int
  301 filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
  302 {
  303         int ret;
  304 
  305         if ((ret = sys_symlink(td, uap)) == 0)
  306                 _filemon_wrapper_link(td, uap->path, uap->link);
  307 
  308         return (ret);
  309 }
  310 
  311 static int
  312 filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
  313 {
  314         int ret;
  315 
  316         if ((ret = sys_linkat(td, uap)) == 0)
  317                 _filemon_wrapper_link(td, uap->path1, uap->path2);
  318 
  319         return (ret);
  320 }
  321 
  322 static void
  323 filemon_event_process_exit(void *arg __unused, struct proc *p)
  324 {
  325         size_t len;
  326         struct filemon *filemon;
  327 
  328         if ((filemon = filemon_proc_get(p)) != NULL) {
  329                 len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr),
  330                     "X %d %d %d\n", p->p_pid, p->p_xexit, p->p_xsig);
  331 
  332                 filemon_output(filemon, filemon->msgbufr, len);
  333 
  334                 /*
  335                  * filemon_untrack_processes() may have dropped this p_filemon
  336                  * already while in filemon_proc_get() before acquiring the
  337                  * filemon lock.
  338                  */
  339                 KASSERT(p->p_filemon == NULL || p->p_filemon == filemon,
  340                     ("%s: p %p was attached while exiting, expected "
  341                     "filemon %p or NULL", __func__, p, filemon));
  342                 if (p->p_filemon == filemon)
  343                         filemon_proc_drop(p);
  344 
  345                 filemon_drop(filemon);
  346         }
  347 }
  348 
  349 static int
  350 filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap)
  351 {
  352         int error, ret;
  353         size_t len;
  354         struct filemon *filemon;
  355 
  356         if ((ret = sys_unlink(td, uap)) == 0) {
  357                 if ((filemon = filemon_proc_get(curproc)) != NULL) {
  358                         if ((error = copyinstr(uap->path, filemon->fname1,
  359                             sizeof(filemon->fname1), NULL)) != 0) {
  360                                 filemon->error = error;
  361                                 goto copyfail;
  362                         }
  363 
  364                         len = snprintf(filemon->msgbufr,
  365                             sizeof(filemon->msgbufr), "D %d %s\n",
  366                             curproc->p_pid, filemon->fname1);
  367 
  368                         filemon_output(filemon, filemon->msgbufr, len);
  369 copyfail:
  370                         filemon_drop(filemon);
  371                 }
  372         }
  373 
  374         return (ret);
  375 }
  376 
  377 static void
  378 filemon_event_process_fork(void *arg __unused, struct proc *p1,
  379     struct proc *p2, int flags __unused)
  380 {
  381         size_t len;
  382         struct filemon *filemon;
  383 
  384         if ((filemon = filemon_proc_get(p1)) != NULL) {
  385                 len = snprintf(filemon->msgbufr,
  386                     sizeof(filemon->msgbufr), "F %d %d\n",
  387                     p1->p_pid, p2->p_pid);
  388 
  389                 filemon_output(filemon, filemon->msgbufr, len);
  390 
  391                 /*
  392                  * filemon_untrack_processes() or
  393                  * filemon_ioctl(FILEMON_SET_PID) may have changed the parent's
  394                  * p_filemon while in filemon_proc_get() before acquiring the
  395                  * filemon lock.  Only inherit if the parent is still traced by
  396                  * this filemon.
  397                  */
  398                 if (p1->p_filemon == filemon) {
  399                         PROC_LOCK(p2);
  400                         /*
  401                          * It may have been attached to already by a new
  402                          * filemon.
  403                          */
  404                         if (p2->p_filemon == NULL) {
  405                                 p2->p_filemon = filemon_acquire(filemon);
  406                                 ++filemon->proccnt;
  407                         }
  408                         PROC_UNLOCK(p2);
  409                 }
  410 
  411                 filemon_drop(filemon);
  412         }
  413 }
  414 
  415 static void
  416 filemon_wrapper_install(void)
  417 {
  418 
  419         sysent[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
  420         sysent[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
  421         sysent[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
  422         sysent[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
  423         sysent[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
  424         sysent[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
  425         sysent[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
  426         sysent[SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
  427 
  428 #if defined(COMPAT_FREEBSD32)
  429         freebsd32_sysent[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
  430         freebsd32_sysent[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
  431         freebsd32_sysent[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
  432         freebsd32_sysent[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
  433         freebsd32_sysent[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
  434         freebsd32_sysent[FREEBSD32_SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
  435         freebsd32_sysent[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
  436         freebsd32_sysent[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
  437 #endif  /* COMPAT_FREEBSD32 */
  438 
  439         filemon_exec_tag = EVENTHANDLER_REGISTER(process_exec,
  440             filemon_event_process_exec, NULL, EVENTHANDLER_PRI_LAST);
  441         filemon_exit_tag = EVENTHANDLER_REGISTER(process_exit,
  442             filemon_event_process_exit, NULL, EVENTHANDLER_PRI_LAST);
  443         filemon_fork_tag = EVENTHANDLER_REGISTER(process_fork,
  444             filemon_event_process_fork, NULL, EVENTHANDLER_PRI_LAST);
  445 }
  446 
  447 static void
  448 filemon_wrapper_deinstall(void)
  449 {
  450 
  451         sysent[SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
  452         sysent[SYS_open].sy_call = (sy_call_t *)sys_open;
  453         sysent[SYS_openat].sy_call = (sy_call_t *)sys_openat;
  454         sysent[SYS_rename].sy_call = (sy_call_t *)sys_rename;
  455         sysent[SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
  456         sysent[SYS_link].sy_call = (sy_call_t *)sys_link;
  457         sysent[SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
  458         sysent[SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
  459 
  460 #if defined(COMPAT_FREEBSD32)
  461         freebsd32_sysent[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
  462         freebsd32_sysent[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open;
  463         freebsd32_sysent[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat;
  464         freebsd32_sysent[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename;
  465         freebsd32_sysent[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
  466         freebsd32_sysent[FREEBSD32_SYS_link].sy_call = (sy_call_t *)sys_link;
  467         freebsd32_sysent[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
  468         freebsd32_sysent[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
  469 #endif  /* COMPAT_FREEBSD32 */
  470 
  471         EVENTHANDLER_DEREGISTER(process_exec, filemon_exec_tag);
  472         EVENTHANDLER_DEREGISTER(process_exit, filemon_exit_tag);
  473         EVENTHANDLER_DEREGISTER(process_fork, filemon_fork_tag);
  474 }

Cache object: d987d505eede8a09d706baa74bd3b89e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.