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.
This commit is contained in:
parent
5c8d326cba
commit
eb9aea5ac0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=236592
377
sys/dev/filemon/filemon.c
Normal file
377
sys/dev/filemon/filemon.c
Normal file
@ -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);
|
34
sys/dev/filemon/filemon.h
Normal file
34
sys/dev/filemon/filemon.h
Normal file
@ -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) */
|
122
sys/dev/filemon/filemon_lock.c
Normal file
122
sys/dev/filemon/filemon_lock.c
Normal file
@ -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);
|
||||
}
|
746
sys/dev/filemon/filemon_wrapper.c
Normal file
746
sys/dev/filemon/filemon_wrapper.c
Normal file
@ -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);
|
||||
|
||||
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_stat(struct thread *td, struct stat_args *uap)
|
||||
{
|
||||
int ret;
|
||||
size_t done;
|
||||
size_t len;
|
||||
struct filemon *filemon;
|
||||
|
||||
if ((ret = sys_stat(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), "S %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);
|
||||
}
|
||||
|
||||
#if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
|
||||
static int
|
||||
filemon_wrapper_freebsd32_stat(struct thread *td,
|
||||
struct freebsd32_stat_args *uap)
|
||||
{
|
||||
int ret;
|
||||
size_t done;
|
||||
size_t len;
|
||||
struct filemon *filemon;
|
||||
|
||||
if ((ret = freebsd32_stat(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), "S %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);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
filemon_wrapper_sys_exit(struct thread *td, struct sys_exit_args *uap)
|
||||
{
|
||||
size_t len;
|
||||
struct filemon *filemon;
|
||||
struct timeval now;
|
||||
|
||||
/* Get timestamp before locking. */
|
||||
getmicrotime(&now);
|
||||
|
||||
/* 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),
|
||||
"X %d %d\n", curproc->p_pid, uap->rval);
|
||||
|
||||
filemon_output(filemon, filemon->msgbufr, len);
|
||||
|
||||
/* Check if the monitored process is about to exit. */
|
||||
if (filemon->pid == curproc->p_pid) {
|
||||
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);
|
||||
}
|
||||
|
||||
/* Unlock the found filemon structure. */
|
||||
filemon_filemon_unlock(filemon);
|
||||
}
|
||||
|
||||
/* Release the read lock. */
|
||||
filemon_unlock_read();
|
||||
|
||||
sys_sys_exit(td, uap);
|
||||
}
|
||||
|
||||
static int
|
||||
filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap)
|
||||
{
|
||||
int ret;
|
||||
size_t done;
|
||||
size_t len;
|
||||
struct filemon *filemon;
|
||||
|
||||
if ((ret = sys_unlink(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), "D %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_vfork(struct thread *td, struct vfork_args *uap)
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
struct filemon *filemon;
|
||||
|
||||
if ((ret = sys_vfork(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 void
|
||||
filemon_wrapper_install(void)
|
||||
{
|
||||
#if defined(__i386__)
|
||||
struct sysent *sv_table = elf32_freebsd_sysvec.sv_table;
|
||||
#elif defined(__amd64__)
|
||||
struct sysent *sv_table = elf64_freebsd_sysvec.sv_table;
|
||||
#else
|
||||
#error Machine type not supported
|
||||
#endif
|
||||
|
||||
sv_table[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
|
||||
sv_table[SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit;
|
||||
sv_table[SYS_execve].sy_call = (sy_call_t *) filemon_wrapper_execve;
|
||||
sv_table[SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork;
|
||||
sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
|
||||
sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
|
||||
sv_table[SYS_stat].sy_call = (sy_call_t *) filemon_wrapper_stat;
|
||||
sv_table[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
|
||||
sv_table[SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork;
|
||||
sv_table[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
|
||||
sv_table[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
|
||||
#ifdef FILEMON_HAS_LINKAT
|
||||
sv_table[SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
|
||||
#endif
|
||||
|
||||
#if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
|
||||
sv_table = ia32_freebsd_sysvec.sv_table;
|
||||
|
||||
sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
|
||||
sv_table[FREEBSD32_SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit;
|
||||
sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_execve;
|
||||
sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork;
|
||||
sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
|
||||
sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
|
||||
sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_stat;
|
||||
sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
|
||||
sv_table[FREEBSD32_SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork;
|
||||
sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
|
||||
sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
|
||||
#ifdef FILEMON_HAS_LINKAT
|
||||
sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
|
||||
#endif
|
||||
#endif /* COMPAT_ARCH32 */
|
||||
}
|
||||
|
||||
static void
|
||||
filemon_wrapper_deinstall(void)
|
||||
{
|
||||
#if defined(__i386__)
|
||||
struct sysent *sv_table = elf32_freebsd_sysvec.sv_table;
|
||||
#elif defined(__amd64__)
|
||||
struct sysent *sv_table = elf64_freebsd_sysvec.sv_table;
|
||||
#else
|
||||
#error Machine type not supported
|
||||
#endif
|
||||
|
||||
sv_table[SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
|
||||
sv_table[SYS_exit].sy_call = (sy_call_t *)sys_sys_exit;
|
||||
sv_table[SYS_execve].sy_call = (sy_call_t *)sys_execve;
|
||||
sv_table[SYS_fork].sy_call = (sy_call_t *)sys_fork;
|
||||
sv_table[SYS_open].sy_call = (sy_call_t *)sys_open;
|
||||
sv_table[SYS_rename].sy_call = (sy_call_t *)sys_rename;
|
||||
sv_table[SYS_stat].sy_call = (sy_call_t *)sys_stat;
|
||||
sv_table[SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
|
||||
sv_table[SYS_vfork].sy_call = (sy_call_t *)sys_vfork;
|
||||
sv_table[SYS_link].sy_call = (sy_call_t *)sys_link;
|
||||
sv_table[SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
|
||||
#ifdef FILEMON_HAS_LINKAT
|
||||
sv_table[SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
|
||||
#endif
|
||||
|
||||
#if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
|
||||
sv_table = ia32_freebsd_sysvec.sv_table;
|
||||
|
||||
sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
|
||||
sv_table[FREEBSD32_SYS_exit].sy_call = (sy_call_t *)sys_sys_exit;
|
||||
sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *)freebsd32_execve;
|
||||
sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *)sys_fork;
|
||||
sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open;
|
||||
sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename;
|
||||
sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *)freebsd32_stat;
|
||||
sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
|
||||
sv_table[FREEBSD32_SYS_vfork].sy_call = (sy_call_t *)sys_vfork;
|
||||
sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *)sys_link;
|
||||
sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
|
||||
#ifdef FILEMON_HAS_LINKAT
|
||||
sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
|
||||
#endif
|
||||
#endif /* COMPAT_ARCH32 */
|
||||
}
|
@ -105,6 +105,7 @@ SUBDIR= ${_3dfx} \
|
||||
fdc \
|
||||
fdescfs \
|
||||
${_fe} \
|
||||
${_filemon} \
|
||||
firewire \
|
||||
firmware \
|
||||
${_fxp} \
|
||||
@ -359,6 +360,7 @@ SUBDIR= ${_3dfx} \
|
||||
|
||||
.if ${MACHINE_CPUARCH} != "powerpc" && ${MACHINE_CPUARCH} != "arm" && \
|
||||
${MACHINE_CPUARCH} != "mips"
|
||||
_filemon= filemon
|
||||
_syscons= syscons
|
||||
_vpo= vpo
|
||||
.endif
|
||||
|
11
sys/modules/filemon/Makefile
Normal file
11
sys/modules/filemon/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
|
||||
MAINTAINER= obrien@FreeBSD.org
|
||||
|
||||
.PATH: ${.CURDIR}/../../dev/filemon
|
||||
|
||||
KMOD= filemon
|
||||
SRCS= ${KMOD}.c
|
||||
SRCS+= vnode_if.h opt_compat.h opt_capsicum.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
Loading…
Reference in New Issue
Block a user