diff options
| author | ad <ad@NetBSD.org> | 2008-01-16 12:34:50 +0000 |
|---|---|---|
| committer | ad <ad@NetBSD.org> | 2008-01-16 12:34:50 +0000 |
| commit | bbc79e58a6b48edc15ae7b2ed8364880fddce1e7 (patch) | |
| tree | 6d440cbcabd2266a3a662898fa5827974c00ff74 /sys/kern/sys_module.c | |
| parent | 257a88e757110a1158f1cbf6be74f050d52f27d6 (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.c | 153 |
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; +} |
