summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/filemon/filemon.c15
-rw-r--r--sys/dev/filemon/filemon.h10
-rw-r--r--sys/dev/filemon/filemon_wrapper.c121
3 files changed, 109 insertions, 37 deletions
diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c
index b8e710d6e23..fe87d6e1e2e 100644
--- a/sys/dev/filemon/filemon.c
+++ b/sys/dev/filemon/filemon.c
@@ -1,4 +1,4 @@
-/* $NetBSD: filemon.c,v 1.21 2015/11/24 01:05:50 pgoyette Exp $ */
+/* $NetBSD: filemon.c,v 1.22 2015/11/25 07:34:49 pgoyette Exp $ */
/*
* Copyright (c) 2010, Juniper Networks, Inc.
*
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: filemon.c,v 1.21 2015/11/24 01:05:50 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: filemon.c,v 1.22 2015/11/25 07:34:49 pgoyette Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -340,13 +340,13 @@ filemon_ioctl(struct file * fp, u_long cmd, void *data)
return (error);
}
-static void
+static int
filemon_load(void *dummy __unused)
{
rw_init(&filemon_mtx);
/* Install the syscall wrappers. */
- filemon_wrapper_install();
+ return filemon_wrapper_install();
}
/*
@@ -400,9 +400,10 @@ filemon_modcmd(modcmd_t cmd, void *data)
logLevel = LOG_INFO;
#endif
- filemon_load(data);
- error = devsw_attach("filemon", NULL, &bmajor,
- &filemon_cdevsw, &cmajor);
+ error = filemon_load(data);
+ if (!error)
+ error = devsw_attach("filemon", NULL, &bmajor,
+ &filemon_cdevsw, &cmajor);
break;
case MODULE_CMD_FINI:
diff --git a/sys/dev/filemon/filemon.h b/sys/dev/filemon/filemon.h
index 544f61ff982..1f8f8e0b1eb 100644
--- a/sys/dev/filemon/filemon.h
+++ b/sys/dev/filemon/filemon.h
@@ -1,4 +1,4 @@
-/* $NetBSD: filemon.h,v 1.7 2015/09/06 06:01:00 dholland Exp $ */
+/* $NetBSD: filemon.h,v 1.8 2015/11/25 07:34:49 pgoyette Exp $ */
/*
* Copyright (c) 2010, Juniper Networks, Inc.
*
@@ -47,9 +47,15 @@ struct filemon {
TAILQ_ENTRY(filemon) fm_link; /* Link into the in-use list. */
};
+struct hijack {
+ int hj_index;
+ sy_call_t *hj_funcs[2]; /* [0] = original, [1] = hijack */
+};
+
struct filemon * filemon_lookup(struct proc *);
void filemon_output(struct filemon *, char *, size_t);
-void filemon_wrapper_install(void);
+int syscall_hijack(struct sysent *, const struct hijack *, bool);
+int filemon_wrapper_install(void);
int filemon_wrapper_deinstall(void);
void filemon_printf(struct filemon *, const char *, ...) __printflike(2, 3);
#endif
diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c
index 7d2bea07a01..ed43f29d58a 100644
--- a/sys/dev/filemon/filemon_wrapper.c
+++ b/sys/dev/filemon/filemon_wrapper.c
@@ -1,4 +1,4 @@
-/* $NetBSD: filemon_wrapper.c,v 1.10 2015/11/23 00:47:43 pgoyette Exp $ */
+/* $NetBSD: filemon_wrapper.c,v 1.11 2015/11/25 07:34:49 pgoyette Exp $ */
/*
* Copyright (c) 2010, Juniper Networks, Inc.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: filemon_wrapper.c,v 1.10 2015/11/23 00:47:43 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: filemon_wrapper.c,v 1.11 2015/11/25 07:34:49 pgoyette Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -39,6 +39,83 @@ __KERNEL_RCSID(0, "$NetBSD: filemon_wrapper.c,v 1.10 2015/11/23 00:47:43 pgoyett
#include "filemon.h"
+static int filemon_wrapper_chdir(struct lwp *, const struct sys_chdir_args *,
+ register_t *);
+static int filemon_wrapper_execve(struct lwp *, struct sys_execve_args *,
+ register_t *);
+static void filemon_wrapper_sys_exit(struct lwp *, struct sys_exit_args *,
+ register_t *);
+static int filemon_wrapper_fork(struct lwp *, const void *, register_t *);
+static int filemon_wrapper_link(struct lwp *, struct sys_link_args *,
+ register_t *);
+static int filemon_wrapper_open(struct lwp *, struct sys_open_args *,
+ register_t *);
+static int filemon_wrapper_openat(struct lwp *, struct sys_openat_args *,
+ register_t *);
+static int filemon_wrapper_rename(struct lwp *, struct sys_rename_args *,
+ register_t *);
+static int filemon_wrapper_symlink(struct lwp *, struct sys_symlink_args *,
+ register_t *);
+static int filemon_wrapper_unlink(struct lwp *, struct sys_unlink_args *,
+ register_t *);
+static int filemon_wrapper_vfork(struct lwp *, const void *, register_t *);
+
+const struct hijack filemon_hijack[] = {
+ { SYS_chdir,
+ { (sy_call_t *)sys_chdir, (sy_call_t *)filemon_wrapper_chdir } },
+ { SYS_execve,
+ { (sy_call_t *)sys_execve, (sy_call_t *)filemon_wrapper_execve } },
+ { SYS_exit,
+ { (sy_call_t *)sys_exit, (sy_call_t *)filemon_wrapper_sys_exit } },
+ { SYS_fork,
+ { (sy_call_t *)sys_fork, (sy_call_t *)filemon_wrapper_fork } },
+ { SYS_link,
+ { (sy_call_t *)sys_link, (sy_call_t *)filemon_wrapper_link } },
+ { SYS_open,
+ { (sy_call_t *)sys_open, (sy_call_t *)filemon_wrapper_open } },
+ { SYS_openat,
+ { (sy_call_t *)sys_openat, (sy_call_t *)filemon_wrapper_openat } },
+ { SYS_rename,
+ { (sy_call_t *)sys_rename, (sy_call_t *)filemon_wrapper_rename } },
+ { SYS_symlink,
+ { (sy_call_t *)sys_symlink, (sy_call_t *)filemon_wrapper_symlink } },
+ { SYS_unlink,
+ { (sy_call_t *)sys_unlink, (sy_call_t *)filemon_wrapper_unlink } },
+ { SYS_vfork,
+ { (sy_call_t *)sys_vfork, (sy_call_t *)filemon_wrapper_vfork } },
+ { -1, {NULL, NULL } }
+};
+
+int
+syscall_hijack(struct sysent *sv_table, const struct hijack *hj_pkg,
+ bool restore)
+{
+ int from, to;
+ const struct hijack *entry;
+
+ if (restore) /* Which entry should currently match? */
+ from = 1;
+ else
+ from = 0;
+ to = 1 - from; /* Which entry will we replace with? */
+
+ KASSERT(kernconfig_is_held());
+
+ /* First, make sure that all of the old values match */
+ for (entry = hj_pkg; entry->hj_index >= 0; entry++)
+ if (sv_table[entry->hj_index].sy_call != entry->hj_funcs[from])
+ break;
+
+ if (entry->hj_index >= 0)
+ return EBUSY;
+
+ /* Now replace the old values with the new ones */
+ for (entry = hj_pkg; entry->hj_index >= 0; entry++)
+ sv_table[entry->hj_index].sy_call = entry->hj_funcs[to];
+
+ return 0;
+}
+
static int
filemon_wrapper_chdir(struct lwp * l, const struct sys_chdir_args * uap,
register_t * retval)
@@ -322,6 +399,7 @@ filemon_wrapper_sys_exit(struct lwp * l, struct sys_exit_args * uap,
rw_exit(&filemon->fm_mtx);
}
sys_exit(l, uap, retval);
+ /* NOT REACHED */
}
static int
@@ -352,41 +430,28 @@ out:
}
-void
+int
filemon_wrapper_install(void)
{
+ int error;
struct sysent *sv_table = emul_netbsd.e_sysent;
- sv_table[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
- sv_table[SYS_execve].sy_call = (sy_call_t *) filemon_wrapper_execve;
- sv_table[SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit;
- sv_table[SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork;
- sv_table[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
- sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
- sv_table[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
- sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
- sv_table[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
- sv_table[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
- sv_table[SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork;
+ kernconfig_lock();
+ error = syscall_hijack(sv_table, filemon_hijack, false);
+ kernconfig_unlock();
+
+ return error;
}
int
filemon_wrapper_deinstall(void)
{
+ int error;
struct sysent *sv_table = emul_netbsd.e_sysent;
- if (sv_table[SYS_chdir].sy_call != (sy_call_t *) filemon_wrapper_chdir)
- return EBUSY;
- sv_table[SYS_chdir].sy_call = (sy_call_t *) sys_chdir;
- sv_table[SYS_execve].sy_call = (sy_call_t *) sys_execve;
- sv_table[SYS_exit].sy_call = (sy_call_t *) sys_exit;
- sv_table[SYS_fork].sy_call = (sy_call_t *) sys_fork;
- sv_table[SYS_link].sy_call = (sy_call_t *) sys_link;
- sv_table[SYS_open].sy_call = (sy_call_t *) sys_open;
- sv_table[SYS_openat].sy_call = (sy_call_t *) sys_openat;
- sv_table[SYS_rename].sy_call = (sy_call_t *) sys_rename;
- sv_table[SYS_symlink].sy_call = (sy_call_t *) sys_symlink;
- sv_table[SYS_unlink].sy_call = (sy_call_t *) sys_unlink;
- sv_table[SYS_vfork].sy_call = (sy_call_t *) sys_vfork;
- return 0;
+ kernconfig_lock();
+ error = syscall_hijack(sv_table, filemon_hijack, true);
+ kernconfig_unlock();
+
+ return error;
}