svn commit: r236592 - in head/sys: dev/filemon modules
modules/filemon
David E. O'Brien
obrien at FreeBSD.org
Mon Jun 4 22:54:20 UTC 2012
Author: obrien
Date: Mon Jun 4 22:54:19 2012
New Revision: 236592
URL: http://svn.freebsd.org/changeset/base/236592
Log:
Add the 'filemon' device. 'filemon' is a kernel module that provides a device
interface for processes to record system calls of its children.
Submitted by: Juniper Networks.
Added:
head/sys/dev/filemon/
head/sys/dev/filemon/filemon.c (contents, props changed)
head/sys/dev/filemon/filemon.h (contents, props changed)
head/sys/dev/filemon/filemon_lock.c (contents, props changed)
head/sys/dev/filemon/filemon_wrapper.c (contents, props changed)
head/sys/modules/filemon/
head/sys/modules/filemon/Makefile (contents, props changed)
Modified:
head/sys/modules/Makefile
Added: head/sys/dev/filemon/filemon.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/dev/filemon/filemon.c Mon Jun 4 22:54:19 2012 (r236592)
@@ -0,0 +1,377 @@
+/*-
+ * Copyright (c) 2011, David E. O'Brien.
+ * Copyright (c) 2009-2011, Juniper Networks, Inc.
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/ioccom.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/poll.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/uio.h>
+
+#if __FreeBSD_version >= 900041
+#include <sys/capability.h>
+#endif
+
+#include "filemon.h"
+
+#if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
+#include <compat/freebsd32/freebsd32_syscall.h>
+#include <compat/freebsd32/freebsd32_proto.h>
+
+extern struct sysentvec ia32_freebsd_sysvec;
+#endif
+
+extern struct sysentvec elf32_freebsd_sysvec;
+extern struct sysentvec elf64_freebsd_sysvec;
+
+static d_close_t filemon_close;
+static d_ioctl_t filemon_ioctl;
+static d_open_t filemon_open;
+static int filemon_unload(void);
+static void filemon_load(void *);
+
+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");
+
+struct filemon {
+ TAILQ_ENTRY(filemon) link; /* Link into the in-use list. */
+ struct mtx mtx; /* Lock mutex for this filemon. */
+ struct cv cv; /* Lock condition variable for this
+ filemon. */
+ struct file *fp; /* Output file pointer. */
+ struct thread *locker; /* Ptr to the thread locking this
+ filemon. */
+ pid_t pid; /* The process ID being monitored. */
+ char fname1[MAXPATHLEN]; /* Temporary filename buffer. */
+ char fname2[MAXPATHLEN]; /* Temporary filename buffer. */
+ char msgbufr[1024]; /* Output message buffer. */
+};
+
+static TAILQ_HEAD(, filemon) filemons_inuse = TAILQ_HEAD_INITIALIZER(filemons_inuse);
+static TAILQ_HEAD(, filemon) filemons_free = TAILQ_HEAD_INITIALIZER(filemons_free);
+static int n_readers = 0;
+static struct mtx access_mtx;
+static struct cv access_cv;
+static struct thread *access_owner = NULL;
+static struct thread *access_requester = NULL;
+
+#if __FreeBSD_version < 701000
+static struct clonedevs *filemon_clones;
+static eventhandler_tag eh_tag;
+#else
+static struct cdev *filemon_dev;
+#endif
+
+#include "filemon_lock.c"
+#include "filemon_wrapper.c"
+
+#if __FreeBSD_version < 701000
+static void
+filemon_clone(void *arg, struct ucred *cred, char *name, int namelen,
+ struct cdev **dev)
+{
+ int u = -1;
+ size_t len;
+
+ if (*dev != NULL)
+ return;
+
+ len = strlen(name);
+
+ if (len != 7)
+ return;
+
+ if (bcmp(name,"filemon", 7) != 0)
+ return;
+
+ /* Clone the device to the new minor number. */
+ if (clone_create(&filemon_clones, &filemon_cdevsw, &u, dev, 0) != 0)
+ /* Create the /dev/filemonNN entry. */
+ *dev = make_dev_cred(&filemon_cdevsw, u, cred, UID_ROOT,
+ GID_WHEEL, 0666, "filemon%d", u);
+ if (*dev != NULL) {
+ dev_ref(*dev);
+ (*dev)->si_flags |= SI_CHEAPCLONE;
+ }
+}
+#endif
+
+static void
+filemon_dtr(void *data)
+{
+ struct filemon *filemon = data;
+
+ if (filemon != NULL) {
+ struct file *fp = filemon->fp;
+
+ /* Get exclusive write access. */
+ filemon_lock_write();
+
+ /* Remove from the in-use list. */
+ TAILQ_REMOVE(&filemons_inuse, filemon, link);
+
+ filemon->fp = NULL;
+ filemon->pid = -1;
+
+ /* Add to the free list. */
+ TAILQ_INSERT_TAIL(&filemons_free, filemon, link);
+
+ /* Give up write access. */
+ filemon_unlock_write();
+
+ if (fp != NULL)
+ fdrop(fp, curthread);
+ }
+}
+
+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;
+
+#if __FreeBSD_version < 701000
+ filemon = dev->si_drv1;
+#else
+ devfs_get_cdevpriv((void **) &filemon);
+#endif
+
+ switch (cmd) {
+ /* Set the output file descriptor. */
+ case FILEMON_SET_FD:
+#if __FreeBSD_version < 900041
+#define FGET_WRITE(a1, a2, a3) fget_write((a1), (a2), (a3))
+#else
+#define FGET_WRITE(a1, a2, a3) fget_write((a1), (a2), CAP_WRITE | CAP_SEEK, (a3))
+#endif
+ if ((error = FGET_WRITE(td, *(int *)data, &filemon->fp)) == 0)
+ /* Write the file header. */
+ filemon_comment(filemon);
+ break;
+
+ /* Set the monitored process ID. */
+ case FILEMON_SET_PID:
+ filemon->pid = *((pid_t *) data);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+
+static int
+filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused,
+ struct thread *td __unused)
+{
+ struct filemon *filemon;
+
+ /* Get exclusive write access. */
+ filemon_lock_write();
+
+ if ((filemon = TAILQ_FIRST(&filemons_free)) != NULL)
+ TAILQ_REMOVE(&filemons_free, filemon, link);
+
+ /* Give up write access. */
+ filemon_unlock_write();
+
+ if (filemon == NULL) {
+ filemon = malloc(sizeof(struct filemon), M_FILEMON,
+ M_WAITOK | M_ZERO);
+
+ filemon->fp = NULL;
+
+ mtx_init(&filemon->mtx, "filemon", "filemon", MTX_DEF);
+ cv_init(&filemon->cv, "filemon");
+ }
+
+ filemon->pid = curproc->p_pid;
+
+#if __FreeBSD_version < 701000
+ dev->si_drv1 = filemon;
+#else
+ devfs_set_cdevpriv(filemon, filemon_dtr);
+#endif
+
+ /* Get exclusive write access. */
+ filemon_lock_write();
+
+ /* Add to the in-use list. */
+ TAILQ_INSERT_TAIL(&filemons_inuse, filemon, link);
+
+ /* Give up write access. */
+ filemon_unlock_write();
+
+ return (0);
+}
+
+static int
+filemon_close(struct cdev *dev __unused, int flag __unused, int fmt __unused,
+ struct thread *td __unused)
+{
+#if __FreeBSD_version < 701000
+ filemon_dtr(dev->si_drv1);
+
+ dev->si_drv1 = NULL;
+
+ /* Schedule this cloned device to be destroyed. */
+ destroy_dev_sched(dev);
+#endif
+
+ return (0);
+}
+
+static void
+filemon_load(void *dummy __unused)
+{
+ mtx_init(&access_mtx, "filemon", "filemon", MTX_DEF);
+ cv_init(&access_cv, "filemon");
+
+ /* Install the syscall wrappers. */
+ filemon_wrapper_install();
+
+#if __FreeBSD_version < 701000
+ /* Enable device cloning. */
+ clone_setup(&filemon_clones);
+
+ /* Setup device cloning events. */
+ eh_tag = EVENTHANDLER_REGISTER(dev_clone, filemon_clone, 0, 1000);
+#else
+ filemon_dev = make_dev(&filemon_cdevsw, 0, UID_ROOT, GID_WHEEL, 0666,
+ "filemon");
+#endif
+}
+
+static int
+filemon_unload(void)
+{
+ struct filemon *filemon;
+ int error = 0;
+
+ /* Get exclusive write access. */
+ filemon_lock_write();
+
+ if (TAILQ_FIRST(&filemons_inuse) != NULL)
+ error = EBUSY;
+ else {
+#if __FreeBSD_version >= 701000
+ destroy_dev(filemon_dev);
+#endif
+
+ /* Deinstall the syscall wrappers. */
+ filemon_wrapper_deinstall();
+ }
+
+ /* Give up write access. */
+ filemon_unlock_write();
+
+ if (error == 0) {
+#if __FreeBSD_version < 701000
+ /*
+ * Check if there is still an event handler callback registered.
+ */
+ if (eh_tag != 0) {
+ /* De-register the device cloning event handler. */
+ EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
+ eh_tag = 0;
+
+ /* Stop device cloning. */
+ clone_cleanup(&filemon_clones);
+ }
+#endif
+ /* free() filemon structs free list. */
+ filemon_lock_write();
+ while ((filemon = TAILQ_FIRST(&filemons_free)) != NULL) {
+ TAILQ_REMOVE(&filemons_free, filemon, link);
+ mtx_destroy(&filemon->mtx);
+ cv_destroy(&filemon->cv);
+ free(filemon, M_FILEMON);
+ }
+ filemon_unlock_write();
+
+ mtx_destroy(&access_mtx);
+ cv_destroy(&access_cv);
+ }
+
+ return (error);
+}
+
+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_SHUTDOWN:
+ break;
+
+ default:
+ error = EOPNOTSUPP;
+ break;
+
+ }
+
+ return (error);
+}
+
+DEV_MODULE(filemon, filemon_modevent, NULL);
+MODULE_VERSION(filemon, 1);
Added: head/sys/dev/filemon/filemon.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/dev/filemon/filemon.h Mon Jun 4 22:54:19 2012 (r236592)
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2011, David E. O'Brien.
+ * Copyright (c) 2009-2011, Juniper Networks, Inc.
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#define FILEMON_SET_FD _IOWR('S', 1, int)
+#define FILEMON_SET_PID _IOWR('S', 2, pid_t)
+
+#define FILEMON_VERSION 4 /* output format
+ (bump when adding record types) */
Added: head/sys/dev/filemon/filemon_lock.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/dev/filemon/filemon_lock.c Mon Jun 4 22:54:19 2012 (r236592)
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2009-2011, Juniper Networks, Inc.
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+static void
+filemon_filemon_lock(struct filemon *filemon)
+{
+ mtx_lock(&filemon->mtx);
+
+ while (filemon->locker != NULL && filemon->locker != curthread)
+ cv_wait(&filemon->cv, &filemon->mtx);
+
+ filemon->locker = curthread;
+
+ mtx_unlock(&filemon->mtx);
+}
+
+static void
+filemon_filemon_unlock(struct filemon *filemon)
+{
+ mtx_lock(&filemon->mtx);
+
+ if (filemon->locker == curthread)
+ filemon->locker = NULL;
+
+ /* Wake up threads waiting. */
+ cv_broadcast(&filemon->cv);
+
+ mtx_unlock(&filemon->mtx);
+}
+
+static void
+filemon_lock_read(void)
+{
+ mtx_lock(&access_mtx);
+
+ while (access_owner != NULL || access_requester != NULL)
+ cv_wait(&access_cv, &access_mtx);
+
+ n_readers++;
+
+ /* Wake up threads waiting. */
+ cv_broadcast(&access_cv);
+
+ mtx_unlock(&access_mtx);
+}
+
+static void
+filemon_unlock_read(void)
+{
+ mtx_lock(&access_mtx);
+
+ if (n_readers > 0)
+ n_readers--;
+
+ /* Wake up a thread waiting. */
+ cv_broadcast(&access_cv);
+
+ mtx_unlock(&access_mtx);
+}
+
+static void
+filemon_lock_write(void)
+{
+ mtx_lock(&access_mtx);
+
+ while (access_owner != curthread) {
+ if (access_owner == NULL &&
+ (access_requester == NULL ||
+ access_requester == curthread)) {
+ access_owner = curthread;
+ access_requester = NULL;
+ } else {
+ if (access_requester == NULL)
+ access_requester = curthread;
+
+ cv_wait(&access_cv, &access_mtx);
+ }
+ }
+
+ mtx_unlock(&access_mtx);
+}
+
+static void
+filemon_unlock_write(void)
+{
+ mtx_lock(&access_mtx);
+
+ /* Sanity check that the current thread actually has the write lock. */
+ if (access_owner == curthread)
+ access_owner = NULL;
+
+ /* Wake up a thread waiting. */
+ cv_broadcast(&access_cv);
+
+ mtx_unlock(&access_mtx);
+}
Added: head/sys/dev/filemon/filemon_wrapper.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/dev/filemon/filemon_wrapper.c Mon Jun 4 22:54:19 2012 (r236592)
@@ -0,0 +1,746 @@
+/*-
+ * Copyright (c) 2011, David E. O'Brien.
+ * Copyright (c) 2009-2011, Juniper Networks, Inc.
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#if __FreeBSD_version > 800032
+#define FILEMON_HAS_LINKAT
+#endif
+
+#if __FreeBSD_version < 900044 /* r225617 (2011-09-16) failed to bump
+ __FreeBSD_version. This really should
+ be based on "900045". "900044" is r225469
+ (2011-09-10) so this code is broken for
+ 9-CURRENT September 10th-16th. */
+#define sys_chdir chdir
+#define sys_execve execve
+#define sys_fork fork
+#define sys_link link
+#define sys_open open
+#define sys_rename rename
+#define sys_stat stat
+#define sys_symlink symlink
+#define sys_unlink unlink
+#define sys_vfork vfork
+#define sys_sys_exit sys_exit
+#ifdef FILEMON_HAS_LINKAT
+#define sys_linkat linkat
+#endif
+#endif /* __FreeBSD_version */
+
+static void
+filemon_output(struct filemon *filemon, char *msg, size_t len)
+{
+ struct uio auio;
+ struct iovec aiov;
+
+ 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;
+
+ bwillwrite();
+
+ fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread);
+}
+
+static struct filemon *
+filemon_pid_check(struct proc *p)
+{
+ struct filemon *filemon;
+
+ TAILQ_FOREACH(filemon, &filemons_inuse, link) {
+ if (p->p_pid == filemon->pid)
+ return (filemon);
+ }
+
+ if (p->p_pptr == NULL)
+ return (NULL);
+
+ return (filemon_pid_check(p->p_pptr));
+}
+
+static void
+filemon_comment(struct filemon *filemon)
+{
+ int len;
+ struct timeval now;
+
+ /* Load timestamp before locking. Less accurate but less contention. */
+ getmicrotime(&now);
+
+ /* Grab a read lock on the filemon inuse list. */
+ filemon_lock_read();
+
+ /* Lock the found filemon structure. */
+ filemon_filemon_lock(filemon);
+
+ 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);
+
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
+
+ /* Release the read lock. */
+ filemon_unlock_read();
+}
+
+static int
+filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
+{
+ int ret;
+ size_t done;
+ size_t len;
+ struct filemon *filemon;
+
+ if ((ret = sys_chdir(td, uap)) == 0) {
+ /* Grab a read lock on the filemon inuse list. */
+ filemon_lock_read();
+
+ if ((filemon = filemon_pid_check(curproc)) != NULL) {
+ /* Lock the found filemon structure. */
+ filemon_filemon_lock(filemon);
+
+ copyinstr(uap->path, filemon->fname1,
+ sizeof(filemon->fname1), &done);
+
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "C %d %s\n",
+ curproc->p_pid, filemon->fname1);
+
+ filemon_output(filemon, filemon->msgbufr, len);
+
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
+ }
+
+ /* Release the read lock. */
+ filemon_unlock_read();
+ }
+
+ return (ret);
+}
+
+static int
+filemon_wrapper_execve(struct thread *td, struct execve_args *uap)
+{
+ char fname[MAXPATHLEN];
+ int ret;
+ size_t done;
+ size_t len;
+ struct filemon *filemon;
+
+ copyinstr(uap->fname, fname, sizeof(fname), &done);
+
+ if ((ret = sys_execve(td, uap)) == 0) {
+ /* Grab a read lock on the filemon inuse list. */
+ filemon_lock_read();
+
+ if ((filemon = filemon_pid_check(curproc)) != NULL) {
+ /* Lock the found filemon structure. */
+ filemon_filemon_lock(filemon);
+
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "E %d %s\n",
+ curproc->p_pid, fname);
+
+ filemon_output(filemon, filemon->msgbufr, len);
+
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
+ }
+
+ /* Release the read lock. */
+ filemon_unlock_read();
+ }
+
+ return (ret);
+}
+
+#if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
+static int
+filemon_wrapper_freebsd32_execve(struct thread *td,
+ struct freebsd32_execve_args *uap)
+{
+ char fname[MAXPATHLEN];
+ int ret;
+ size_t done;
+ size_t len;
+ struct filemon *filemon;
+
+ copyinstr(uap->fname, fname, sizeof(fname), &done);
+
+ if ((ret = freebsd32_execve(td, uap)) == 0) {
+ /* Grab a read lock on the filemon inuse list. */
+ filemon_lock_read();
+
+ if ((filemon = filemon_pid_check(curproc)) != NULL) {
+ /* Lock the found filemon structure. */
+ filemon_filemon_lock(filemon);
+
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "E %d %s\n",
+ curproc->p_pid, fname);
+
+ filemon_output(filemon, filemon->msgbufr, len);
+
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
+ }
+
+ /* Release the read lock. */
+ filemon_unlock_read();
+ }
+
+ return (ret);
+}
+#endif
+
+static int
+filemon_wrapper_fork(struct thread *td, struct fork_args *uap)
+{
+ int ret;
+ size_t len;
+ struct filemon *filemon;
+
+ if ((ret = sys_fork(td, uap)) == 0) {
+ /* Grab a read lock on the filemon inuse list. */
+ filemon_lock_read();
+
+ if ((filemon = filemon_pid_check(curproc)) != NULL) {
+ /* Lock the found filemon structure. */
+ filemon_filemon_lock(filemon);
+
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "F %d %ld\n",
+ curproc->p_pid, (long)curthread->td_retval[0]);
+
+ filemon_output(filemon, filemon->msgbufr, len);
+
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
+ }
+
+ /* Release the read lock. */
+ filemon_unlock_read();
+ }
+
+ return (ret);
+}
+
+static int
+filemon_wrapper_open(struct thread *td, struct open_args *uap)
+{
+ int ret;
+ size_t done;
+ size_t len;
+ struct filemon *filemon;
+
+ if ((ret = sys_open(td, uap)) == 0) {
+ /* Grab a read lock on the filemon inuse list. */
+ filemon_lock_read();
+
+ if ((filemon = filemon_pid_check(curproc)) != NULL) {
+ /* Lock the found filemon structure. */
+ filemon_filemon_lock(filemon);
+
+ copyinstr(uap->path, filemon->fname1,
+ sizeof(filemon->fname1), &done);
+
+ if (uap->flags & O_RDWR) {
+ /*
+ * We'll get the W record below, but need
+ * to also output an R to distingish from
+ * O_WRONLY.
+ */
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "R %d %s\n",
+ curproc->p_pid, filemon->fname1);
+ filemon_output(filemon, filemon->msgbufr, len);
+ }
+
+
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "%c %d %s\n",
+ (uap->flags & O_ACCMODE) ? 'W':'R',
+ curproc->p_pid, filemon->fname1);
+ filemon_output(filemon, filemon->msgbufr, len);
+
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
+ }
+
+ /* Release the read lock. */
+ filemon_unlock_read();
+ }
+
+ return (ret);
+}
+
+static int
+filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
+{
+ int ret;
+ size_t done;
+ size_t len;
+ struct filemon *filemon;
+
+ if ((ret = sys_rename(td, uap)) == 0) {
+ /* Grab a read lock on the filemon inuse list. */
+ filemon_lock_read();
+
+ if ((filemon = filemon_pid_check(curproc)) != NULL) {
+ /* Lock the found filemon structure. */
+ filemon_filemon_lock(filemon);
+
+ copyinstr(uap->from, filemon->fname1,
+ sizeof(filemon->fname1), &done);
+ copyinstr(uap->to, filemon->fname2,
+ sizeof(filemon->fname2), &done);
+
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "M %d '%s' '%s'\n",
+ curproc->p_pid, filemon->fname1, filemon->fname2);
+
+ filemon_output(filemon, filemon->msgbufr, len);
+
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
+ }
+
+ /* Release the read lock. */
+ filemon_unlock_read();
+ }
+
+ return (ret);
+}
+
+static int
+filemon_wrapper_link(struct thread *td, struct link_args *uap)
+{
+ int ret;
+ size_t done;
+ size_t len;
+ struct filemon *filemon;
+
+ if ((ret = sys_link(td, uap)) == 0) {
+ /* Grab a read lock on the filemon inuse list. */
+ filemon_lock_read();
+
+ if ((filemon = filemon_pid_check(curproc)) != NULL) {
+ /* Lock the found filemon structure. */
+ filemon_filemon_lock(filemon);
+
+ copyinstr(uap->path, filemon->fname1,
+ sizeof(filemon->fname1), &done);
+ copyinstr(uap->link, filemon->fname2,
+ sizeof(filemon->fname2), &done);
+
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
+ curproc->p_pid, filemon->fname1, filemon->fname2);
+
+ filemon_output(filemon, filemon->msgbufr, len);
+
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
+ }
+
+ /* Release the read lock. */
+ filemon_unlock_read();
+ }
+
+ return (ret);
+}
+
+static int
+filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
+{
+ int ret;
+ size_t done;
+ size_t len;
+ struct filemon *filemon;
+
+ if ((ret = sys_symlink(td, uap)) == 0) {
+ /* Grab a read lock on the filemon inuse list. */
+ filemon_lock_read();
+
+ if ((filemon = filemon_pid_check(curproc)) != NULL) {
+ /* Lock the found filemon structure. */
+ filemon_filemon_lock(filemon);
+
+ copyinstr(uap->path, filemon->fname1,
+ sizeof(filemon->fname1), &done);
+ copyinstr(uap->link, filemon->fname2,
+ sizeof(filemon->fname2), &done);
+
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
+ curproc->p_pid, filemon->fname1, filemon->fname2);
+
+ filemon_output(filemon, filemon->msgbufr, len);
+
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
+ }
+
+ /* Release the read lock. */
+ filemon_unlock_read();
+ }
+
+ return (ret);
+}
+
+#ifdef FILEMON_HAS_LINKAT
+static int
+filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
+{
+ int ret;
+ size_t done;
+ size_t len;
+ struct filemon *filemon;
+
+ if ((ret = sys_linkat(td, uap)) == 0) {
+ /* Grab a read lock on the filemon inuse list. */
+ filemon_lock_read();
+
+ if ((filemon = filemon_pid_check(curproc)) != NULL) {
+ /* Lock the found filemon structure. */
+ filemon_filemon_lock(filemon);
+
+ copyinstr(uap->path1, filemon->fname1,
+ sizeof(filemon->fname1), &done);
+ copyinstr(uap->path2, filemon->fname2,
+ sizeof(filemon->fname2), &done);
+
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
+ curproc->p_pid, filemon->fname1, filemon->fname2);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-head
mailing list