Index: stable/10/sys/dev/filemon/filemon.c =================================================================== --- stable/10/sys/dev/filemon/filemon.c (revision 343885) +++ stable/10/sys/dev/filemon/filemon.c (revision 343886) @@ -1,512 +1,513 @@ /*- * Copyright (c) 2011, David E. O'Brien. * Copyright (c) 2009-2011, Juniper Networks, Inc. * Copyright (c) 2015-2016, EMC Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JUNIPER NETWORKS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JUNIPER NETWORKS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "filemon.h" #if defined(COMPAT_FREEBSD32) #include #include #include #endif static d_close_t filemon_close; static d_ioctl_t filemon_ioctl; static d_open_t filemon_open; static struct cdevsw filemon_cdevsw = { .d_version = D_VERSION, .d_close = filemon_close, .d_ioctl = filemon_ioctl, .d_open = filemon_open, .d_name = "filemon", }; MALLOC_DECLARE(M_FILEMON); MALLOC_DEFINE(M_FILEMON, "filemon", "File access monitor"); /* * The filemon->lock protects several things currently: * - fname1/fname2/msgbufr are pre-allocated and used per syscall * for logging and copyins rather than stack variables. * - Serializing the filemon's log output. * - Preventing inheritance or removal of the filemon into proc.p_filemon. */ struct filemon { struct sx lock; /* Lock for this filemon. */ struct file *fp; /* Output file pointer. */ struct ucred *cred; /* Credential of tracer. */ char fname1[MAXPATHLEN]; /* Temporary filename buffer. */ char fname2[MAXPATHLEN]; /* Temporary filename buffer. */ - char msgbufr[1024]; /* Output message buffer. */ + char msgbufr[2*MAXPATHLEN + 100]; /* Output message buffer. */ int error; /* Log write error, returned on close(2). */ u_int refcnt; /* Pointer reference count. */ u_int proccnt; /* Process count. */ }; static struct cdev *filemon_dev; static void filemon_output(struct filemon *filemon, char *msg, size_t len); static __inline struct filemon * filemon_acquire(struct filemon *filemon) { if (filemon != NULL) refcount_acquire(&filemon->refcnt); return (filemon); } /* * Release a reference and free on the last one. */ static void filemon_release(struct filemon *filemon) { if (refcount_release(&filemon->refcnt) == 0) return; /* * There are valid cases of releasing while locked, such as in * filemon_untrack_processes, but none which are done where there * is not at least 1 reference remaining. */ sx_assert(&filemon->lock, SA_UNLOCKED); if (filemon->cred != NULL) crfree(filemon->cred); sx_destroy(&filemon->lock); free(filemon, M_FILEMON); } /* * Acquire the proc's p_filemon reference and lock the filemon. * The proc's p_filemon may not match this filemon on return. */ static struct filemon * filemon_proc_get(struct proc *p) { struct filemon *filemon; if (p->p_filemon == NULL) return (NULL); PROC_LOCK(p); filemon = filemon_acquire(p->p_filemon); PROC_UNLOCK(p); if (filemon == NULL) return (NULL); /* * The p->p_filemon may have changed by now. That case is handled * by the exit and fork hooks and filemon_attach_proc specially. */ sx_xlock(&filemon->lock); return (filemon); } /* Remove and release the filemon on the given process. */ static void filemon_proc_drop(struct proc *p) { struct filemon *filemon; KASSERT(p->p_filemon != NULL, ("%s: proc %p NULL p_filemon", __func__, p)); sx_assert(&p->p_filemon->lock, SA_XLOCKED); PROC_LOCK(p); filemon = p->p_filemon; p->p_filemon = NULL; --filemon->proccnt; PROC_UNLOCK(p); /* * This should not be the last reference yet. filemon_release() * cannot be called with filemon locked, which the caller expects * will stay locked. */ KASSERT(filemon->refcnt > 1, ("%s: proc %p dropping filemon %p " "with last reference", __func__, p, filemon)); filemon_release(filemon); } /* Unlock and release the filemon. */ static __inline void filemon_drop(struct filemon *filemon) { sx_xunlock(&filemon->lock); filemon_release(filemon); } #include "filemon_wrapper.c" static void filemon_write_header(struct filemon *filemon) { int len; struct timeval now; getmicrotime(&now); len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "# filemon version %d\n# Target pid %d\n# Start %ju.%06ju\nV %d\n", FILEMON_VERSION, curproc->p_pid, (uintmax_t)now.tv_sec, (uintmax_t)now.tv_usec, FILEMON_VERSION); - - filemon_output(filemon, filemon->msgbufr, len); + if (len < sizeof(filemon->msgbufr)) + filemon_output(filemon, filemon->msgbufr, len); } /* * Invalidate the passed filemon in all processes. */ static void filemon_untrack_processes(struct filemon *filemon) { struct proc *p; sx_assert(&filemon->lock, SA_XLOCKED); /* Avoid allproc loop if there is no need. */ if (filemon->proccnt == 0) return; /* * Processes in this list won't go away while here since * filemon_event_process_exit() will lock on filemon->lock * which we hold. */ sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { /* * No PROC_LOCK is needed to compare here since it is * guaranteed to not change since we have its filemon * locked. Everything that changes this p_filemon will * be locked on it. */ if (p->p_filemon == filemon) filemon_proc_drop(p); } sx_sunlock(&allproc_lock); /* * It's possible some references were acquired but will be * dropped shortly as they are restricted from being * inherited. There is at least the reference in cdevpriv remaining. */ KASSERT(filemon->refcnt > 0, ("%s: filemon %p should have " "references still.", __func__, filemon)); KASSERT(filemon->proccnt == 0, ("%s: filemon %p should not have " "attached procs still.", __func__, filemon)); } /* * Close out the log. */ static void filemon_close_log(struct filemon *filemon) { struct file *fp; struct timeval now; size_t len; sx_assert(&filemon->lock, SA_XLOCKED); if (filemon->fp == NULL) return; getmicrotime(&now); len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "# Stop %ju.%06ju\n# Bye bye\n", (uintmax_t)now.tv_sec, (uintmax_t)now.tv_usec); - filemon_output(filemon, filemon->msgbufr, len); + if (len < sizeof(filemon->msgbufr)) + filemon_output(filemon, filemon->msgbufr, len); fp = filemon->fp; filemon->fp = NULL; sx_xunlock(&filemon->lock); fdrop(fp, curthread); sx_xlock(&filemon->lock); } /* * The devfs file is being closed. Untrace all processes. It is possible * filemon_close/close(2) was not called. */ static void filemon_dtr(void *data) { struct filemon *filemon = data; if (filemon == NULL) return; sx_xlock(&filemon->lock); /* * Detach the filemon. It cannot be inherited after this. */ filemon_untrack_processes(filemon); filemon_close_log(filemon); filemon_drop(filemon); } /* Attach the filemon to the process. */ static int filemon_attach_proc(struct filemon *filemon, struct proc *p) { struct filemon *filemon2; sx_assert(&filemon->lock, SA_XLOCKED); PROC_LOCK_ASSERT(p, MA_OWNED); KASSERT((p->p_flag & P_WEXIT) == 0, ("%s: filemon %p attaching to exiting process %p", __func__, filemon, p)); KASSERT((p->p_flag & P_INEXEC) == 0, ("%s: filemon %p attaching to execing process %p", __func__, filemon, p)); if (p->p_filemon == filemon) return (0); /* * Don't allow truncating other process traces. It is * not really intended to trace procs other than curproc * anyhow. */ if (p->p_filemon != NULL && p != curproc) return (EBUSY); /* * Historic behavior of filemon has been to let a child initiate * tracing on itself and cease existing tracing. Bmake * .META + .MAKE relies on this. It is only relevant for attaching to * curproc. */ while (p->p_filemon != NULL) { PROC_UNLOCK(p); sx_xunlock(&filemon->lock); while ((filemon2 = filemon_proc_get(p)) != NULL) { /* It may have changed. */ if (p->p_filemon == filemon2) filemon_proc_drop(p); filemon_drop(filemon2); } sx_xlock(&filemon->lock); PROC_LOCK(p); /* * It may have been attached to, though unlikely. * Try again if needed. */ } KASSERT(p->p_filemon == NULL, ("%s: proc %p didn't detach filemon %p", __func__, p, p->p_filemon)); p->p_filemon = filemon_acquire(filemon); ++filemon->proccnt; return (0); } static int filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused, struct thread *td) { int error = 0; struct filemon *filemon; struct proc *p; cap_rights_t rights; if ((error = devfs_get_cdevpriv((void **) &filemon)) != 0) return (error); sx_xlock(&filemon->lock); switch (cmd) { /* Set the output file descriptor. */ case FILEMON_SET_FD: if (filemon->fp != NULL) { error = EEXIST; break; } error = fget_write(td, *(int *)data, cap_rights_init(&rights, CAP_PWRITE), &filemon->fp); if (error == 0) /* Write the file header. */ filemon_write_header(filemon); break; /* Set the monitored process ID. */ case FILEMON_SET_PID: /* Invalidate any existing processes already set. */ filemon_untrack_processes(filemon); error = pget(*((pid_t *)data), PGET_CANDEBUG | PGET_NOTWEXIT | PGET_NOTINEXEC, &p); if (error == 0) { KASSERT(p->p_filemon != filemon, ("%s: proc %p didn't untrack filemon %p", __func__, p, filemon)); error = filemon_attach_proc(filemon, p); PROC_UNLOCK(p); } break; default: error = EINVAL; break; } sx_xunlock(&filemon->lock); return (error); } static int filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused, struct thread *td) { int error; struct filemon *filemon; filemon = malloc(sizeof(*filemon), M_FILEMON, M_WAITOK | M_ZERO); sx_init(&filemon->lock, "filemon"); refcount_init(&filemon->refcnt, 1); filemon->cred = crhold(td->td_ucred); error = devfs_set_cdevpriv(filemon, filemon_dtr); if (error != 0) filemon_release(filemon); return (error); } /* Called on close of last devfs file handle, before filemon_dtr(). */ static int filemon_close(struct cdev *dev __unused, int flag __unused, int fmt __unused, struct thread *td __unused) { struct filemon *filemon; int error; if ((error = devfs_get_cdevpriv((void **) &filemon)) != 0) return (error); sx_xlock(&filemon->lock); filemon_close_log(filemon); error = filemon->error; sx_xunlock(&filemon->lock); /* * Processes are still being traced but won't log anything * now. After this call returns filemon_dtr() is called which * will detach processes. */ return (error); } static void filemon_load(void *dummy __unused) { /* Install the syscall wrappers. */ filemon_wrapper_install(); filemon_dev = make_dev(&filemon_cdevsw, 0, UID_ROOT, GID_WHEEL, 0666, "filemon"); } static int filemon_unload(void) { destroy_dev(filemon_dev); filemon_wrapper_deinstall(); return (0); } static int filemon_modevent(module_t mod __unused, int type, void *data) { int error = 0; switch (type) { case MOD_LOAD: filemon_load(data); break; case MOD_UNLOAD: error = filemon_unload(); break; case MOD_QUIESCE: /* * The wrapper implementation is unsafe for reliable unload. * Require forcing an unload. */ error = EBUSY; break; case MOD_SHUTDOWN: break; default: error = EOPNOTSUPP; break; } return (error); } DEV_MODULE(filemon, filemon_modevent, NULL); MODULE_VERSION(filemon, 1); Index: stable/10/sys/dev/filemon/filemon_wrapper.c =================================================================== --- stable/10/sys/dev/filemon/filemon_wrapper.c (revision 343885) +++ stable/10/sys/dev/filemon/filemon_wrapper.c (revision 343886) @@ -1,474 +1,460 @@ /*- * Copyright (c) 2011, David E. O'Brien. * Copyright (c) 2009-2011, Juniper Networks, Inc. * Copyright (c) 2015-2016, EMC Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JUNIPER NETWORKS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JUNIPER NETWORKS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include +#include + #include "opt_compat.h" +static void filemon_output_event(struct filemon *filemon, const char *fmt, ...) + __printflike(2, 3); + static eventhandler_tag filemon_exec_tag; static eventhandler_tag filemon_exit_tag; static eventhandler_tag filemon_fork_tag; static void filemon_output(struct filemon *filemon, char *msg, size_t len) { struct uio auio; struct iovec aiov; int error; if (filemon->fp == NULL) return; aiov.iov_base = msg; aiov.iov_len = len; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_resid = len; auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_WRITE; auio.uio_td = curthread; auio.uio_offset = (off_t) -1; if (filemon->fp->f_type == DTYPE_VNODE) bwillwrite(); error = fo_write(filemon->fp, &auio, filemon->cred, 0, curthread); if (error != 0 && filemon->error == 0) filemon->error = error; } +static void +filemon_output_event(struct filemon *filemon, const char *fmt, ...) +{ + va_list ap; + size_t len; + + va_start(ap, fmt); + len = vsnprintf(filemon->msgbufr, sizeof(filemon->msgbufr), fmt, ap); + va_end(ap); + /* The event is truncated but still worth logging. */ + if (len >= sizeof(filemon->msgbufr)) + len = sizeof(filemon->msgbufr) - 1; + filemon_output(filemon, filemon->msgbufr, len); +} + static int filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap) { int error, ret; - size_t len; struct filemon *filemon; if ((ret = sys_chdir(td, uap)) == 0) { if ((filemon = filemon_proc_get(curproc)) != NULL) { if ((error = copyinstr(uap->path, filemon->fname1, sizeof(filemon->fname1), NULL)) != 0) { filemon->error = error; goto copyfail; } - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "C %d %s\n", + filemon_output_event(filemon, "C %d %s\n", curproc->p_pid, filemon->fname1); - - filemon_output(filemon, filemon->msgbufr, len); copyfail: filemon_drop(filemon); } } return (ret); } static void filemon_event_process_exec(void *arg __unused, struct proc *p, struct image_params *imgp) { struct filemon *filemon; - size_t len; if ((filemon = filemon_proc_get(p)) != NULL) { - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "E %d %s\n", + filemon_output_event(filemon, "E %d %s\n", p->p_pid, imgp->execpath != NULL ? imgp->execpath : ""); - filemon_output(filemon, filemon->msgbufr, len); - /* If the credentials changed then cease tracing. */ if (imgp->newcred != NULL && imgp->credential_setid && priv_check_cred(filemon->cred, PRIV_DEBUG_DIFFCRED, 0) != 0) { /* * It may have changed to NULL already, but * will not be re-attached by anything else. */ if (p->p_filemon != NULL) { KASSERT(p->p_filemon == filemon, ("%s: proc %p didn't have expected" " filemon %p", __func__, p, filemon)); filemon_proc_drop(p); } } filemon_drop(filemon); } } static void _filemon_wrapper_openat(struct thread *td, char *upath, int flags, int fd) { int error; - size_t len; struct file *fp; struct filemon *filemon; char *atpath, *freepath; cap_rights_t rights; if ((filemon = filemon_proc_get(curproc)) != NULL) { atpath = ""; freepath = NULL; fp = NULL; if ((error = copyinstr(upath, filemon->fname1, sizeof(filemon->fname1), NULL)) != 0) { filemon->error = error; goto copyfail; } if (filemon->fname1[0] != '/' && fd != AT_FDCWD) { /* * rats - we cannot do too much about this. * the trace should show a dir we read * recently.. output an A record as a clue * until we can do better. * XXX: This may be able to come out with * the namecache lookup now. */ - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "A %d %s\n", + filemon_output_event(filemon, "A %d %s\n", curproc->p_pid, filemon->fname1); - filemon_output(filemon, filemon->msgbufr, len); /* * Try to resolve the path from the vnode using the * namecache. It may be inaccurate, but better * than nothing. */ if (getvnode(td->td_proc->p_fd, fd, cap_rights_init(&rights, CAP_LOOKUP), &fp) == 0) { vn_fullpath(td, fp->f_vnode, &atpath, &freepath); } } if (flags & O_RDWR) { /* * We'll get the W record below, but need * to also output an R to distinguish from * O_WRONLY. */ - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "R %d %s%s%s\n", + filemon_output_event(filemon, "R %d %s%s%s\n", curproc->p_pid, atpath, atpath[0] != '\0' ? "/" : "", filemon->fname1); - filemon_output(filemon, filemon->msgbufr, len); } - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "%c %d %s%s%s\n", + filemon_output_event(filemon, "%c %d %s%s%s\n", (flags & O_ACCMODE) ? 'W':'R', curproc->p_pid, atpath, atpath[0] != '\0' ? "/" : "", filemon->fname1); - filemon_output(filemon, filemon->msgbufr, len); copyfail: filemon_drop(filemon); if (fp != NULL) fdrop(fp, td); free(freepath, M_TEMP); } } static int filemon_wrapper_open(struct thread *td, struct open_args *uap) { int ret; if ((ret = sys_open(td, uap)) == 0) _filemon_wrapper_openat(td, uap->path, uap->flags, AT_FDCWD); return (ret); } static int filemon_wrapper_openat(struct thread *td, struct openat_args *uap) { int ret; if ((ret = sys_openat(td, uap)) == 0) _filemon_wrapper_openat(td, uap->path, uap->flag, uap->fd); return (ret); } static int filemon_wrapper_rename(struct thread *td, struct rename_args *uap) { int error, ret; - size_t len; struct filemon *filemon; if ((ret = sys_rename(td, uap)) == 0) { if ((filemon = filemon_proc_get(curproc)) != NULL) { if (((error = copyinstr(uap->from, filemon->fname1, sizeof(filemon->fname1), NULL)) != 0) || ((error = copyinstr(uap->to, filemon->fname2, sizeof(filemon->fname2), NULL)) != 0)) { filemon->error = error; goto copyfail; } - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "M %d '%s' '%s'\n", + filemon_output_event(filemon, "M %d '%s' '%s'\n", curproc->p_pid, filemon->fname1, filemon->fname2); - - filemon_output(filemon, filemon->msgbufr, len); copyfail: filemon_drop(filemon); } } return (ret); } static void _filemon_wrapper_link(struct thread *td, char *upath1, char *upath2) { struct filemon *filemon; - size_t len; int error; if ((filemon = filemon_proc_get(curproc)) != NULL) { if (((error = copyinstr(upath1, filemon->fname1, sizeof(filemon->fname1), NULL)) != 0) || ((error = copyinstr(upath2, filemon->fname2, sizeof(filemon->fname2), NULL)) != 0)) { filemon->error = error; goto copyfail; } - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "L %d '%s' '%s'\n", + filemon_output_event(filemon, "L %d '%s' '%s'\n", curproc->p_pid, filemon->fname1, filemon->fname2); - - filemon_output(filemon, filemon->msgbufr, len); copyfail: filemon_drop(filemon); } } static int filemon_wrapper_link(struct thread *td, struct link_args *uap) { int ret; if ((ret = sys_link(td, uap)) == 0) _filemon_wrapper_link(td, uap->path, uap->link); return (ret); } static int filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap) { int ret; if ((ret = sys_symlink(td, uap)) == 0) _filemon_wrapper_link(td, uap->path, uap->link); return (ret); } static int filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap) { int ret; if ((ret = sys_linkat(td, uap)) == 0) _filemon_wrapper_link(td, uap->path1, uap->path2); return (ret); } static void filemon_event_process_exit(void *arg __unused, struct proc *p) { - size_t len; struct filemon *filemon; if ((filemon = filemon_proc_get(p)) != NULL) { - len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), - "X %d %d\n", p->p_pid, W_EXITCODE(p->p_xstat, 0)); + filemon_output_event(filemon, "X %d %d\n", + p->p_pid, W_EXITCODE(p->p_xstat, 0)); - filemon_output(filemon, filemon->msgbufr, len); - /* * filemon_untrack_processes() may have dropped this p_filemon * already while in filemon_proc_get() before acquiring the * filemon lock. */ KASSERT(p->p_filemon == NULL || p->p_filemon == filemon, ("%s: p %p was attached while exiting, expected " "filemon %p or NULL", __func__, p, filemon)); if (p->p_filemon == filemon) filemon_proc_drop(p); filemon_drop(filemon); } } static int filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap) { int error, ret; - size_t len; struct filemon *filemon; if ((ret = sys_unlink(td, uap)) == 0) { if ((filemon = filemon_proc_get(curproc)) != NULL) { if ((error = copyinstr(uap->path, filemon->fname1, sizeof(filemon->fname1), NULL)) != 0) { filemon->error = error; goto copyfail; } - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "D %d %s\n", + filemon_output_event(filemon, "D %d %s\n", curproc->p_pid, filemon->fname1); - - filemon_output(filemon, filemon->msgbufr, len); copyfail: filemon_drop(filemon); } } return (ret); } static void filemon_event_process_fork(void *arg __unused, struct proc *p1, struct proc *p2, int flags __unused) { - size_t len; struct filemon *filemon; if ((filemon = filemon_proc_get(p1)) != NULL) { - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "F %d %d\n", + filemon_output_event(filemon, "F %d %d\n", p1->p_pid, p2->p_pid); - - filemon_output(filemon, filemon->msgbufr, len); /* * filemon_untrack_processes() or * filemon_ioctl(FILEMON_SET_PID) may have changed the parent's * p_filemon while in filemon_proc_get() before acquiring the * filemon lock. Only inherit if the parent is still traced by * this filemon. */ if (p1->p_filemon == filemon) { PROC_LOCK(p2); /* * It may have been attached to already by a new * filemon. */ if (p2->p_filemon == NULL) { p2->p_filemon = filemon_acquire(filemon); ++filemon->proccnt; } PROC_UNLOCK(p2); } filemon_drop(filemon); } } static void filemon_wrapper_install(void) { sysent[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir; sysent[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; sysent[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat; sysent[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename; sysent[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink; sysent[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link; sysent[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink; sysent[SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat; #if defined(COMPAT_FREEBSD32) freebsd32_sysent[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir; freebsd32_sysent[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; freebsd32_sysent[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat; freebsd32_sysent[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename; freebsd32_sysent[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink; freebsd32_sysent[FREEBSD32_SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link; freebsd32_sysent[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink; freebsd32_sysent[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat; #endif /* COMPAT_FREEBSD32 */ filemon_exec_tag = EVENTHANDLER_REGISTER(process_exec, filemon_event_process_exec, NULL, EVENTHANDLER_PRI_LAST); filemon_exit_tag = EVENTHANDLER_REGISTER(process_exit, filemon_event_process_exit, NULL, EVENTHANDLER_PRI_LAST); filemon_fork_tag = EVENTHANDLER_REGISTER(process_fork, filemon_event_process_fork, NULL, EVENTHANDLER_PRI_LAST); } static void filemon_wrapper_deinstall(void) { sysent[SYS_chdir].sy_call = (sy_call_t *)sys_chdir; sysent[SYS_open].sy_call = (sy_call_t *)sys_open; sysent[SYS_openat].sy_call = (sy_call_t *)sys_openat; sysent[SYS_rename].sy_call = (sy_call_t *)sys_rename; sysent[SYS_unlink].sy_call = (sy_call_t *)sys_unlink; sysent[SYS_link].sy_call = (sy_call_t *)sys_link; sysent[SYS_symlink].sy_call = (sy_call_t *)sys_symlink; sysent[SYS_linkat].sy_call = (sy_call_t *)sys_linkat; #if defined(COMPAT_FREEBSD32) freebsd32_sysent[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir; freebsd32_sysent[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open; freebsd32_sysent[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat; freebsd32_sysent[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename; freebsd32_sysent[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink; freebsd32_sysent[FREEBSD32_SYS_link].sy_call = (sy_call_t *)sys_link; freebsd32_sysent[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *)sys_symlink; freebsd32_sysent[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *)sys_linkat; #endif /* COMPAT_FREEBSD32 */ EVENTHANDLER_DEREGISTER(process_exec, filemon_exec_tag); EVENTHANDLER_DEREGISTER(process_exit, filemon_exit_tag); EVENTHANDLER_DEREGISTER(process_fork, filemon_fork_tag); } Index: stable/10 =================================================================== --- stable/10 (revision 343885) +++ stable/10 (revision 343886) Property changes on: stable/10 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r337272