Module Name: src
Committed By: pgoyette
Date: Tue Apr 3 08:29:44 UTC 2018
Modified Files:
src/doc [pgoyette-compat]: COMPAT-branch-notes
src/lib/libc/sys [pgoyette-compat]: modctl.2
src/sbin/modstat [pgoyette-compat]: main.c
src/sys/compat/common [pgoyette-compat]: Makefile.sysio compat_80_mod.c
compat_mod.h files.common
src/sys/compat/netbsd32 [pgoyette-compat]: netbsd32_module.c
src/sys/kern [pgoyette-compat]: compat_stub.c sys_module.c
src/sys/modules/compat_80 [pgoyette-compat]: Makefile
src/sys/sys [pgoyette-compat]: compat_stub.h module.h
Added Files:
src/sys/compat/common [pgoyette-compat]: kern_mod_80.c
Log Message:
Remove fixed allocation of modules' "required" lists (previously
limited to MAXMODDEPS entries). Update the modctl(MODCTL_STAT)
syscall to return the required data in a new format, and retain
the previous data format in MODCTL_OSTAT. Update the compat_80
and compat_netbsd32 modules as needed.
To generate a diff of this commit:
cvs rdiff -u -r1.1.2.8 -r1.1.2.9 src/doc/COMPAT-branch-notes
cvs rdiff -u -r1.13 -r1.13.4.1 src/lib/libc/sys/modctl.2
cvs rdiff -u -r1.24.12.1 -r1.24.12.2 src/sbin/modstat/main.c
cvs rdiff -u -r1.7.18.19 -r1.7.18.20 src/sys/compat/common/Makefile.sysio
cvs rdiff -u -r1.1.2.6 -r1.1.2.7 src/sys/compat/common/compat_80_mod.c
cvs rdiff -u -r1.1.42.17 -r1.1.42.18 src/sys/compat/common/compat_mod.h
cvs rdiff -u -r1.1.2.29 -r1.1.2.30 src/sys/compat/common/files.common
cvs rdiff -u -r0 -r1.1.2.1 src/sys/compat/common/kern_mod_80.c
cvs rdiff -u -r1.6 -r1.6.2.1 src/sys/compat/netbsd32/netbsd32_module.c
cvs rdiff -u -r1.1.2.13 -r1.1.2.14 src/sys/kern/compat_stub.c
cvs rdiff -u -r1.23.2.5 -r1.23.2.6 src/sys/kern/sys_module.c
cvs rdiff -u -r1.1.2.2 -r1.1.2.3 src/sys/modules/compat_80/Makefile
cvs rdiff -u -r1.1.2.13 -r1.1.2.14 src/sys/sys/compat_stub.h
cvs rdiff -u -r1.41.14.7 -r1.41.14.8 src/sys/sys/module.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/doc/COMPAT-branch-notes
diff -u src/doc/COMPAT-branch-notes:1.1.2.8 src/doc/COMPAT-branch-notes:1.1.2.9
--- src/doc/COMPAT-branch-notes:1.1.2.8 Wed Mar 28 03:41:26 2018
+++ src/doc/COMPAT-branch-notes Tue Apr 3 08:29:44 2018
@@ -27,6 +27,11 @@ DONE
defopt/defflag lines in the config files* as needed, to insure that
built-in dependencies get resolved.
+8. Fixed limits on the number of module depedencies and maximum
+ recursion level have been removed. Previous code for reporting
+ module status to userland has been versioned and moved to the
+ compat_80 module.
+
TODO
----
Index: src/lib/libc/sys/modctl.2
diff -u src/lib/libc/sys/modctl.2:1.13 src/lib/libc/sys/modctl.2:1.13.4.1
--- src/lib/libc/sys/modctl.2:1.13 Mon Jul 3 21:32:50 2017
+++ src/lib/libc/sys/modctl.2 Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-.\" $NetBSD: modctl.2,v 1.13 2017/07/03 21:32:50 wiz Exp $
+.\" $NetBSD: modctl.2,v 1.13.4.1 2018/04/03 08:29:44 pgoyette Exp $
.\"
.\" Copyright (c) 2009 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -74,9 +74,19 @@ In this case, the
argument should be a
.Em struct iovec
pointing to a suitable block of memory.
-The kernel will fill this block with an array of
+The kernel will fill this block with
+.Bl -bullet
+.It
+a count of the number of modules loaded (including aliases),
+.It
+an array of
.Em modstat_t
-structures, one per loaded module.
+structures, one per loaded module, and
+.It
+a series of NUL-terminated strings containing the modules'
+required modules lists.
+.El
+.Pp
If the block is not large enough, the data returned will be truncated
to fit.
The kernel will then update the
@@ -146,9 +156,6 @@ contains the following elements, which a
.Bl -tag -width aaaaaaaa
.It Fa "char ms_name[MAXMODNAME]"
The name of the module.
-.It Fa "char ms_required[MAXMODNAME * MAXMODDEPS]"
-The list of modules required by this module
-as a comma-delimited list of module names.
.It Fa "modsrc_t ms_source"
One of the following enumerated constants:
.Bl -tag -compact -width "MODULE_SOURCE_FILESYS"
@@ -172,14 +179,13 @@ Device driver.
Executable file format.
.It Dv MODULE_CLASS_MISC
Miscellaneous.
-.It Dv MODULE_CLASS_ANY
-Any module class.
-.\" XXX: is MODULE_CLASS_ANY ever returned by this interface?
.El
.It Fa "uint64_t ms_addr"
The load address within the kernel.
+(This value is available only for privileged users.)
.It Fa "u_int ms_size"
Loaded size of the module.
+(This value is available only for privileged users.)
.It Fa "u_int ms_refcnt"
Current number of live references to this module.
.It Fa "u_int ms_flags"
@@ -190,6 +196,8 @@ The "force" flag must be specified to re
.It Dv MODFLAG_AUTO_LOADED
The module was auto-loaded by the operating system.
.El
+.It Fa "uint_ms_reqoffset"
+The offset (in bytes) from the beginning of the required-module data.
.El
.Sh RETURN VALUES
Upon successful completion, the value returned is 0.
Index: src/sbin/modstat/main.c
diff -u src/sbin/modstat/main.c:1.24.12.1 src/sbin/modstat/main.c:1.24.12.2
--- src/sbin/modstat/main.c:1.24.12.1 Sat Mar 10 10:33:40 2018
+++ src/sbin/modstat/main.c Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.24.12.1 2018/03/10 10:33:40 pgoyette Exp $ */
+/* $NetBSD: main.c,v 1.24.12.2 2018/04/03 08:29:44 pgoyette Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: main.c,v 1.24.12.1 2018/03/10 10:33:40 pgoyette Exp $");
+__RCSID("$NetBSD: main.c,v 1.24.12.2 2018/04/03 08:29:44 pgoyette Exp $");
#endif /* !lint */
#include <sys/module.h>
@@ -81,6 +81,7 @@ main(int argc, char **argv)
int ch, rc, modauto = 1;
size_t maxnamelen = 16, i, modautolen;
char loadable = '\0';
+ const char *reqoff, *req;
bool address = false;
name = NULL;
@@ -177,29 +178,36 @@ main(int argc, char **argv)
len = iov.iov_len;
}
- len = iov.iov_len / sizeof(modstat_t);
- qsort(iov.iov_base, len, sizeof(modstat_t), modstatcmp);
- for (i = 0, ms = iov.iov_base; i < len; i++, ms++) {
+ len = *(int *)iov.iov_base;
+ ms = (modstat_t *)((char *)iov.iov_base + sizeof(int));
+
+ qsort(ms, len, sizeof(modstat_t), modstatcmp);
+ for (i = 0; i < len; i++, ms++) {
size_t namelen = strlen(ms->ms_name);
if (maxnamelen < namelen)
maxnamelen = namelen;
}
+ ms = (modstat_t *)((char *)iov.iov_base + sizeof(int));
+ reqoff = (char *)(&ms[len]);
+
printf("%-*s %-8s %-8s %-4s %5s ",
(int)maxnamelen, "NAME", "CLASS", "SOURCE", "FLAG", "REFS");
if (address)
printf("%-16s ", "ADDRESS");
printf("%7s %s \n", "SIZE", "REQUIRES");
- for (ms = iov.iov_base; len != 0; ms++, len--) {
+
+ for (; len != 0; ms++, len--) {
const char *class;
const char *source;
+ if (ms->ms_reqoffset == 0)
+ req = "-";
+ else {
+ req = &reqoff[ms->ms_reqoffset];
+ }
if (name != NULL && strcmp(ms->ms_name, name) != 0) {
continue;
}
- if (ms->ms_required[0] == '\0') {
- ms->ms_required[0] = '-';
- ms->ms_required[1] = '\0';
- }
if (ms->ms_size == 0) {
sbuf[0] = '-';
sbuf[1] = '\0';
@@ -221,7 +229,7 @@ main(int argc, char **argv)
ms->ms_refcnt);
if (address)
printf("%-16" PRIx64 " ", ms->ms_addr);
- printf("%7s %s\n", sbuf, ms->ms_required);
+ printf("%7s %s\n", sbuf, (req));
}
exit(EXIT_SUCCESS);
Index: src/sys/compat/common/Makefile.sysio
diff -u src/sys/compat/common/Makefile.sysio:1.7.18.19 src/sys/compat/common/Makefile.sysio:1.7.18.20
--- src/sys/compat/common/Makefile.sysio:1.7.18.19 Thu Mar 29 23:23:03 2018
+++ src/sys/compat/common/Makefile.sysio Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.sysio,v 1.7.18.19 2018/03/29 23:23:03 pgoyette Exp $
+# $NetBSD: Makefile.sysio,v 1.7.18.20 2018/04/03 08:29:44 pgoyette Exp $
# Sources for syscall and ioctl compatibility across the versions.
@@ -45,6 +45,9 @@ SRCS+= kern_sa_60.c tty_60.c kern_time_6
# Compatibility code for NetBSD 7.0
SRCS+= rtsock_70.c uipc_usrreq_70.c
+# Compatability code for NetBSD 8.0
+SRCS+= kern_mod_80.c
+
# More compatibility code for NetBSD 5.0
.PATH: ${S}/opencrypto
SRCS+= ocryptodev.c
Index: src/sys/compat/common/compat_80_mod.c
diff -u src/sys/compat/common/compat_80_mod.c:1.1.2.6 src/sys/compat/common/compat_80_mod.c:1.1.2.7
--- src/sys/compat/common/compat_80_mod.c:1.1.2.6 Sat Mar 24 08:10:49 2018
+++ src/sys/compat/common/compat_80_mod.c Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: compat_80_mod.c,v 1.1.2.6 2018/03/24 08:10:49 pgoyette Exp $ */
+/* $NetBSD: compat_80_mod.c,v 1.1.2.7 2018/04/03 08:29:44 pgoyette Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: compat_80_mod.c,v 1.1.2.6 2018/03/24 08:10:49 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: compat_80_mod.c,v 1.1.2.7 2018/04/03 08:29:44 pgoyette Exp $");
#include <sys/systm.h>
#include <sys/module.h>
@@ -46,6 +46,7 @@ __KERNEL_RCSID(0, "$NetBSD: compat_80_mo
int compat_80_init(void)
{
+ kern_mod_80_init();
raidframe_80_init();
return 0;
@@ -55,6 +56,7 @@ int compat_80_fini(void)
{
raidframe_80_fini();
+ kern_mod_80_fini();
return 0;
}
Index: src/sys/compat/common/compat_mod.h
diff -u src/sys/compat/common/compat_mod.h:1.1.42.17 src/sys/compat/common/compat_mod.h:1.1.42.18
--- src/sys/compat/common/compat_mod.h:1.1.42.17 Sat Mar 31 09:17:35 2018
+++ src/sys/compat/common/compat_mod.h Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: compat_mod.h,v 1.1.42.17 2018/03/31 09:17:35 pgoyette Exp $ */
+/* $NetBSD: compat_mod.h,v 1.1.42.18 2018/04/03 08:29:44 pgoyette Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -42,6 +42,8 @@ void compat_sysctl_vfs(struct sysctllog
#ifdef COMPAT_80
int compat_80_init(void);
int compat_80_fini(void);
+void kern_mod_80_init(void);
+void kern_mod_80_fini(void);
#endif
#ifdef COMPAT_70
Index: src/sys/compat/common/files.common
diff -u src/sys/compat/common/files.common:1.1.2.29 src/sys/compat/common/files.common:1.1.2.30
--- src/sys/compat/common/files.common:1.1.2.29 Sat Mar 31 09:17:35 2018
+++ src/sys/compat/common/files.common Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-# $NetBSD: files.common,v 1.1.2.29 2018/03/31 09:17:35 pgoyette Exp $
+# $NetBSD: files.common,v 1.1.2.30 2018/04/03 08:29:44 pgoyette Exp $
#
# Generic files, used by all compat options.
@@ -96,6 +96,7 @@ file compat/common/uipc_usrreq_70.c com
# Compatability code for NetBSD 8.0
file compat/common/compat_80_mod.c compat_80
+file compat/common/kern_mod_80.c compat_80
#
# Sources for sysv ipc compatibility across the versions.
Index: src/sys/compat/netbsd32/netbsd32_module.c
diff -u src/sys/compat/netbsd32/netbsd32_module.c:1.6 src/sys/compat/netbsd32/netbsd32_module.c:1.6.2.1
--- src/sys/compat/netbsd32/netbsd32_module.c:1.6 Thu Jan 18 13:31:21 2018
+++ src/sys/compat/netbsd32/netbsd32_module.c Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_module.c,v 1.6 2018/01/18 13:31:21 maxv Exp $ */
+/* $NetBSD: netbsd32_module.c,v 1.6.2.1 2018/04/03 08:29:44 pgoyette Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_module.c,v 1.6 2018/01/18 13:31:21 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_module.c,v 1.6.2.1 2018/04/03 08:29:44 pgoyette Exp $");
#include <sys/param.h>
#include <sys/dirent.h>
@@ -42,17 +42,37 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_mod
#include <compat/netbsd32/netbsd32_syscallargs.h>
#include <compat/netbsd32/netbsd32_conv.h>
+#ifdef COMPAT_80
+static void
+copy_oalias(omodstat_t *oms, const char * const *aliasp, modinfo_t *mi,
+ module_t *mod)
+{
+
+ strlcpy(oms->oms_name, *aliasp, sizeof(oms->oms_name));
+ strlcpy(oms->oms_required, mi->mi_name, sizeof(oms->oms_required));
+ oms->oms_class = mi->mi_class;
+ oms->oms_source = mod->mod_source;
+ oms->oms_flags = mod->mod_flags | MODFLG_IS_ALIAS;
+}
+
static int
-modctl32_handle_stat(struct netbsd32_iovec *iov, void *arg)
+modctl32_handle_ostat(int cmd, struct netbsd32_iovec *iov, void *arg)
{
- modstat_t *ms, *mso;
+ omodstat_t *oms, *omso;
modinfo_t *mi;
module_t *mod;
vaddr_t addr;
size_t size;
- size_t mslen;
+ size_t omslen;
+ size_t used;
int error;
+ int omscnt;
bool stataddr;
+ const char * const *aliasp;
+ const char *suffix = "...";
+
+ if (cmd != MODCTL_OSTAT)
+ return EINVAL;
/* If not privileged, don't expose kernel addresses. */
error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
@@ -60,34 +80,229 @@ modctl32_handle_stat(struct netbsd32_iov
stataddr = (error == 0);
kernconfig_lock();
- mslen = (module_count+module_builtinlist+1) * sizeof(modstat_t);
- mso = kmem_zalloc(mslen, KM_SLEEP);
- ms = mso;
+ omscnt = 0;
TAILQ_FOREACH(mod, &module_list, mod_chain) {
+ omscnt++;
mi = mod->mod_info;
- strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name));
+ if ((aliasp = *mi->mi_aliases) != NULL) {
+ while (*aliasp++ != NULL)
+ omscnt++;
+ }
+ }
+ TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
+ omscnt++;
+ mi = mod->mod_info;
+ if ((aliasp = *mi->mi_aliases) != NULL) {
+ while (*aliasp++ != NULL)
+ omscnt++;
+ }
+ }
+ omslen = omscnt * sizeof(omodstat_t);
+ omso = kmem_zalloc(omslen, KM_SLEEP);
+ oms = omso;
+ TAILQ_FOREACH(mod, &module_list, mod_chain) {
+ mi = mod->mod_info;
+ strlcpy(oms->oms_name, mi->mi_name, sizeof(oms->oms_name));
if (mi->mi_required != NULL) {
- strlcpy(ms->ms_required, mi->mi_required,
- sizeof(ms->ms_required));
+ used = strlcpy(oms->oms_required, mi->mi_required,
+ sizeof(oms->oms_required));
+ if (used >= sizeof(oms->oms_required)) {
+ oms->oms_required[sizeof(oms->oms_required) -
+ strlen(suffix) - 1] = '\0';
+ strlcat(oms->oms_required, suffix,
+ sizeof(oms->oms_required));
+ }
}
if (mod->mod_kobj != NULL && stataddr) {
kobj_stat(mod->mod_kobj, &addr, &size);
- ms->ms_addr = addr;
- ms->ms_size = size;
+ oms->oms_addr = addr;
+ oms->oms_size = size;
}
- ms->ms_class = mi->mi_class;
- ms->ms_refcnt = mod->mod_refcnt;
- ms->ms_source = mod->mod_source;
- ms->ms_flags = mod->mod_flags;
+ oms->oms_class = mi->mi_class;
+ oms->oms_refcnt = mod->mod_refcnt;
+ oms->oms_source = mod->mod_source;
+ oms->oms_flags = mod->mod_flags;
+ oms++;
+ aliasp = *mi->mi_aliases;
+ if (aliasp == NULL)
+ continue;
+ while (*aliasp) {
+ copy_oalias(oms, aliasp, mi, mod);
+ aliasp++;
+ oms++;
+ }
+ }
+ TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
+ mi = mod->mod_info;
+ strlcpy(oms->oms_name, mi->mi_name, sizeof(oms->oms_name));
+ if (mi->mi_required != NULL) {
+ used = strlcpy(oms->oms_required, mi->mi_required,
+ sizeof(oms->oms_required));
+ if (used >= sizeof(oms->oms_required)) {
+ oms->oms_required[sizeof(oms->oms_required) -
+ strlen(suffix) - 1] = '\0';
+ strlcat(oms->oms_required, suffix,
+ sizeof(oms->oms_required));
+ }
+ }
+ if (mod->mod_kobj != NULL && stataddr) {
+ kobj_stat(mod->mod_kobj, &addr, &size);
+ oms->oms_addr = addr;
+ oms->oms_size = size;
+ }
+ oms->oms_class = mi->mi_class;
+ oms->oms_refcnt = -1;
+ KASSERT(mod->mod_source == MODULE_SOURCE_KERNEL);
+ oms->oms_source = mod->mod_source;
+ oms++;
+ aliasp = *mi->mi_aliases;
+ if (aliasp == NULL)
+ continue;
+ while (*aliasp) {
+ copy_oalias(oms, aliasp, mi, mod);
+ aliasp++;
+ oms++;
+ }
+ }
+ kernconfig_unlock();
+ error = copyout(omso, NETBSD32PTR64(iov->iov_base),
+ min(omslen - sizeof(modstat_t), iov->iov_len));
+ kmem_free(omso, omslen);
+ if (error == 0) {
+ iov->iov_len = omslen - sizeof(modstat_t);
+ error = copyout(iov, arg, sizeof(*iov));
+ }
+
+ return error;
+}
+#endif /* COMPAT_80 */
+
+static void
+copy_alias(modstat_t *ms, const char * const *aliasp, modinfo_t *mi,
+ module_t *mod)
+{
+
+ strlcpy(ms->ms_name, *aliasp, sizeof(ms->ms_name));
+ ms->ms_class = mi->mi_class;
+ ms->ms_source = mod->mod_source;
+ ms->ms_flags = mod->mod_flags | MODFLG_IS_ALIAS;
+ ms->ms_reqoffset = 0;
+}
+
+static int
+modctl32_handle_stat(struct netbsd32_iovec *iov, void *arg)
+{
+ int ms_cnt;
+ modstat_t *ms, *mso;
+ size_t ms_len;
+ int req_cnt;
+ char *req, *reqo;
+ size_t req_len;
+ char *out_p;
+ size_t out_s;
+
+ modinfo_t *mi;
+ module_t *mod;
+ vaddr_t addr;
+ size_t size;
+ size_t used;
+ int off;
+ int error;
+ bool stataddr;
+ const char * const *aliasp;
+
+ /* If not privileged, don't expose kernel addresses. */
+ error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
+ 0, (void *)(uintptr_t)MODCTL_STAT, NULL, NULL);
+ stataddr = (error == 0);
+
+ kernconfig_lock();
+ ms_cnt = 0;
+ req_len = 1;
+
+ /*
+ * Count up the number of modstat_t needed, and total size of
+ * require_module lists on both active and built-in lists
+ */
+ TAILQ_FOREACH(mod, &module_list, mod_chain) {
+ ms_cnt++;
+ mi = mod->mod_info;
+ if ((aliasp = *mi->mi_aliases) != NULL) {
+ while (*aliasp++ != NULL)
+ ms_cnt++;
+ }
+ if (mi->mi_required != NULL) {
+ req_cnt++;
+ req_len += strlen(mi->mi_required) + 1;
+ }
+ }
+ TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
+ ms_cnt++;
+ mi = mod->mod_info;
+ if ((aliasp = *mi->mi_aliases) != NULL) {
+ while (*aliasp++ != NULL)
+ ms_cnt++;
+ }
+ if (mi->mi_required != NULL) {
+ req_cnt++;
+ req_len += strlen(mi->mi_required) + 1;
+ }
+ }
+
+ /* Allocate internal buffers to hold all the output data */
+ ms_len = ms_cnt * sizeof(modstat_t);
+ ms = kmem_zalloc(ms_len, KM_SLEEP);
+ req = kmem_zalloc(req_len, KM_SLEEP);
+
+ mso = ms;
+ reqo = req++;
+ off = 1;
+
+ /*
+ * Load data into our internal buffers for both active and
+ * build-in module lists
+ */
+ 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) {
+ ms->ms_reqoffset = off;
+ used = strlcpy(req, mi->mi_required, req_len - off);
+ KASSERTMSG(used < req_len - off, "reqlist grew!");
+ off = used + 1;
+ req += used + 1;
+ } else
+ ms->ms_reqoffset = 0;
+ if (mod->mod_kobj != NULL && stataddr) {
+ 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->ms_flags = mod->mod_flags;
+ ms++;
+ aliasp = *mi->mi_aliases;
+ if (aliasp == NULL)
+ continue;
+ while (*aliasp) {
+ copy_alias(ms, aliasp, mi, mod);
+ aliasp++;
ms++;
+ }
}
TAILQ_FOREACH(mod, &module_builtins, 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));
- }
+ ms->ms_reqoffset = off;
+ used = strlcpy(req, mi->mi_required, req_len - off);
+ KASSERTMSG(used < req_len - off, "reqlist grew!");
+ off += used + 1;
+ req += used + 1;
+ } else
+ ms->ms_reqoffset = 0;
if (mod->mod_kobj != NULL && stataddr) {
kobj_stat(mod->mod_kobj, &addr, &size);
ms->ms_addr = addr;
@@ -98,19 +313,58 @@ modctl32_handle_stat(struct netbsd32_iov
KASSERT(mod->mod_source == MODULE_SOURCE_KERNEL);
ms->ms_source = mod->mod_source;
ms++;
+ aliasp = *mi->mi_aliases;
+ if (aliasp == NULL)
+ continue;
+ while (*aliasp) {
+ copy_alias(ms, aliasp, mi, mod);
+ aliasp++;
+ ms++;
+ }
}
kernconfig_unlock();
- error = copyout(mso, NETBSD32PTR64(iov->iov_base),
- min(mslen - sizeof(modstat_t), iov->iov_len));
- kmem_free(mso, mslen);
+
+ /*
+ * Now copyout our internal buffers back to userland
+ */
+ out_p = NETBSD32PTR64(iov->iov_base);
+ out_s = iov->iov_len;
+ size = sizeof(ms_cnt);
+
+ /* Copy out the count of modstat_t */
+ if (out_s) {
+ size = min(sizeof(ms_cnt), out_s);
+ error = copyout(&ms_cnt, out_p, size);
+ out_p += size;
+ out_s -= size;
+ }
+ /* Copy out the modstat_t array */
+ if (out_s && error == 0) {
+ size = min(ms_len, out_s);
+ error = copyout(mso, out_p, size);
+ out_p += size;
+ out_s -= size;
+ }
+ /* Copy out the "required" strings */
+ if (out_s && error == 0) {
+ size = min(req_len, out_s);
+ error = copyout(reqo, out_p, size);
+ out_p += size;
+ out_s -= size;
+ }
+ kmem_free(mso, ms_len);
+ kmem_free(reqo, req_len);
+
+ /* Finally, update the userland copy of the iovec's length */
if (error == 0) {
- iov->iov_len = mslen - sizeof(modstat_t);
+ iov->iov_len = ms_len + req_len + sizeof(ms_cnt);
error = copyout(iov, arg, sizeof(*iov));
}
return error;
}
+
int
netbsd32_modctl(struct lwp *lwp, const struct netbsd32_modctl_args *uap,
register_t *result)
@@ -146,6 +400,16 @@ netbsd32_modctl(struct lwp *lwp, const s
}
break;
+#ifdef COMPAT_80
+ case MODCTL_OSTAT:
+ error = copyin(arg, &iov, sizeof(iov));
+ if (error != 0) {
+ break;
+ }
+ error = modctl32_handle_ostat(SCARG(uap, cmd), &iov, arg);
+ break;
+#endif
+
case MODCTL_STAT:
error = copyin(arg, &iov, sizeof(iov));
if (error != 0) {
Index: src/sys/kern/compat_stub.c
diff -u src/sys/kern/compat_stub.c:1.1.2.13 src/sys/kern/compat_stub.c:1.1.2.14
--- src/sys/kern/compat_stub.c:1.1.2.13 Fri Mar 30 10:09:08 2018
+++ src/sys/kern/compat_stub.c Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: compat_stub.c,v 1.1.2.13 2018/03/30 10:09:08 pgoyette Exp $ */
+/* $NetBSD: compat_stub.c,v 1.1.2.14 2018/04/03 08:29:44 pgoyette Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -148,3 +148,8 @@ int (*if43_20_cvtcmd)(int) = (void *)eno
void (*rtsock14_oifmsg)(struct ifnet *) = (void *)voidop;
int (*rtsock14_iflist)(struct ifnet *, struct rt_walkarg *,
struct rt_addrinfo *, size_t) = (void *)enosys;
+
+/*
+ * modctl handler for old style OSTAT
+ */
+int (*compat_modstat_80)(int, struct iovec *, void *) = (void *)enosys;
Index: src/sys/kern/sys_module.c
diff -u src/sys/kern/sys_module.c:1.23.2.5 src/sys/kern/sys_module.c:1.23.2.6
--- src/sys/kern/sys_module.c:1.23.2.5 Sun Apr 1 23:06:11 2018
+++ src/sys/kern/sys_module.c Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_module.c,v 1.23.2.5 2018/04/01 23:06:11 pgoyette Exp $ */
+/* $NetBSD: sys_module.c,v 1.23.2.6 2018/04/03 08:29:44 pgoyette Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_module.c,v 1.23.2.5 2018/04/01 23:06:11 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_module.c,v 1.23.2.6 2018/04/03 08:29:44 pgoyette Exp $");
#ifdef _KERNEL_OPT
#include "opt_modular.h"
@@ -47,6 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: sys_module.c
#include <sys/module.h>
#include <sys/syscall.h>
#include <sys/syscallargs.h>
+#include <sys/compat_stub.h>
/*
* Arbitrary limit to avoid DoS for excessive memory allocation.
@@ -116,27 +117,33 @@ copy_alias(modstat_t *ms, const char * c
{
strlcpy(ms->ms_name, *aliasp, sizeof(ms->ms_name));
- strlcpy(ms->ms_required, mi->mi_name, sizeof(ms->ms_required));
ms->ms_class = mi->mi_class;
ms->ms_source = mod->mod_source;
ms->ms_flags = mod->mod_flags | MODFLG_IS_ALIAS;
+ ms->ms_reqoffset = 0;
}
static int
handle_modctl_stat(struct iovec *iov, void *arg)
{
+ int ms_cnt;
modstat_t *ms, *mso;
+ size_t ms_len;
+ int req_cnt;
+ char *req, *reqo;
+ size_t req_len;
+ char *out_p;
+ size_t out_s;
+
modinfo_t *mi;
module_t *mod;
vaddr_t addr;
size_t size;
- size_t mslen;
size_t used;
+ int off;
int error;
- int mscnt;
bool stataddr;
const char * const *aliasp;
- const char *suffix = "...";
/* If not privileged, don't expose kernel addresses. */
error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
@@ -144,31 +151,62 @@ handle_modctl_stat(struct iovec *iov, vo
stataddr = (error == 0);
kernconfig_lock();
- mscnt = 0;
+ ms_cnt = 0;
+ req_len = 1;
+
+ /*
+ * Count up the number of modstat_t needed, and total size of
+ * require_module lists on both active and built-in lists
+ */
TAILQ_FOREACH(mod, &module_list, mod_chain) {
- mscnt++;
+ ms_cnt++;
mi = mod->mod_info;
if ((aliasp = *mi->mi_aliases) != NULL) {
while (*aliasp++ != NULL)
- mslen++;
+ ms_cnt++;
+ }
+ if (mi->mi_required != NULL) {
+ req_cnt++;
+ req_len += strlen(mi->mi_required) + 1;
+ }
+ }
+ TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
+ ms_cnt++;
+ mi = mod->mod_info;
+ if ((aliasp = *mi->mi_aliases) != NULL) {
+ while (*aliasp++ != NULL)
+ ms_cnt++;
+ }
+ if (mi->mi_required != NULL) {
+ req_cnt++;
+ req_len += strlen(mi->mi_required) + 1;
}
}
- mslen = (mscnt+module_builtinlist+1) * sizeof(modstat_t);
- mso = kmem_zalloc(mslen, KM_SLEEP);
- ms = mso;
+
+ /* Allocate internal buffers to hold all the output data */
+ ms_len = ms_cnt * sizeof(modstat_t);
+ ms = kmem_zalloc(ms_len, KM_SLEEP);
+ req = kmem_zalloc(req_len, KM_SLEEP);
+
+ mso = ms;
+ reqo = req++;
+ off = 1;
+
+ /*
+ * Load data into our internal buffers for both active and
+ * build-in module lists
+ */
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) {
- used = strlcpy(ms->ms_required, mi->mi_required,
- sizeof(ms->ms_required));
- if (used >= sizeof(ms->ms_required)) {
- ms->ms_required[sizeof(ms->ms_required) -
- strlen(suffix) - 1] = '\0';
- strlcat(ms->ms_required, suffix,
- sizeof(ms->ms_required));
- }
- }
+ ms->ms_reqoffset = off;
+ used = strlcpy(req, mi->mi_required, req_len - off);
+ KASSERTMSG(used < req_len - off, "reqlist grew!");
+ off += used + 1;
+ req += used + 1;
+ } else
+ ms->ms_reqoffset = 0;
if (mod->mod_kobj != NULL && stataddr) {
kobj_stat(mod->mod_kobj, &addr, &size);
ms->ms_addr = addr;
@@ -192,13 +230,13 @@ handle_modctl_stat(struct iovec *iov, vo
mi = mod->mod_info;
strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name));
if (mi->mi_required != NULL) {
- *ms->ms_required = '\0';
- used = strlcat(ms->ms_required, mi->mi_required,
- sizeof(ms->ms_required) - 6);
- if (used > sizeof(ms->ms_required) - 6)
- strlcat(ms->ms_required, ", ...",
- sizeof(ms->ms_required));
- }
+ ms->ms_reqoffset = off;
+ used = strlcpy(req, mi->mi_required, req_len - off);
+ KASSERTMSG(used < req_len - off, "reqlist grew!");
+ off += used + 1;
+ req += used + 1;
+ } else
+ ms->ms_reqoffset = 0;
if (mod->mod_kobj != NULL && stataddr) {
kobj_stat(mod->mod_kobj, &addr, &size);
ms->ms_addr = addr;
@@ -219,11 +257,41 @@ handle_modctl_stat(struct iovec *iov, vo
}
}
kernconfig_unlock();
- error = copyout(mso, iov->iov_base,
- min(mslen - sizeof(modstat_t), iov->iov_len));
- kmem_free(mso, mslen);
+
+ /*
+ * Now copyout our internal buffers back to userland
+ */
+ out_p = iov->iov_base;
+ out_s = iov->iov_len;
+ size = sizeof(ms_cnt);
+
+ /* Copy out the count of modstat_t */
+ if (out_s) {
+ size = min(sizeof(ms_cnt), out_s);
+ error = copyout(&ms_cnt, out_p, size);
+ out_p += size;
+ out_s -= size;
+ }
+ /* Copy out the modstat_t array */
+ if (out_s && error == 0) {
+ size = min(ms_len, out_s);
+ error = copyout(mso, out_p, size);
+ out_p += size;
+ out_s -= size;
+ }
+ /* Copy out the "required" strings */
+ if (out_s && error == 0) {
+ size = min(req_len, out_s);
+ error = copyout(reqo, out_p, size);
+ out_p += size;
+ out_s -= size;
+ }
+ kmem_free(mso, ms_len);
+ kmem_free(reqo, req_len);
+
+ /* Finally, update the userland copy of the iovec's length */
if (error == 0) {
- iov->iov_len = mslen - sizeof(modstat_t);
+ iov->iov_len = ms_len + req_len + sizeof(ms_cnt);
error = copyout(iov, arg, sizeof(*iov));
}
@@ -286,7 +354,6 @@ sys_modctl(struct lwp *l, const struct s
(void *)(uintptr_t)MODCTL_LOAD,
(void *)loadtype, NULL);
break;
-
default:
error = EINVAL;
break;
@@ -295,7 +362,9 @@ sys_modctl(struct lwp *l, const struct s
break;
default:
- error = EINVAL;
+ error = (*compat_modstat_80)(SCARG(uap, cmd), &iov, arg);
+ if (error == ENOSYS)
+ error = EINVAL;
break;
}
Index: src/sys/modules/compat_80/Makefile
diff -u src/sys/modules/compat_80/Makefile:1.1.2.2 src/sys/modules/compat_80/Makefile:1.1.2.3
--- src/sys/modules/compat_80/Makefile:1.1.2.2 Sat Mar 24 01:59:16 2018
+++ src/sys/modules/compat_80/Makefile Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.1.2.2 2018/03/24 01:59:16 pgoyette Exp $
+# $NetBSD: Makefile,v 1.1.2.3 2018/04/03 08:29:44 pgoyette Exp $
.include "../Makefile.inc"
@@ -9,6 +9,7 @@ KMOD= compat_80
CPPFLAGS+= -DCOMPAT_80
SRCS+= compat_80_mod.c
+SRCS+= kern_mod_80.c
.PATH: ${S}/dev/raidframe
Index: src/sys/sys/compat_stub.h
diff -u src/sys/sys/compat_stub.h:1.1.2.13 src/sys/sys/compat_stub.h:1.1.2.14
--- src/sys/sys/compat_stub.h:1.1.2.13 Fri Mar 30 10:09:08 2018
+++ src/sys/sys/compat_stub.h Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: compat_stub.h,v 1.1.2.13 2018/03/30 10:09:08 pgoyette Exp $ */
+/* $NetBSD: compat_stub.h,v 1.1.2.14 2018/04/03 08:29:44 pgoyette Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -171,4 +171,10 @@ extern void (*rtsock14_oifmsg)(struct if
extern int (*rtsock14_iflist)(struct ifnet *, struct rt_walkarg *,
struct rt_addrinfo *, size_t);
+/*
+ * modctl handler for old style OSTAT
+ */
+struct iovec;
+
+extern int (*compat_modstat_80)(int, struct iovec *, void *);
#endif /* _SYS_COMPAT_STUB_H */
Index: src/sys/sys/module.h
diff -u src/sys/sys/module.h:1.41.14.7 src/sys/sys/module.h:1.41.14.8
--- src/sys/sys/module.h:1.41.14.7 Sun Apr 1 23:06:11 2018
+++ src/sys/sys/module.h Tue Apr 3 08:29:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: module.h,v 1.41.14.7 2018/04/01 23:06:11 pgoyette Exp $ */
+/* $NetBSD: module.h,v 1.41.14.8 2018/04/03 08:29:44 pgoyette Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -240,24 +240,41 @@ typedef struct modctl_load {
typedef enum modctl {
MODCTL_LOAD, /* modctl_load_t *ml */
MODCTL_UNLOAD, /* char *name */
- MODCTL_STAT, /* struct iovec *buffer */
- MODCTL_EXISTS /* enum: 0: load, 1: autoload */
+ MODCTL_OSTAT, /* struct iovec *buffer */
+ MODCTL_EXISTS, /* enum: 0: load, 1: autoload */
+ MODCTL_STAT /* struct iovec *buffer */
} modctl_t;
/*
* This structure intentionally has the same layout for 32 and 64
* bit builds.
*/
+typedef struct omodstat {
+ char oms_name[MAXMODNAME];
+ char oms_required[MAXMODNAME * MAXMODDEPS];
+ uint64_t oms_addr;
+ modsrc_t oms_source;
+ modclass_t oms_class;
+ u_int oms_size;
+ u_int oms_refcnt;
+ u_int oms_flags;
+ u_int oms_reserved[3];
+} omodstat_t;
+
+/*
+ * This structure is used with the newer version of MODCTL_STAT, which
+ * exports strings of arbitrary length for the list of required modules.
+ */
typedef struct modstat {
char ms_name[MAXMODNAME];
- char ms_required[MAXMODNAME * MAXMODDEPS];
uint64_t ms_addr;
modsrc_t ms_source;
modclass_t ms_class;
u_int ms_size;
u_int ms_refcnt;
u_int ms_flags;
- u_int ms_reserved[3];
+ u_int ms_reqoffset; /* offset to module's required list
+ from beginning of iovec buffer! */
} modstat_t;
int modctl(int, void *);
Added files:
Index: src/sys/compat/common/kern_mod_80.c
diff -u /dev/null src/sys/compat/common/kern_mod_80.c:1.1.2.1
--- /dev/null Tue Apr 3 08:29:44 2018
+++ src/sys/compat/common/kern_mod_80.c Tue Apr 3 08:29:44 2018
@@ -0,0 +1,203 @@
+/* $NetBSD: kern_mod_80.c,v 1.1.2.1 2018/04/03 08:29:44 pgoyette 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.
+ *
+ * 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: kern_mod_80.c,v 1.1.2.1 2018/04/03 08:29:44 pgoyette Exp $");
+
+#ifdef _KERNEL_OPT
+#include "opt_modular.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/namei.h>
+#include <sys/kauth.h>
+#include <sys/kmem.h>
+#include <sys/kobj.h>
+#include <sys/module.h>
+#include <sys/syscall.h>
+#include <sys/syscallargs.h>
+#include <sys/compat_stub.h>
+
+#include <compat/common/compat_mod.h>
+
+static void
+copy_oalias(omodstat_t *oms, const char * const *aliasp, modinfo_t *mi,
+ module_t *mod)
+{
+
+ strlcpy(oms->oms_name, *aliasp, sizeof(oms->oms_name));
+ strlcpy(oms->oms_required, mi->mi_name, sizeof(oms->oms_required));
+ oms->oms_class = mi->mi_class;
+ oms->oms_source = mod->mod_source;
+ oms->oms_flags = mod->mod_flags | MODFLG_IS_ALIAS;
+}
+
+static int
+compat_80_modstat(int cmd, struct iovec *iov, void *arg)
+{
+ omodstat_t *oms, *omso;
+ modinfo_t *mi;
+ module_t *mod;
+ vaddr_t addr;
+ size_t size;
+ size_t omslen;
+ size_t used;
+ int error;
+ int omscnt;
+ bool stataddr;
+ const char * const *aliasp;
+ const char *suffix = "...";
+
+ if (cmd != MODCTL_OSTAT)
+ return EINVAL;
+
+ error = copyin(arg, iov, sizeof(*iov));
+ if (error != 0) {
+ return error;
+ }
+
+ /* If not privileged, don't expose kernel addresses. */
+ error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
+ 0, (void *)(uintptr_t)MODCTL_STAT, NULL, NULL);
+ stataddr = (error == 0);
+
+ kernconfig_lock();
+ omscnt = 0;
+ TAILQ_FOREACH(mod, &module_list, mod_chain) {
+ omscnt++;
+ mi = mod->mod_info;
+ if ((aliasp = *mi->mi_aliases) != NULL) {
+ while (*aliasp++ != NULL)
+ omscnt++;
+ }
+ }
+ TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
+ omscnt++;
+ mi = mod->mod_info;
+ if ((aliasp = *mi->mi_aliases) != NULL) {
+ while (*aliasp++ != NULL)
+ omscnt++;
+ }
+ }
+ omslen = omscnt * sizeof(omodstat_t);
+ omso = kmem_zalloc(omslen, KM_SLEEP);
+ oms = omso;
+ TAILQ_FOREACH(mod, &module_list, mod_chain) {
+ mi = mod->mod_info;
+ strlcpy(oms->oms_name, mi->mi_name, sizeof(oms->oms_name));
+ if (mi->mi_required != NULL) {
+ used = strlcpy(oms->oms_required, mi->mi_required,
+ sizeof(oms->oms_required));
+ if (used >= sizeof(oms->oms_required)) {
+ oms->oms_required[sizeof(oms->oms_required) -
+ strlen(suffix) - 1] = '\0';
+ strlcat(oms->oms_required, suffix,
+ sizeof(oms->oms_required));
+ }
+ }
+ if (mod->mod_kobj != NULL && stataddr) {
+ kobj_stat(mod->mod_kobj, &addr, &size);
+ oms->oms_addr = addr;
+ oms->oms_size = size;
+ }
+ oms->oms_class = mi->mi_class;
+ oms->oms_refcnt = mod->mod_refcnt;
+ oms->oms_source = mod->mod_source;
+ oms->oms_flags = mod->mod_flags;
+ oms++;
+ aliasp = *mi->mi_aliases;
+ if (aliasp == NULL)
+ continue;
+ while (*aliasp) {
+ copy_oalias(oms, aliasp, mi, mod);
+ aliasp++;
+ oms++;
+ }
+ }
+ TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
+ mi = mod->mod_info;
+ strlcpy(oms->oms_name, mi->mi_name, sizeof(oms->oms_name));
+ if (mi->mi_required != NULL) {
+ used = strlcpy(oms->oms_required, mi->mi_required,
+ sizeof(oms->oms_required));
+ if (used >= sizeof(oms->oms_required)) {
+ oms->oms_required[sizeof(oms->oms_required) -
+ strlen(suffix) - 1] = '\0';
+ strlcat(oms->oms_required, suffix,
+ sizeof(oms->oms_required));
+ }
+ }
+ if (mod->mod_kobj != NULL && stataddr) {
+ kobj_stat(mod->mod_kobj, &addr, &size);
+ oms->oms_addr = addr;
+ oms->oms_size = size;
+ }
+ oms->oms_class = mi->mi_class;
+ oms->oms_refcnt = -1;
+ KASSERT(mod->mod_source == MODULE_SOURCE_KERNEL);
+ oms->oms_source = mod->mod_source;
+ oms++;
+ aliasp = *mi->mi_aliases;
+ if (aliasp == NULL)
+ continue;
+ while (*aliasp) {
+ copy_oalias(oms, aliasp, mi, mod);
+ aliasp++;
+ oms++;
+ }
+ }
+ kernconfig_unlock();
+ error = copyout(omso, iov->iov_base, min(omslen, iov->iov_len));
+ kmem_free(omso, omslen);
+ if (error == 0) {
+ iov->iov_len = omslen;
+ error = copyout(iov, arg, sizeof(*iov));
+ }
+
+ return error;
+}
+
+void
+kern_mod_80_init(void)
+{
+
+ compat_modstat_80 = compat_80_modstat;
+}
+
+void
+kern_mod_80_fini(void)
+{
+
+ compat_modstat_80 = (void *)enosys;
+}