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

Cache object: ad19c15d44186b53d2c4382bcda41c03


[ 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.