summaryrefslogtreecommitdiff
path: root/sys/kern/sys_module.c
diff options
context:
space:
mode:
authorad <ad@NetBSD.org>2008-01-16 12:34:50 +0000
committerad <ad@NetBSD.org>2008-01-16 12:34:50 +0000
commitbbc79e58a6b48edc15ae7b2ed8364880fddce1e7 (patch)
tree6d440cbcabd2266a3a662898fa5827974c00ff74 /sys/kern/sys_module.c
parent257a88e757110a1158f1cbf6be74f050d52f27d6 (diff)
Pull in my modules code for review/test/hacking.
Diffstat (limited to 'sys/kern/sys_module.c')
-rw-r--r--sys/kern/sys_module.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/sys/kern/sys_module.c b/sys/kern/sys_module.c
new file mode 100644
index 00000000000..5cf042334db
--- /dev/null
+++ b/sys/kern/sys_module.c
@@ -0,0 +1,153 @@
+/* $NetBSD: sys_module.c,v 1.1 2008/01/16 12:34:51 ad Exp $ */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION 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.
+ */
+
+/*
+ * System calls relating to loadable modules.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sys_module.c,v 1.1 2008/01/16 12:34:51 ad Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/kauth.h>
+#include <sys/kobj.h>
+#include <sys/kmem.h>
+#include <sys/module.h>
+#include <sys/kauth.h>
+#include <sys/syscall.h>
+#include <sys/syscallargs.h>
+
+int
+sys_modctl(struct lwp *l, const struct sys_modctl_args *uap,
+ register_t *retval)
+{
+ /* {
+ syscallarg(int) cmd;
+ syscallarg(void *) arg;
+ } */
+ char buf[MAXMODNAME];
+ size_t mslen;
+ module_t *mod;
+ modinfo_t *mi;
+ modstat_t *ms, *mso;
+ vaddr_t addr;
+ size_t size;
+ struct iovec iov;
+ int error;
+ void *arg;
+
+ arg = SCARG(uap, arg);
+
+ switch (SCARG(uap, cmd)) {
+ case MODCTL_LOAD:
+ case MODCTL_FORCELOAD:
+ case MODCTL_UNLOAD:
+ /* Authorize. */
+ error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MODULE,
+ 0, (void *)SCARG(uap, cmd), NULL, NULL);
+ if (error != 0) {
+ return error;
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (SCARG(uap, cmd)) {
+ case MODCTL_FORCELOAD:
+ case MODCTL_LOAD:
+ error = copyinstr(arg, buf, sizeof(buf) - 1, NULL);
+ if (error == 0) {
+ error = module_load(buf,
+ SCARG(uap, cmd) == MODCTL_FORCELOAD);
+ }
+ break;
+
+ case MODCTL_UNLOAD:
+ error = copyinstr(arg, buf, sizeof(buf) - 1, NULL);
+ if (error == 0) {
+ error = module_unload(buf);
+ }
+ break;
+
+ case MODCTL_STAT:
+ error = copyin(arg, &iov, sizeof(iov));
+ if (error != 0) {
+ break;
+ }
+ mutex_enter(&module_lock);
+ mslen = (module_count + 1) * sizeof(modstat_t);
+ mso = kmem_zalloc(mslen, KM_SLEEP);
+ if (mso == NULL) {
+ mutex_exit(&module_lock);
+ return ENOMEM;
+ }
+ ms = mso;
+ TAILQ_FOREACH(mod, &module_list, mod_chain) {
+ mi = mod->mod_info;
+ strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name));
+ if (mi->mi_required != NULL) {
+ strlcpy(ms->ms_required, mi->mi_required,
+ sizeof(ms->ms_required));
+ }
+ if (mod->mod_kobj != NULL) {
+ kobj_stat(mod->mod_kobj, &addr, &size);
+ ms->ms_addr = addr;
+ ms->ms_size = size;
+ }
+ ms->ms_class = mi->mi_class;
+ ms->ms_refcnt = mod->mod_refcnt;
+ ms->ms_source = mod->mod_source;
+ ms++;
+ }
+ mutex_exit(&module_lock);
+ error = copyout(mso, iov.iov_base,
+ min(mslen - sizeof(modstat_t), iov.iov_len));
+ kmem_free(mso, mslen);
+ if (error == 0) {
+ iov.iov_len = mslen - sizeof(modstat_t);
+ error = copyout(&iov, arg, sizeof(iov));
+ }
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}