Sun Mar 11 08:32:21 2018 UTC ()
Since we use pointer semantics when walking the alias lists, declare
the pointer variable accordingly.


(pgoyette)
diff -r1.130.2.2 -r1.130.2.3 src/sys/kern/kern_module.c
diff -r1.23.2.2 -r1.23.2.3 src/sys/kern/sys_module.c

cvs diff -r1.130.2.2 -r1.130.2.3 src/sys/kern/kern_module.c (switch to unified diff)

--- src/sys/kern/kern_module.c 2018/03/11 07:25:59 1.130.2.2
+++ src/sys/kern/kern_module.c 2018/03/11 08:32:21 1.130.2.3
@@ -1,1611 +1,1611 @@ @@ -1,1611 +1,1611 @@
1/* $NetBSD: kern_module.c,v 1.130.2.2 2018/03/11 07:25:59 pgoyette Exp $ */ 1/* $NetBSD: kern_module.c,v 1.130.2.3 2018/03/11 08:32:21 pgoyette Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software developed for The NetBSD Foundation 7 * This code is derived from software developed for The NetBSD Foundation
8 * by Andrew Doran. 8 * by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Kernel module support. 33 * Kernel module support.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.130.2.2 2018/03/11 07:25:59 pgoyette Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.130.2.3 2018/03/11 08:32:21 pgoyette Exp $");
38 38
39#define _MODULE_INTERNAL 39#define _MODULE_INTERNAL
40 40
41#ifdef _KERNEL_OPT 41#ifdef _KERNEL_OPT
42#include "opt_ddb.h" 42#include "opt_ddb.h"
43#include "opt_modular.h" 43#include "opt_modular.h"
44#endif 44#endif
45 45
46#include <sys/param.h> 46#include <sys/param.h>
47#include <sys/systm.h> 47#include <sys/systm.h>
48#include <sys/kernel.h> 48#include <sys/kernel.h>
49#include <sys/proc.h> 49#include <sys/proc.h>
50#include <sys/kauth.h> 50#include <sys/kauth.h>
51#include <sys/kobj.h> 51#include <sys/kobj.h>
52#include <sys/kmem.h> 52#include <sys/kmem.h>
53#include <sys/module.h> 53#include <sys/module.h>
54#include <sys/kthread.h> 54#include <sys/kthread.h>
55#include <sys/sysctl.h> 55#include <sys/sysctl.h>
56#include <sys/lock.h> 56#include <sys/lock.h>
57 57
58#include <uvm/uvm_extern.h> 58#include <uvm/uvm_extern.h>
59 59
60struct vm_map *module_map; 60struct vm_map *module_map;
61const char *module_machine; 61const char *module_machine;
62char module_base[MODULE_BASE_SIZE]; 62char module_base[MODULE_BASE_SIZE];
63 63
64struct modlist module_list = TAILQ_HEAD_INITIALIZER(module_list); 64struct modlist module_list = TAILQ_HEAD_INITIALIZER(module_list);
65struct modlist module_builtins = TAILQ_HEAD_INITIALIZER(module_builtins); 65struct modlist module_builtins = TAILQ_HEAD_INITIALIZER(module_builtins);
66static struct modlist module_bootlist = TAILQ_HEAD_INITIALIZER(module_bootlist); 66static struct modlist module_bootlist = TAILQ_HEAD_INITIALIZER(module_bootlist);
67 67
68static module_t *module_active; 68static module_t *module_active;
69bool module_verbose_on; 69bool module_verbose_on;
70#ifdef MODULAR_DEFAULT_AUTOLOAD 70#ifdef MODULAR_DEFAULT_AUTOLOAD
71bool module_autoload_on = true; 71bool module_autoload_on = true;
72#else 72#else
73bool module_autoload_on = false; 73bool module_autoload_on = false;
74#endif 74#endif
75u_int module_count; 75u_int module_count;
76u_int module_builtinlist; 76u_int module_builtinlist;
77u_int module_autotime = 10; 77u_int module_autotime = 10;
78u_int module_gen = 1; 78u_int module_gen = 1;
79static kcondvar_t module_thread_cv; 79static kcondvar_t module_thread_cv;
80static kmutex_t module_thread_lock; 80static kmutex_t module_thread_lock;
81static int module_thread_ticks; 81static int module_thread_ticks;
82int (*module_load_vfs_vec)(const char *, int, bool, module_t *, 82int (*module_load_vfs_vec)(const char *, int, bool, module_t *,
83 prop_dictionary_t *) = (void *)eopnotsupp; 83 prop_dictionary_t *) = (void *)eopnotsupp;
84 84
85static kauth_listener_t module_listener; 85static kauth_listener_t module_listener;
86 86
87/* Ensure that the kernel's link set isn't empty. */ 87/* Ensure that the kernel's link set isn't empty. */
88static modinfo_t module_dummy; 88static modinfo_t module_dummy;
89__link_set_add_rodata(modules, module_dummy); 89__link_set_add_rodata(modules, module_dummy);
90 90
91static module_t *module_newmodule(modsrc_t); 91static module_t *module_newmodule(modsrc_t);
92static void module_require_force(module_t *); 92static void module_require_force(module_t *);
93static int module_do_load(const char *, bool, int, prop_dictionary_t, 93static int module_do_load(const char *, bool, int, prop_dictionary_t,
94 module_t **, modclass_t modclass, bool); 94 module_t **, modclass_t modclass, bool);
95static int module_do_unload(const char *, bool); 95static int module_do_unload(const char *, bool);
96static int module_do_builtin(const module_t *, const char *, module_t **, 96static int module_do_builtin(const module_t *, const char *, module_t **,
97 prop_dictionary_t); 97 prop_dictionary_t);
98static int module_fetch_info(module_t *); 98static int module_fetch_info(module_t *);
99static void module_thread(void *); 99static void module_thread(void *);
100 100
101static module_t *module_lookup(const char *); 101static module_t *module_lookup(const char *);
102int module_alias_lookup(const char *, module_t *); 102int module_alias_lookup(const char *, module_t *);
103static void module_enqueue(module_t *); 103static void module_enqueue(module_t *);
104 104
105static bool module_merge_dicts(prop_dictionary_t, const prop_dictionary_t); 105static bool module_merge_dicts(prop_dictionary_t, const prop_dictionary_t);
106 106
107static void sysctl_module_setup(void); 107static void sysctl_module_setup(void);
108static int sysctl_module_autotime(SYSCTLFN_PROTO); 108static int sysctl_module_autotime(SYSCTLFN_PROTO);
109 109
110#define MODULE_CLASS_MATCH(mi, modclass) \ 110#define MODULE_CLASS_MATCH(mi, modclass) \
111 ((modclass) == MODULE_CLASS_ANY || (modclass) == (mi)->mi_class) 111 ((modclass) == MODULE_CLASS_ANY || (modclass) == (mi)->mi_class)
112 112
113static void 113static void
114module_incompat(const modinfo_t *mi, int modclass) 114module_incompat(const modinfo_t *mi, int modclass)
115{ 115{
116 module_error("incompatible module class for `%s' (%d != %d)", 116 module_error("incompatible module class for `%s' (%d != %d)",
117 mi->mi_name, modclass, mi->mi_class); 117 mi->mi_name, modclass, mi->mi_class);
118} 118}
119 119
120/* 120/*
121 * module_error: 121 * module_error:
122 * 122 *
123 * Utility function: log an error. 123 * Utility function: log an error.
124 */ 124 */
125void 125void
126module_error(const char *fmt, ...) 126module_error(const char *fmt, ...)
127{ 127{
128 va_list ap; 128 va_list ap;
129 129
130 va_start(ap, fmt); 130 va_start(ap, fmt);
131 printf("WARNING: module error: "); 131 printf("WARNING: module error: ");
132 vprintf(fmt, ap); 132 vprintf(fmt, ap);
133 printf("\n"); 133 printf("\n");
134 va_end(ap); 134 va_end(ap);
135} 135}
136 136
137/* 137/*
138 * module_print: 138 * module_print:
139 * 139 *
140 * Utility function: log verbose output. 140 * Utility function: log verbose output.
141 */ 141 */
142void 142void
143module_print(const char *fmt, ...) 143module_print(const char *fmt, ...)
144{ 144{
145 va_list ap; 145 va_list ap;
146 146
147 if (module_verbose_on) { 147 if (module_verbose_on) {
148 va_start(ap, fmt); 148 va_start(ap, fmt);
149 printf("DEBUG: module: "); 149 printf("DEBUG: module: ");
150 vprintf(fmt, ap); 150 vprintf(fmt, ap);
151 printf("\n"); 151 printf("\n");
152 va_end(ap); 152 va_end(ap);
153 } 153 }
154} 154}
155 155
156static int 156static int
157module_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 157module_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
158 void *arg0, void *arg1, void *arg2, void *arg3) 158 void *arg0, void *arg1, void *arg2, void *arg3)
159{ 159{
160 int result; 160 int result;
161 161
162 result = KAUTH_RESULT_DEFER; 162 result = KAUTH_RESULT_DEFER;
163 163
164 if (action != KAUTH_SYSTEM_MODULE) 164 if (action != KAUTH_SYSTEM_MODULE)
165 return result; 165 return result;
166 166
167 if ((uintptr_t)arg2 != 0) /* autoload */ 167 if ((uintptr_t)arg2 != 0) /* autoload */
168 result = KAUTH_RESULT_ALLOW; 168 result = KAUTH_RESULT_ALLOW;
169 169
170 return result; 170 return result;
171} 171}
172 172
173/* 173/*
174 * Allocate a new module_t 174 * Allocate a new module_t
175 */ 175 */
176static module_t * 176static module_t *
177module_newmodule(modsrc_t source) 177module_newmodule(modsrc_t source)
178{ 178{
179 module_t *mod; 179 module_t *mod;
180 180
181 mod = kmem_zalloc(sizeof(*mod), KM_SLEEP); 181 mod = kmem_zalloc(sizeof(*mod), KM_SLEEP);
182 mod->mod_source = source; 182 mod->mod_source = source;
183 mod->mod_info = NULL; 183 mod->mod_info = NULL;
184 mod->mod_flags = 0; 184 mod->mod_flags = 0;
185 return mod; 185 return mod;
186} 186}
187 187
188/* 188/*
189 * Require the -f (force) flag to load a module 189 * Require the -f (force) flag to load a module
190 */ 190 */
191static void 191static void
192module_require_force(struct module *mod) 192module_require_force(struct module *mod)
193{ 193{
194 mod->mod_flags |= MODFLG_MUST_FORCE; 194 mod->mod_flags |= MODFLG_MUST_FORCE;
195} 195}
196 196
197/* 197/*
198 * Add modules to the builtin list. This can done at boottime or 198 * Add modules to the builtin list. This can done at boottime or
199 * at runtime if the module is linked into the kernel with an 199 * at runtime if the module is linked into the kernel with an
200 * external linker. All or none of the input will be handled. 200 * external linker. All or none of the input will be handled.
201 * Optionally, the modules can be initialized. If they are not 201 * Optionally, the modules can be initialized. If they are not
202 * initialized, module_init_class() or module_load() can be used 202 * initialized, module_init_class() or module_load() can be used
203 * later, but these are not guaranteed to give atomic results. 203 * later, but these are not guaranteed to give atomic results.
204 */ 204 */
205int 205int
206module_builtin_add(modinfo_t *const *mip, size_t nmodinfo, bool init) 206module_builtin_add(modinfo_t *const *mip, size_t nmodinfo, bool init)
207{ 207{
208 struct module **modp = NULL, *mod_iter; 208 struct module **modp = NULL, *mod_iter;
209 int rv = 0, i, mipskip; 209 int rv = 0, i, mipskip;
210 210
211 if (init) { 211 if (init) {
212 rv = kauth_authorize_system(kauth_cred_get(), 212 rv = kauth_authorize_system(kauth_cred_get(),
213 KAUTH_SYSTEM_MODULE, 0, (void *)(uintptr_t)MODCTL_LOAD, 213 KAUTH_SYSTEM_MODULE, 0, (void *)(uintptr_t)MODCTL_LOAD,
214 (void *)(uintptr_t)1, NULL); 214 (void *)(uintptr_t)1, NULL);
215 if (rv) { 215 if (rv) {
216 return rv; 216 return rv;
217 } 217 }
218 } 218 }
219 219
220 for (i = 0, mipskip = 0; i < nmodinfo; i++) { 220 for (i = 0, mipskip = 0; i < nmodinfo; i++) {
221 if (mip[i] == &module_dummy) { 221 if (mip[i] == &module_dummy) {
222 KASSERT(nmodinfo > 0); 222 KASSERT(nmodinfo > 0);
223 nmodinfo--; 223 nmodinfo--;
224 } 224 }
225 } 225 }
226 if (nmodinfo == 0) 226 if (nmodinfo == 0)
227 return 0; 227 return 0;
228 228
229 modp = kmem_zalloc(sizeof(*modp) * nmodinfo, KM_SLEEP); 229 modp = kmem_zalloc(sizeof(*modp) * nmodinfo, KM_SLEEP);
230 for (i = 0, mipskip = 0; i < nmodinfo; i++) { 230 for (i = 0, mipskip = 0; i < nmodinfo; i++) {
231 if (mip[i+mipskip] == &module_dummy) { 231 if (mip[i+mipskip] == &module_dummy) {
232 mipskip++; 232 mipskip++;
233 continue; 233 continue;
234 } 234 }
235 modp[i] = module_newmodule(MODULE_SOURCE_KERNEL); 235 modp[i] = module_newmodule(MODULE_SOURCE_KERNEL);
236 modp[i]->mod_info = mip[i+mipskip]; 236 modp[i]->mod_info = mip[i+mipskip];
237 } 237 }
238 kernconfig_lock(); 238 kernconfig_lock();
239 239
240 /* do this in three stages for error recovery and atomicity */ 240 /* do this in three stages for error recovery and atomicity */
241 241
242 /* first check for presence */ 242 /* first check for presence */
243 for (i = 0; i < nmodinfo; i++) { 243 for (i = 0; i < nmodinfo; i++) {
244 TAILQ_FOREACH(mod_iter, &module_builtins, mod_chain) { 244 TAILQ_FOREACH(mod_iter, &module_builtins, mod_chain) {
245 if (strcmp(mod_iter->mod_info->mi_name, 245 if (strcmp(mod_iter->mod_info->mi_name,
246 modp[i]->mod_info->mi_name) == 0) 246 modp[i]->mod_info->mi_name) == 0)
247 break; 247 break;
248 } 248 }
249 if (mod_iter) { 249 if (mod_iter) {
250 rv = EEXIST; 250 rv = EEXIST;
251 goto out; 251 goto out;
252 } 252 }
253 253
254 if (module_lookup(modp[i]->mod_info->mi_name) != NULL) { 254 if (module_lookup(modp[i]->mod_info->mi_name) != NULL) {
255 rv = EEXIST; 255 rv = EEXIST;
256 goto out; 256 goto out;
257 } 257 }
258 } 258 }
259 259
260 /* then add to list */ 260 /* then add to list */
261 for (i = 0; i < nmodinfo; i++) { 261 for (i = 0; i < nmodinfo; i++) {
262 TAILQ_INSERT_TAIL(&module_builtins, modp[i], mod_chain); 262 TAILQ_INSERT_TAIL(&module_builtins, modp[i], mod_chain);
263 module_builtinlist++; 263 module_builtinlist++;
264 } 264 }
265 265
266 /* finally, init (if required) */ 266 /* finally, init (if required) */
267 if (init) { 267 if (init) {
268 for (i = 0; i < nmodinfo; i++) { 268 for (i = 0; i < nmodinfo; i++) {
269 rv = module_do_builtin(modp[i], 269 rv = module_do_builtin(modp[i],
270 modp[i]->mod_info->mi_name, NULL, NULL); 270 modp[i]->mod_info->mi_name, NULL, NULL);
271 /* throw in the towel, recovery hard & not worth it */ 271 /* throw in the towel, recovery hard & not worth it */
272 if (rv) 272 if (rv)
273 panic("%s: builtin module \"%s\" init failed:" 273 panic("%s: builtin module \"%s\" init failed:"
274 " %d", __func__, 274 " %d", __func__,
275 modp[i]->mod_info->mi_name, rv); 275 modp[i]->mod_info->mi_name, rv);
276 } 276 }
277 } 277 }
278 278
279 out: 279 out:
280 kernconfig_unlock(); 280 kernconfig_unlock();
281 if (rv != 0) { 281 if (rv != 0) {
282 for (i = 0; i < nmodinfo; i++) { 282 for (i = 0; i < nmodinfo; i++) {
283 if (modp[i]) 283 if (modp[i])
284 kmem_free(modp[i], sizeof(*modp[i])); 284 kmem_free(modp[i], sizeof(*modp[i]));
285 } 285 }
286 } 286 }
287 kmem_free(modp, sizeof(*modp) * nmodinfo); 287 kmem_free(modp, sizeof(*modp) * nmodinfo);
288 return rv; 288 return rv;
289} 289}
290 290
291/* 291/*
292 * Optionally fini and remove builtin module from the kernel. 292 * Optionally fini and remove builtin module from the kernel.
293 * Note: the module will now be unreachable except via mi && builtin_add. 293 * Note: the module will now be unreachable except via mi && builtin_add.
294 */ 294 */
295int 295int
296module_builtin_remove(modinfo_t *mi, bool fini) 296module_builtin_remove(modinfo_t *mi, bool fini)
297{ 297{
298 struct module *mod; 298 struct module *mod;
299 int rv = 0; 299 int rv = 0;
300 300
301 if (fini) { 301 if (fini) {
302 rv = kauth_authorize_system(kauth_cred_get(), 302 rv = kauth_authorize_system(kauth_cred_get(),
303 KAUTH_SYSTEM_MODULE, 0, (void *)(uintptr_t)MODCTL_UNLOAD, 303 KAUTH_SYSTEM_MODULE, 0, (void *)(uintptr_t)MODCTL_UNLOAD,
304 NULL, NULL); 304 NULL, NULL);
305 if (rv) 305 if (rv)
306 return rv; 306 return rv;
307 307
308 kernconfig_lock(); 308 kernconfig_lock();
309 rv = module_do_unload(mi->mi_name, true); 309 rv = module_do_unload(mi->mi_name, true);
310 if (rv) { 310 if (rv) {
311 goto out; 311 goto out;
312 } 312 }
313 } else { 313 } else {
314 kernconfig_lock(); 314 kernconfig_lock();
315 } 315 }
316 TAILQ_FOREACH(mod, &module_builtins, mod_chain) { 316 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
317 if (strcmp(mod->mod_info->mi_name, mi->mi_name) == 0) 317 if (strcmp(mod->mod_info->mi_name, mi->mi_name) == 0)
318 break; 318 break;
319 } 319 }
320 if (mod) { 320 if (mod) {
321 TAILQ_REMOVE(&module_builtins, mod, mod_chain); 321 TAILQ_REMOVE(&module_builtins, mod, mod_chain);
322 module_builtinlist--; 322 module_builtinlist--;
323 } else { 323 } else {
324 KASSERT(fini == false); 324 KASSERT(fini == false);
325 rv = ENOENT; 325 rv = ENOENT;
326 } 326 }
327 327
328 out: 328 out:
329 kernconfig_unlock(); 329 kernconfig_unlock();
330 return rv; 330 return rv;
331} 331}
332 332
333/* 333/*
334 * module_init: 334 * module_init:
335 * 335 *
336 * Initialize the module subsystem. 336 * Initialize the module subsystem.
337 */ 337 */
338void 338void
339module_init(void) 339module_init(void)
340{ 340{
341 __link_set_decl(modules, modinfo_t); 341 __link_set_decl(modules, modinfo_t);
342 extern struct vm_map *module_map; 342 extern struct vm_map *module_map;
343 modinfo_t *const *mip; 343 modinfo_t *const *mip;
344 int rv; 344 int rv;
345 345
346 if (module_map == NULL) { 346 if (module_map == NULL) {
347 module_map = kernel_map; 347 module_map = kernel_map;
348 } 348 }
349 cv_init(&module_thread_cv, "mod_unld"); 349 cv_init(&module_thread_cv, "mod_unld");
350 mutex_init(&module_thread_lock, MUTEX_DEFAULT, IPL_NONE); 350 mutex_init(&module_thread_lock, MUTEX_DEFAULT, IPL_NONE);
351 351
352#ifdef MODULAR /* XXX */ 352#ifdef MODULAR /* XXX */
353 module_init_md(); 353 module_init_md();
354#endif 354#endif
355 355
356 if (!module_machine) 356 if (!module_machine)
357 module_machine = machine; 357 module_machine = machine;
358#if __NetBSD_Version__ / 1000000 % 100 == 99 /* -current */ 358#if __NetBSD_Version__ / 1000000 % 100 == 99 /* -current */
359 snprintf(module_base, sizeof(module_base), "/stand/%s/%s/modules", 359 snprintf(module_base, sizeof(module_base), "/stand/%s/%s/modules",
360 module_machine, osrelease); 360 module_machine, osrelease);
361#else /* release */ 361#else /* release */
362 snprintf(module_base, sizeof(module_base), "/stand/%s/%d.%d/modules", 362 snprintf(module_base, sizeof(module_base), "/stand/%s/%d.%d/modules",
363 module_machine, __NetBSD_Version__ / 100000000, 363 module_machine, __NetBSD_Version__ / 100000000,
364 __NetBSD_Version__ / 1000000 % 100); 364 __NetBSD_Version__ / 1000000 % 100);
365#endif 365#endif
366 366
367 module_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 367 module_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
368 module_listener_cb, NULL); 368 module_listener_cb, NULL);
369 369
370 __link_set_foreach(mip, modules) { 370 __link_set_foreach(mip, modules) {
371 if ((rv = module_builtin_add(mip, 1, false)) != 0) 371 if ((rv = module_builtin_add(mip, 1, false)) != 0)
372 module_error("builtin %s failed: %d\n", 372 module_error("builtin %s failed: %d\n",
373 (*mip)->mi_name, rv); 373 (*mip)->mi_name, rv);
374 } 374 }
375 375
376 sysctl_module_setup(); 376 sysctl_module_setup();
377} 377}
378 378
379/* 379/*
380 * module_start_unload_thread: 380 * module_start_unload_thread:
381 * 381 *
382 * Start the auto unload kthread. 382 * Start the auto unload kthread.
383 */ 383 */
384void 384void
385module_start_unload_thread(void) 385module_start_unload_thread(void)
386{ 386{
387 int error; 387 int error;
388 388
389 error = kthread_create(PRI_VM, KTHREAD_MPSAFE, NULL, module_thread, 389 error = kthread_create(PRI_VM, KTHREAD_MPSAFE, NULL, module_thread,
390 NULL, NULL, "modunload"); 390 NULL, NULL, "modunload");
391 if (error != 0) 391 if (error != 0)
392 panic("%s: %d", __func__, error); 392 panic("%s: %d", __func__, error);
393} 393}
394 394
395/* 395/*
396 * module_builtin_require_force 396 * module_builtin_require_force
397 * 397 *
398 * Require MODCTL_MUST_FORCE to load any built-in modules that have  398 * Require MODCTL_MUST_FORCE to load any built-in modules that have
399 * not yet been initialized 399 * not yet been initialized
400 */ 400 */
401void 401void
402module_builtin_require_force(void) 402module_builtin_require_force(void)
403{ 403{
404 module_t *mod; 404 module_t *mod;
405 405
406 kernconfig_lock(); 406 kernconfig_lock();
407 TAILQ_FOREACH(mod, &module_builtins, mod_chain) { 407 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
408 module_require_force(mod); 408 module_require_force(mod);
409 } 409 }
410 kernconfig_unlock(); 410 kernconfig_unlock();
411} 411}
412 412
413static struct sysctllog *module_sysctllog; 413static struct sysctllog *module_sysctllog;
414 414
415static int 415static int
416sysctl_module_autotime(SYSCTLFN_ARGS) 416sysctl_module_autotime(SYSCTLFN_ARGS)
417{ 417{
418 struct sysctlnode node; 418 struct sysctlnode node;
419 int t, error; 419 int t, error;
420 420
421 t = *(int *)rnode->sysctl_data; 421 t = *(int *)rnode->sysctl_data;
422 422
423 node = *rnode; 423 node = *rnode;
424 node.sysctl_data = &t; 424 node.sysctl_data = &t;
425 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 425 error = sysctl_lookup(SYSCTLFN_CALL(&node));
426 if (error || newp == NULL) 426 if (error || newp == NULL)
427 return (error); 427 return (error);
428 428
429 if (t < 0) 429 if (t < 0)
430 return (EINVAL); 430 return (EINVAL);
431 431
432 *(int *)rnode->sysctl_data = t; 432 *(int *)rnode->sysctl_data = t;
433 return (0); 433 return (0);
434} 434}
435 435
436static void 436static void
437sysctl_module_setup(void) 437sysctl_module_setup(void)
438{ 438{
439 const struct sysctlnode *node = NULL; 439 const struct sysctlnode *node = NULL;
440 440
441 sysctl_createv(&module_sysctllog, 0, NULL, &node, 441 sysctl_createv(&module_sysctllog, 0, NULL, &node,
442 CTLFLAG_PERMANENT, 442 CTLFLAG_PERMANENT,
443 CTLTYPE_NODE, "module", 443 CTLTYPE_NODE, "module",
444 SYSCTL_DESCR("Module options"), 444 SYSCTL_DESCR("Module options"),
445 NULL, 0, NULL, 0, 445 NULL, 0, NULL, 0,
446 CTL_KERN, CTL_CREATE, CTL_EOL); 446 CTL_KERN, CTL_CREATE, CTL_EOL);
447 447
448 if (node == NULL) 448 if (node == NULL)
449 return; 449 return;
450 450
451 sysctl_createv(&module_sysctllog, 0, &node, NULL, 451 sysctl_createv(&module_sysctllog, 0, &node, NULL,
452 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 452 CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
453 CTLTYPE_BOOL, "autoload", 453 CTLTYPE_BOOL, "autoload",
454 SYSCTL_DESCR("Enable automatic load of modules"), 454 SYSCTL_DESCR("Enable automatic load of modules"),
455 NULL, 0, &module_autoload_on, 0, 455 NULL, 0, &module_autoload_on, 0,
456 CTL_CREATE, CTL_EOL); 456 CTL_CREATE, CTL_EOL);
457 sysctl_createv(&module_sysctllog, 0, &node, NULL, 457 sysctl_createv(&module_sysctllog, 0, &node, NULL,
458 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 458 CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
459 CTLTYPE_BOOL, "verbose", 459 CTLTYPE_BOOL, "verbose",
460 SYSCTL_DESCR("Enable verbose output"), 460 SYSCTL_DESCR("Enable verbose output"),
461 NULL, 0, &module_verbose_on, 0, 461 NULL, 0, &module_verbose_on, 0,
462 CTL_CREATE, CTL_EOL); 462 CTL_CREATE, CTL_EOL);
463 sysctl_createv(&module_sysctllog, 0, &node, NULL, 463 sysctl_createv(&module_sysctllog, 0, &node, NULL,
464 CTLFLAG_PERMANENT | CTLFLAG_READONLY, 464 CTLFLAG_PERMANENT | CTLFLAG_READONLY,
465 CTLTYPE_STRING, "path", 465 CTLTYPE_STRING, "path",
466 SYSCTL_DESCR("Default module load path"), 466 SYSCTL_DESCR("Default module load path"),
467 NULL, 0, module_base, 0, 467 NULL, 0, module_base, 0,
468 CTL_CREATE, CTL_EOL); 468 CTL_CREATE, CTL_EOL);
469 sysctl_createv(&module_sysctllog, 0, &node, NULL, 469 sysctl_createv(&module_sysctllog, 0, &node, NULL,
470 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 470 CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
471 CTLTYPE_INT, "autotime", 471 CTLTYPE_INT, "autotime",
472 SYSCTL_DESCR("Auto-unload delay"), 472 SYSCTL_DESCR("Auto-unload delay"),
473 sysctl_module_autotime, 0, &module_autotime, 0, 473 sysctl_module_autotime, 0, &module_autotime, 0,
474 CTL_CREATE, CTL_EOL); 474 CTL_CREATE, CTL_EOL);
475} 475}
476 476
477/* 477/*
478 * module_init_class: 478 * module_init_class:
479 * 479 *
480 * Initialize all built-in and pre-loaded modules of the 480 * Initialize all built-in and pre-loaded modules of the
481 * specified class. 481 * specified class.
482 */ 482 */
483void 483void
484module_init_class(modclass_t modclass) 484module_init_class(modclass_t modclass)
485{ 485{
486 TAILQ_HEAD(, module) bi_fail = TAILQ_HEAD_INITIALIZER(bi_fail); 486 TAILQ_HEAD(, module) bi_fail = TAILQ_HEAD_INITIALIZER(bi_fail);
487 module_t *mod; 487 module_t *mod;
488 modinfo_t *mi; 488 modinfo_t *mi;
489 489
490 kernconfig_lock(); 490 kernconfig_lock();
491 /* 491 /*
492 * Builtins first. These will not depend on pre-loaded modules 492 * Builtins first. These will not depend on pre-loaded modules
493 * (because the kernel would not link). 493 * (because the kernel would not link).
494 */ 494 */
495 do { 495 do {
496 TAILQ_FOREACH(mod, &module_builtins, mod_chain) { 496 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
497 mi = mod->mod_info; 497 mi = mod->mod_info;
498 if (!MODULE_CLASS_MATCH(mi, modclass)) 498 if (!MODULE_CLASS_MATCH(mi, modclass))
499 continue; 499 continue;
500 /* 500 /*
501 * If initializing a builtin module fails, don't try 501 * If initializing a builtin module fails, don't try
502 * to load it again. But keep it around and queue it 502 * to load it again. But keep it around and queue it
503 * on the builtins list after we're done with module 503 * on the builtins list after we're done with module
504 * init. Don't set it to MODFLG_MUST_FORCE in case a 504 * init. Don't set it to MODFLG_MUST_FORCE in case a
505 * future attempt to initialize can be successful. 505 * future attempt to initialize can be successful.
506 * (If the module has previously been set to 506 * (If the module has previously been set to
507 * MODFLG_MUST_FORCE, don't try to override that!) 507 * MODFLG_MUST_FORCE, don't try to override that!)
508 */ 508 */
509 if ((mod->mod_flags & MODFLG_MUST_FORCE) || 509 if ((mod->mod_flags & MODFLG_MUST_FORCE) ||
510 module_do_builtin(mod, mi->mi_name, NULL, 510 module_do_builtin(mod, mi->mi_name, NULL,
511 NULL) != 0) { 511 NULL) != 0) {
512 TAILQ_REMOVE(&module_builtins, mod, mod_chain); 512 TAILQ_REMOVE(&module_builtins, mod, mod_chain);
513 TAILQ_INSERT_TAIL(&bi_fail, mod, mod_chain); 513 TAILQ_INSERT_TAIL(&bi_fail, mod, mod_chain);
514 } 514 }
515 break; 515 break;
516 } 516 }
517 } while (mod != NULL); 517 } while (mod != NULL);
518 518
519 /* 519 /*
520 * Now preloaded modules. These will be pulled off the 520 * Now preloaded modules. These will be pulled off the
521 * list as we call module_do_load(); 521 * list as we call module_do_load();
522 */ 522 */
523 do { 523 do {
524 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) { 524 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) {
525 mi = mod->mod_info; 525 mi = mod->mod_info;
526 if (!MODULE_CLASS_MATCH(mi, modclass)) 526 if (!MODULE_CLASS_MATCH(mi, modclass))
527 continue; 527 continue;
528 module_do_load(mi->mi_name, false, 0, NULL, NULL, 528 module_do_load(mi->mi_name, false, 0, NULL, NULL,
529 modclass, false); 529 modclass, false);
530 break; 530 break;
531 } 531 }
532 } while (mod != NULL); 532 } while (mod != NULL);
533 533
534 /* return failed builtin modules to builtin list */ 534 /* return failed builtin modules to builtin list */
535 while ((mod = TAILQ_FIRST(&bi_fail)) != NULL) { 535 while ((mod = TAILQ_FIRST(&bi_fail)) != NULL) {
536 TAILQ_REMOVE(&bi_fail, mod, mod_chain); 536 TAILQ_REMOVE(&bi_fail, mod, mod_chain);
537 TAILQ_INSERT_TAIL(&module_builtins, mod, mod_chain); 537 TAILQ_INSERT_TAIL(&module_builtins, mod, mod_chain);
538 } 538 }
539 539
540 kernconfig_unlock(); 540 kernconfig_unlock();
541} 541}
542 542
543/* 543/*
544 * module_compatible: 544 * module_compatible:
545 * 545 *
546 * Return true if the two supplied kernel versions are said to 546 * Return true if the two supplied kernel versions are said to
547 * have the same binary interface for kernel code. The entire 547 * have the same binary interface for kernel code. The entire
548 * version is signficant for the development tree (-current), 548 * version is signficant for the development tree (-current),
549 * major and minor versions are significant for official 549 * major and minor versions are significant for official
550 * releases of the system. 550 * releases of the system.
551 */ 551 */
552bool 552bool
553module_compatible(int v1, int v2) 553module_compatible(int v1, int v2)
554{ 554{
555 555
556#if __NetBSD_Version__ / 1000000 % 100 == 99 /* -current */ 556#if __NetBSD_Version__ / 1000000 % 100 == 99 /* -current */
557 return v1 == v2; 557 return v1 == v2;
558#else /* release */ 558#else /* release */
559 return abs(v1 - v2) < 10000; 559 return abs(v1 - v2) < 10000;
560#endif 560#endif
561} 561}
562 562
563/* 563/*
564 * module_load: 564 * module_load:
565 * 565 *
566 * Load a single module from the file system. 566 * Load a single module from the file system.
567 */ 567 */
568int 568int
569module_load(const char *filename, int flags, prop_dictionary_t props, 569module_load(const char *filename, int flags, prop_dictionary_t props,
570 modclass_t modclass) 570 modclass_t modclass)
571{ 571{
572 module_t *mod; 572 module_t *mod;
573 int error; 573 int error;
574 574
575 /* Test if we already have the module loaded before 575 /* Test if we already have the module loaded before
576 * authorizing so we have the opportunity to return EEXIST. */ 576 * authorizing so we have the opportunity to return EEXIST. */
577 kernconfig_lock(); 577 kernconfig_lock();
578 mod = module_lookup(filename); 578 mod = module_lookup(filename);
579 if (mod != NULL) { 579 if (mod != NULL) {
580 module_print("%s module `%s' already loaded", 580 module_print("%s module `%s' already loaded",
581 "requested", filename); 581 "requested", filename);
582 error = EEXIST; 582 error = EEXIST;
583 goto out; 583 goto out;
584 } 584 }
585 585
586 /* Authorize. */ 586 /* Authorize. */
587 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE, 587 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
588 0, (void *)(uintptr_t)MODCTL_LOAD, NULL, NULL); 588 0, (void *)(uintptr_t)MODCTL_LOAD, NULL, NULL);
589 if (error != 0) 589 if (error != 0)
590 goto out; 590 goto out;
591 591
592 error = module_do_load(filename, false, flags, props, NULL, modclass, 592 error = module_do_load(filename, false, flags, props, NULL, modclass,
593 false); 593 false);
594 594
595out: 595out:
596 kernconfig_unlock(); 596 kernconfig_unlock();
597 return error; 597 return error;
598} 598}
599 599
600/* 600/*
601 * module_autoload: 601 * module_autoload:
602 * 602 *
603 * Load a single module from the file system, system initiated. 603 * Load a single module from the file system, system initiated.
604 */ 604 */
605int 605int
606module_autoload(const char *filename, modclass_t modclass) 606module_autoload(const char *filename, modclass_t modclass)
607{ 607{
608 int error; 608 int error;
609 609
610 kernconfig_lock(); 610 kernconfig_lock();
611 611
612 /* Nothing if the user has disabled it. */ 612 /* Nothing if the user has disabled it. */
613 if (!module_autoload_on) { 613 if (!module_autoload_on) {
614 kernconfig_unlock(); 614 kernconfig_unlock();
615 return EPERM; 615 return EPERM;
616 } 616 }
617 617
618 /* Disallow path separators and magic symlinks. */ 618 /* Disallow path separators and magic symlinks. */
619 if (strchr(filename, '/') != NULL || strchr(filename, '@') != NULL || 619 if (strchr(filename, '/') != NULL || strchr(filename, '@') != NULL ||
620 strchr(filename, '.') != NULL) { 620 strchr(filename, '.') != NULL) {
621 kernconfig_unlock(); 621 kernconfig_unlock();
622 return EPERM; 622 return EPERM;
623 } 623 }
624 624
625 /* Authorize. */ 625 /* Authorize. */
626 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE, 626 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
627 0, (void *)(uintptr_t)MODCTL_LOAD, (void *)(uintptr_t)1, NULL); 627 0, (void *)(uintptr_t)MODCTL_LOAD, (void *)(uintptr_t)1, NULL);
628 628
629 if (error == 0) 629 if (error == 0)
630 error = module_do_load(filename, false, 0, NULL, NULL, modclass, 630 error = module_do_load(filename, false, 0, NULL, NULL, modclass,
631 true); 631 true);
632 632
633 kernconfig_unlock(); 633 kernconfig_unlock();
634 return error; 634 return error;
635} 635}
636 636
637/* 637/*
638 * module_unload: 638 * module_unload:
639 * 639 *
640 * Find and unload a module by name. 640 * Find and unload a module by name.
641 */ 641 */
642int 642int
643module_unload(const char *name) 643module_unload(const char *name)
644{ 644{
645 int error; 645 int error;
646 646
647 /* Authorize. */ 647 /* Authorize. */
648 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE, 648 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
649 0, (void *)(uintptr_t)MODCTL_UNLOAD, NULL, NULL); 649 0, (void *)(uintptr_t)MODCTL_UNLOAD, NULL, NULL);
650 if (error != 0) { 650 if (error != 0) {
651 return error; 651 return error;
652 } 652 }
653 653
654 kernconfig_lock(); 654 kernconfig_lock();
655 error = module_do_unload(name, true); 655 error = module_do_unload(name, true);
656 kernconfig_unlock(); 656 kernconfig_unlock();
657 657
658 return error; 658 return error;
659} 659}
660 660
661/* 661/*
662 * module_alias_lookup 662 * module_alias_lookup
663 * 663 *
664 * locate a name within a module's alias list 664 * locate a name within a module's alias list
665 */ 665 */
666int 666int
667module_alias_lookup(const char *name, module_t *mod) 667module_alias_lookup(const char *name, module_t *mod)
668{ 668{
669 const char * const aliasp[]; 669 const char * const *aliasp;
670 670
671 aliasp = *mod->mod_info->mi_aliases; 671 aliasp = *mod->mod_info->mi_aliases;
672 if (aliasp == NULL) 672 if (aliasp == NULL)
673 return 0; 673 return 0;
674 while (*aliasp) 674 while (*aliasp)
675 if (strcmp(*aliasp++, name) == 0) 675 if (strcmp(*aliasp++, name) == 0)
676 return 1; 676 return 1;
677 return 0; 677 return 0;
678} 678}
679 679
680/* 680/*
681 * module_lookup: 681 * module_lookup:
682 * 682 *
683 * Look up a module by name. 683 * Look up a module by name.
684 */ 684 */
685module_t * 685module_t *
686module_lookup(const char *name) 686module_lookup(const char *name)
687{ 687{
688 module_t *mod; 688 module_t *mod;
689 689
690 KASSERT(kernconfig_is_held()); 690 KASSERT(kernconfig_is_held());
691 691
692 TAILQ_FOREACH(mod, &module_list, mod_chain) { 692 TAILQ_FOREACH(mod, &module_list, mod_chain) {
693 if (strcmp(mod->mod_info->mi_name, name) == 0) { 693 if (strcmp(mod->mod_info->mi_name, name) == 0) {
694 break; 694 break;
695 if (module_alias_lookup(name, mod)) 695 if (module_alias_lookup(name, mod))
696 break; 696 break;
697 } 697 }
698 } 698 }
699 699
700 return mod; 700 return mod;
701} 701}
702 702
703/* 703/*
704 * module_hold: 704 * module_hold:
705 * 705 *
706 * Add a single reference to a module. It's the caller's 706 * Add a single reference to a module. It's the caller's
707 * responsibility to ensure that the reference is dropped 707 * responsibility to ensure that the reference is dropped
708 * later. 708 * later.
709 */ 709 */
710int 710int
711module_hold(const char *name) 711module_hold(const char *name)
712{ 712{
713 module_t *mod; 713 module_t *mod;
714 714
715 kernconfig_lock(); 715 kernconfig_lock();
716 mod = module_lookup(name); 716 mod = module_lookup(name);
717 if (mod == NULL) { 717 if (mod == NULL) {
718 kernconfig_unlock(); 718 kernconfig_unlock();
719 return ENOENT; 719 return ENOENT;
720 } 720 }
721 mod->mod_refcnt++; 721 mod->mod_refcnt++;
722 kernconfig_unlock(); 722 kernconfig_unlock();
723 723
724 return 0; 724 return 0;
725} 725}
726 726
727/* 727/*
728 * module_rele: 728 * module_rele:
729 * 729 *
730 * Release a reference acquired with module_hold(). 730 * Release a reference acquired with module_hold().
731 */ 731 */
732void 732void
733module_rele(const char *name) 733module_rele(const char *name)
734{ 734{
735 module_t *mod; 735 module_t *mod;
736 736
737 kernconfig_lock(); 737 kernconfig_lock();
738 mod = module_lookup(name); 738 mod = module_lookup(name);
739 if (mod == NULL) { 739 if (mod == NULL) {
740 kernconfig_unlock(); 740 kernconfig_unlock();
741 panic("%s: gone", __func__); 741 panic("%s: gone", __func__);
742 } 742 }
743 mod->mod_refcnt--; 743 mod->mod_refcnt--;
744 kernconfig_unlock(); 744 kernconfig_unlock();
745} 745}
746 746
747/* 747/*
748 * module_enqueue: 748 * module_enqueue:
749 * 749 *
750 * Put a module onto the global list and update counters. 750 * Put a module onto the global list and update counters.
751 */ 751 */
752void 752void
753module_enqueue(module_t *mod) 753module_enqueue(module_t *mod)
754{ 754{
755 int i; 755 int i;
756 756
757 KASSERT(kernconfig_is_held()); 757 KASSERT(kernconfig_is_held());
758 758
759 /* 759 /*
760 * Put new entry at the head of the queue so autounload can unload 760 * Put new entry at the head of the queue so autounload can unload
761 * requisite modules with only one pass through the queue. 761 * requisite modules with only one pass through the queue.
762 */ 762 */
763 TAILQ_INSERT_HEAD(&module_list, mod, mod_chain); 763 TAILQ_INSERT_HEAD(&module_list, mod, mod_chain);
764 if (mod->mod_nrequired) { 764 if (mod->mod_nrequired) {
765 765
766 /* Add references to the requisite modules. */ 766 /* Add references to the requisite modules. */
767 for (i = 0; i < mod->mod_nrequired; i++) { 767 for (i = 0; i < mod->mod_nrequired; i++) {
768 KASSERT(mod->mod_required[i] != NULL); 768 KASSERT(mod->mod_required[i] != NULL);
769 mod->mod_required[i]->mod_refcnt++; 769 mod->mod_required[i]->mod_refcnt++;
770 } 770 }
771 } 771 }
772 module_count++; 772 module_count++;
773 module_gen++; 773 module_gen++;
774} 774}
775 775
776/* 776/*
777 * module_do_builtin: 777 * module_do_builtin:
778 * 778 *
779 * Initialize a module from the list of modules that are 779 * Initialize a module from the list of modules that are
780 * already linked into the kernel. 780 * already linked into the kernel.
781 */ 781 */
782static int 782static int
783module_do_builtin(const module_t *pmod, const char *name, module_t **modp, 783module_do_builtin(const module_t *pmod, const char *name, module_t **modp,
784 prop_dictionary_t props) 784 prop_dictionary_t props)
785{ 785{
786 const char *p, *s; 786 const char *p, *s;
787 const char * const aliasp[]; 787 const char * const *aliasp;
788 char buf[MAXMODNAME]; 788 char buf[MAXMODNAME];
789 modinfo_t *mi = NULL; 789 modinfo_t *mi = NULL;
790 module_t *mod, *mod2, *mod_loaded, *prev_active; 790 module_t *mod, *mod2, *mod_loaded, *prev_active;
791 size_t len; 791 size_t len;
792 int error; 792 int error;
793 793
794 KASSERT(kernconfig_is_held()); 794 KASSERT(kernconfig_is_held());
795 795
796 /* 796 /*
797 * Search the list to see if we have a module by this name. 797 * Search the list to see if we have a module by this name.
798 */ 798 */
799 TAILQ_FOREACH(mod, &module_builtins, mod_chain) { 799 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
800 if (strcmp(mod->mod_info->mi_name, name) == 0) { 800 if (strcmp(mod->mod_info->mi_name, name) == 0) {
801 mi = mod->mod_info; 801 mi = mod->mod_info;
802 break; 802 break;
803 } 803 }
804 } 804 }
805 805
806 /* 806 /*
807 * Check to see if already loaded. This might happen if we 807 * Check to see if already loaded. This might happen if we
808 * were already loaded as a dependency. 808 * were already loaded as a dependency.
809 */ 809 */
810 if ((mod_loaded = module_lookup(name)) != NULL) { 810 if ((mod_loaded = module_lookup(name)) != NULL) {
811 KASSERT(mod == NULL); 811 KASSERT(mod == NULL);
812 if (modp) 812 if (modp)
813 *modp = mod_loaded; 813 *modp = mod_loaded;
814 return 0; 814 return 0;
815 } 815 }
816 816
817 /* Note! This is from TAILQ, not immediate above */ 817 /* Note! This is from TAILQ, not immediate above */
818 if (mi == NULL) { 818 if (mi == NULL) {
819 /* 819 /*
820 * XXX: We'd like to panic here, but currently in some 820 * XXX: We'd like to panic here, but currently in some
821 * cases (such as nfsserver + nfs), the dependee can be 821 * cases (such as nfsserver + nfs), the dependee can be
822 * succesfully linked without the dependencies. 822 * succesfully linked without the dependencies.
823 */ 823 */
824 module_error("%s: can't find builtin dependency `%s'", 824 module_error("%s: can't find builtin dependency `%s'",
825 pmod->mod_info->mi_name, name); 825 pmod->mod_info->mi_name, name);
826 return ENOENT; 826 return ENOENT;
827 } 827 }
828 828
829 /* 829 /*
830 * Initialize pre-requisites. 830 * Initialize pre-requisites.
831 */ 831 */
832 if (mi->mi_required != NULL) { 832 if (mi->mi_required != NULL) {
833 for (s = mi->mi_required; *s != '\0'; s = p) { 833 for (s = mi->mi_required; *s != '\0'; s = p) {
834 if (*s == ',') 834 if (*s == ',')
835 s++; 835 s++;
836 p = s; 836 p = s;
837 while (*p != '\0' && *p != ',') 837 while (*p != '\0' && *p != ',')
838 p++; 838 p++;
839 len = min(p - s + 1, sizeof(buf)); 839 len = min(p - s + 1, sizeof(buf));
840 strlcpy(buf, s, len); 840 strlcpy(buf, s, len);
841 if (buf[0] == '\0') 841 if (buf[0] == '\0')
842 break; 842 break;
843 if (mod->mod_nrequired == MAXMODDEPS - 1) { 843 if (mod->mod_nrequired == MAXMODDEPS - 1) {
844 module_error("%s: too many required modules " 844 module_error("%s: too many required modules "
845 "%d >= %d", pmod->mod_info->mi_name, 845 "%d >= %d", pmod->mod_info->mi_name,
846 mod->mod_nrequired, MAXMODDEPS - 1); 846 mod->mod_nrequired, MAXMODDEPS - 1);
847 return EINVAL; 847 return EINVAL;
848 } 848 }
849 error = module_do_builtin(mod, buf, &mod2, NULL); 849 error = module_do_builtin(mod, buf, &mod2, NULL);
850 if (error != 0) { 850 if (error != 0) {
851 return error; 851 return error;
852 } 852 }
853 mod->mod_required[mod->mod_nrequired++] = mod2; 853 mod->mod_required[mod->mod_nrequired++] = mod2;
854 } 854 }
855 } 855 }
856 856
857 /* 857 /*
858 * Retrieve that none of the module's aliases already exist 858 * Retrieve that none of the module's aliases already exist
859 */ 859 */
860 860
861 if ((aliasp = *mod->mod_info->mi_aliases) != NULL) { 861 if ((aliasp = *mod->mod_info->mi_aliases) != NULL) {
862 while (*aliasp) 862 while (*aliasp)
863 if (module_lookup(*aliasp++) != NULL) 863 if (module_lookup(*aliasp++) != NULL)
864 return EEXIST; 864 return EEXIST;
865 } 865 }
866 /* 866 /*
867 * Try to initialize the module. 867 * Try to initialize the module.
868 */ 868 */
869 prev_active = module_active; 869 prev_active = module_active;
870 module_active = mod; 870 module_active = mod;
871 error = (*mi->mi_modcmd)(MODULE_CMD_INIT, props); 871 error = (*mi->mi_modcmd)(MODULE_CMD_INIT, props);
872 module_active = prev_active; 872 module_active = prev_active;
873 if (error != 0) { 873 if (error != 0) {
874 module_error("builtin module `%s' " 874 module_error("builtin module `%s' "
875 "failed to init, error %d", mi->mi_name, error); 875 "failed to init, error %d", mi->mi_name, error);
876 return error; 876 return error;
877 } 877 }
878 878
879 /* load always succeeds after this point */ 879 /* load always succeeds after this point */
880 880
881 TAILQ_REMOVE(&module_builtins, mod, mod_chain); 881 TAILQ_REMOVE(&module_builtins, mod, mod_chain);
882 module_builtinlist--; 882 module_builtinlist--;
883 if (modp != NULL) { 883 if (modp != NULL) {
884 *modp = mod; 884 *modp = mod;
885 } 885 }
886 module_enqueue(mod); 886 module_enqueue(mod);
887 return 0; 887 return 0;
888} 888}
889 889
890/* 890/*
891 * module_do_load: 891 * module_do_load:
892 * 892 *
893 * Helper routine: load a module from the file system, or one 893 * Helper routine: load a module from the file system, or one
894 * pushed by the boot loader. 894 * pushed by the boot loader.
895 */ 895 */
896static int 896static int
897module_do_load(const char *name, bool isdep, int flags, 897module_do_load(const char *name, bool isdep, int flags,
898 prop_dictionary_t props, module_t **modp, modclass_t modclass, 898 prop_dictionary_t props, module_t **modp, modclass_t modclass,
899 bool autoload) 899 bool autoload)
900{ 900{
901#define MODULE_MAX_DEPTH 6 901#define MODULE_MAX_DEPTH 6
902 902
903 TAILQ_HEAD(pending_t, module); 903 TAILQ_HEAD(pending_t, module);
904 static int depth = 0; 904 static int depth = 0;
905 static struct pending_t *pending_lists[MODULE_MAX_DEPTH]; 905 static struct pending_t *pending_lists[MODULE_MAX_DEPTH];
906 struct pending_t *pending; 906 struct pending_t *pending;
907 struct pending_t new_pending = TAILQ_HEAD_INITIALIZER(new_pending); 907 struct pending_t new_pending = TAILQ_HEAD_INITIALIZER(new_pending);
908 modinfo_t *mi; 908 modinfo_t *mi;
909 module_t *mod, *mod2, *prev_active; 909 module_t *mod, *mod2, *prev_active;
910 prop_dictionary_t filedict; 910 prop_dictionary_t filedict;
911 char buf[MAXMODNAME]; 911 char buf[MAXMODNAME];
912 const char *s, *p; 912 const char *s, *p;
913 const char * const aliasp[]; 913 const char * const *aliasp;
914 int error; 914 int error;
915 size_t len; 915 size_t len;
916 916
917 KASSERT(kernconfig_is_held()); 917 KASSERT(kernconfig_is_held());
918 918
919 filedict = NULL; 919 filedict = NULL;
920 error = 0; 920 error = 0;
921 921
922 /* 922 /*
923 * Avoid recursing too far. 923 * Avoid recursing too far.
924 */ 924 */
925 if (++depth > MODULE_MAX_DEPTH) { 925 if (++depth > MODULE_MAX_DEPTH) {
926 module_error("recursion too deep for `%s' %d > %d", name, 926 module_error("recursion too deep for `%s' %d > %d", name,
927 depth, MODULE_MAX_DEPTH); 927 depth, MODULE_MAX_DEPTH);
928 depth--; 928 depth--;
929 return EMLINK; 929 return EMLINK;
930 } 930 }
931 931
932 /* 932 /*
933 * Set up the pending list for this depth. If this is a 933 * Set up the pending list for this depth. If this is a
934 * recursive entry, then use same list as for outer call, 934 * recursive entry, then use same list as for outer call,
935 * else use the locally allocated list. In either case, 935 * else use the locally allocated list. In either case,
936 * remember which one we're using. 936 * remember which one we're using.
937 */ 937 */
938 if (isdep) { 938 if (isdep) {
939 KASSERT(depth > 1); 939 KASSERT(depth > 1);
940 pending = pending_lists[depth - 2]; 940 pending = pending_lists[depth - 2];
941 } else 941 } else
942 pending = &new_pending; 942 pending = &new_pending;
943 pending_lists[depth - 1] = pending; 943 pending_lists[depth - 1] = pending;
944 944
945 /* 945 /*
946 * Search the list of disabled builtins first. 946 * Search the list of disabled builtins first.
947 */ 947 */
948 TAILQ_FOREACH(mod, &module_builtins, mod_chain) { 948 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
949 if (strcmp(mod->mod_info->mi_name, name) == 0) { 949 if (strcmp(mod->mod_info->mi_name, name) == 0) {
950 break; 950 break;
951 } 951 }
952 } 952 }
953 if (mod) { 953 if (mod) {
954 if ((mod->mod_flags & MODFLG_MUST_FORCE) && 954 if ((mod->mod_flags & MODFLG_MUST_FORCE) &&
955 (flags & MODCTL_LOAD_FORCE) == 0) { 955 (flags & MODCTL_LOAD_FORCE) == 0) {
956 if (!autoload) { 956 if (!autoload) {
957 module_error("use -f to reinstate " 957 module_error("use -f to reinstate "
958 "builtin module `%s'", name); 958 "builtin module `%s'", name);
959 } 959 }
960 depth--; 960 depth--;
961 return EPERM; 961 return EPERM;
962 } else { 962 } else {
963 error = module_do_builtin(mod, name, modp, props); 963 error = module_do_builtin(mod, name, modp, props);
964 depth--; 964 depth--;
965 return error; 965 return error;
966 } 966 }
967 } 967 }
968 968
969 /* 969 /*
970 * Load the module and link. Before going to the file system, 970 * Load the module and link. Before going to the file system,
971 * scan the list of modules loaded by the boot loader. 971 * scan the list of modules loaded by the boot loader.
972 */ 972 */
973 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) { 973 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) {
974 if (strcmp(mod->mod_info->mi_name, name) == 0) { 974 if (strcmp(mod->mod_info->mi_name, name) == 0) {
975 TAILQ_REMOVE(&module_bootlist, mod, mod_chain); 975 TAILQ_REMOVE(&module_bootlist, mod, mod_chain);
976 break; 976 break;
977 } 977 }
978 } 978 }
979 if (mod != NULL) { 979 if (mod != NULL) {
980 TAILQ_INSERT_TAIL(pending, mod, mod_chain); 980 TAILQ_INSERT_TAIL(pending, mod, mod_chain);
981 } else { 981 } else {
982 /* 982 /*
983 * Check to see if module is already present. 983 * Check to see if module is already present.
984 */ 984 */
985 mod = module_lookup(name); 985 mod = module_lookup(name);
986 if (mod != NULL) { 986 if (mod != NULL) {
987 if (modp != NULL) { 987 if (modp != NULL) {
988 *modp = mod; 988 *modp = mod;
989 } 989 }
990 module_print("%s module `%s' already loaded", 990 module_print("%s module `%s' already loaded",
991 isdep ? "dependent" : "requested", name); 991 isdep ? "dependent" : "requested", name);
992 depth--; 992 depth--;
993 return EEXIST; 993 return EEXIST;
994 } 994 }
995 995
996 mod = module_newmodule(MODULE_SOURCE_FILESYS); 996 mod = module_newmodule(MODULE_SOURCE_FILESYS);
997 if (mod == NULL) { 997 if (mod == NULL) {
998 module_error("out of memory for `%s'", name); 998 module_error("out of memory for `%s'", name);
999 depth--; 999 depth--;
1000 return ENOMEM; 1000 return ENOMEM;
1001 } 1001 }
1002 1002
1003 error = module_load_vfs_vec(name, flags, autoload, mod, 1003 error = module_load_vfs_vec(name, flags, autoload, mod,
1004 &filedict); 1004 &filedict);
1005 if (error != 0) { 1005 if (error != 0) {
1006#ifdef DEBUG 1006#ifdef DEBUG
1007 /* 1007 /*
1008 * The exec class of modules contains a list of 1008 * The exec class of modules contains a list of
1009 * modules that is the union of all the modules 1009 * modules that is the union of all the modules
1010 * available for each architecture, so we don't 1010 * available for each architecture, so we don't
1011 * print an error if they are missing. 1011 * print an error if they are missing.
1012 */ 1012 */
1013 if ((modclass != MODULE_CLASS_EXEC || error != ENOENT) 1013 if ((modclass != MODULE_CLASS_EXEC || error != ENOENT)
1014 && root_device != NULL) 1014 && root_device != NULL)
1015 module_error("vfs load failed for `%s', " 1015 module_error("vfs load failed for `%s', "
1016 "error %d", name, error); 1016 "error %d", name, error);
1017#endif 1017#endif
1018 kmem_free(mod, sizeof(*mod)); 1018 kmem_free(mod, sizeof(*mod));
1019 depth--; 1019 depth--;
1020 return error; 1020 return error;
1021 } 1021 }
1022 TAILQ_INSERT_TAIL(pending, mod, mod_chain); 1022 TAILQ_INSERT_TAIL(pending, mod, mod_chain);
1023 1023
1024 error = module_fetch_info(mod); 1024 error = module_fetch_info(mod);
1025 if (error != 0) { 1025 if (error != 0) {
1026 module_error("cannot fetch info for `%s', error %d", 1026 module_error("cannot fetch info for `%s', error %d",
1027 name, error); 1027 name, error);
1028 goto fail; 1028 goto fail;
1029 } 1029 }
1030 } 1030 }
1031 1031
1032 /* 1032 /*
1033 * Check compatibility. 1033 * Check compatibility.
1034 */ 1034 */
1035 mi = mod->mod_info; 1035 mi = mod->mod_info;
1036 if (strlen(mi->mi_name) >= MAXMODNAME) { 1036 if (strlen(mi->mi_name) >= MAXMODNAME) {
1037 error = EINVAL; 1037 error = EINVAL;
1038 module_error("module name `%s' longer than %d", mi->mi_name, 1038 module_error("module name `%s' longer than %d", mi->mi_name,
1039 MAXMODNAME); 1039 MAXMODNAME);
1040 goto fail; 1040 goto fail;
1041 } 1041 }
1042 if (!module_compatible(mi->mi_version, __NetBSD_Version__)) { 1042 if (!module_compatible(mi->mi_version, __NetBSD_Version__)) {
1043 module_error("module `%s' built for `%d', system `%d'", 1043 module_error("module `%s' built for `%d', system `%d'",
1044 mi->mi_name, mi->mi_version, __NetBSD_Version__); 1044 mi->mi_name, mi->mi_version, __NetBSD_Version__);
1045 if ((flags & MODCTL_LOAD_FORCE) != 0) { 1045 if ((flags & MODCTL_LOAD_FORCE) != 0) {
1046 module_error("forced load, system may be unstable"); 1046 module_error("forced load, system may be unstable");
1047 } else { 1047 } else {
1048 error = EPROGMISMATCH; 1048 error = EPROGMISMATCH;
1049 goto fail; 1049 goto fail;
1050 } 1050 }
1051 } 1051 }
1052 1052
1053 /* 1053 /*
1054 * If a specific kind of module was requested, ensure that we have 1054 * If a specific kind of module was requested, ensure that we have
1055 * a match. 1055 * a match.
1056 */ 1056 */
1057 if (!MODULE_CLASS_MATCH(mi, modclass)) { 1057 if (!MODULE_CLASS_MATCH(mi, modclass)) {
1058 module_incompat(mi, modclass); 1058 module_incompat(mi, modclass);
1059 error = ENOENT; 1059 error = ENOENT;
1060 goto fail; 1060 goto fail;
1061 } 1061 }
1062 1062
1063 /* 1063 /*
1064 * If loading a dependency, `name' is a plain module name. 1064 * If loading a dependency, `name' is a plain module name.
1065 * The name must match. 1065 * The name must match.
1066 */ 1066 */
1067 if (isdep && strcmp(mi->mi_name, name) != 0) { 1067 if (isdep && strcmp(mi->mi_name, name) != 0) {
1068 module_error("dependency name mismatch (`%s' != `%s')", 1068 module_error("dependency name mismatch (`%s' != `%s')",
1069 name, mi->mi_name); 1069 name, mi->mi_name);
1070 error = ENOENT; 1070 error = ENOENT;
1071 goto fail; 1071 goto fail;
1072 } 1072 }
1073 1073
1074 /* 1074 /*
1075 * If we loaded a module from the filesystem, check the actual 1075 * If we loaded a module from the filesystem, check the actual
1076 * module name (from the modinfo_t) to ensure another module 1076 * module name (from the modinfo_t) to ensure another module
1077 * with the same name doesn't already exist. (There's no 1077 * with the same name doesn't already exist. (There's no
1078 * guarantee the filename will match the module name, and the 1078 * guarantee the filename will match the module name, and the
1079 * dup-symbols check may not be sufficient.) 1079 * dup-symbols check may not be sufficient.)
1080 */ 1080 */
1081 if (mod->mod_source == MODULE_SOURCE_FILESYS) { 1081 if (mod->mod_source == MODULE_SOURCE_FILESYS) {
1082 mod2 = module_lookup(mod->mod_info->mi_name); 1082 mod2 = module_lookup(mod->mod_info->mi_name);
1083 if ( mod2 && mod2 != mod) { 1083 if ( mod2 && mod2 != mod) {
1084 module_error("module with name `%s' already loaded", 1084 module_error("module with name `%s' already loaded",
1085 mod2->mod_info->mi_name); 1085 mod2->mod_info->mi_name);
1086 error = EEXIST; 1086 error = EEXIST;
1087 goto fail; 1087 goto fail;
1088 } 1088 }
1089 } 1089 }
1090 1090
1091 /* 1091 /*
1092 * Block circular dependencies. 1092 * Block circular dependencies.
1093 */ 1093 */
1094 TAILQ_FOREACH(mod2, pending, mod_chain) { 1094 TAILQ_FOREACH(mod2, pending, mod_chain) {
1095 if (mod == mod2) { 1095 if (mod == mod2) {
1096 continue; 1096 continue;
1097 } 1097 }
1098 if (strcmp(mod2->mod_info->mi_name, mi->mi_name) == 0) { 1098 if (strcmp(mod2->mod_info->mi_name, mi->mi_name) == 0) {
1099 error = EDEADLK; 1099 error = EDEADLK;
1100 module_error("circular dependency detected for `%s'", 1100 module_error("circular dependency detected for `%s'",
1101 mi->mi_name); 1101 mi->mi_name);
1102 goto fail; 1102 goto fail;
1103 } 1103 }
1104 } 1104 }
1105 1105
1106 /* 1106 /*
1107 * Now try to load any requisite modules. 1107 * Now try to load any requisite modules.
1108 */ 1108 */
1109 if (mi->mi_required != NULL) { 1109 if (mi->mi_required != NULL) {
1110 for (s = mi->mi_required; *s != '\0'; s = p) { 1110 for (s = mi->mi_required; *s != '\0'; s = p) {
1111 if (*s == ',') 1111 if (*s == ',')
1112 s++; 1112 s++;
1113 p = s; 1113 p = s;
1114 while (*p != '\0' && *p != ',') 1114 while (*p != '\0' && *p != ',')
1115 p++; 1115 p++;
1116 len = p - s + 1; 1116 len = p - s + 1;
1117 if (len >= MAXMODNAME) { 1117 if (len >= MAXMODNAME) {
1118 error = EINVAL; 1118 error = EINVAL;
1119 module_error("required module name `%s' " 1119 module_error("required module name `%s' "
1120 "longer than %d", mi->mi_required, 1120 "longer than %d", mi->mi_required,
1121 MAXMODNAME); 1121 MAXMODNAME);
1122 goto fail; 1122 goto fail;
1123 } 1123 }
1124 strlcpy(buf, s, len); 1124 strlcpy(buf, s, len);
1125 if (buf[0] == '\0') 1125 if (buf[0] == '\0')
1126 break; 1126 break;
1127 if (mod->mod_nrequired == MAXMODDEPS - 1) { 1127 if (mod->mod_nrequired == MAXMODDEPS - 1) {
1128 error = EINVAL; 1128 error = EINVAL;
1129 module_error("too many required modules " 1129 module_error("too many required modules "
1130 "%d >= %d", mod->mod_nrequired, 1130 "%d >= %d", mod->mod_nrequired,
1131 MAXMODDEPS - 1); 1131 MAXMODDEPS - 1);
1132 goto fail; 1132 goto fail;
1133 } 1133 }
1134 if (strcmp(buf, mi->mi_name) == 0) { 1134 if (strcmp(buf, mi->mi_name) == 0) {
1135 error = EDEADLK; 1135 error = EDEADLK;
1136 module_error("self-dependency detected for " 1136 module_error("self-dependency detected for "
1137 "`%s'", mi->mi_name); 1137 "`%s'", mi->mi_name);
1138 goto fail; 1138 goto fail;
1139 } 1139 }
1140 error = module_do_load(buf, true, flags, NULL, 1140 error = module_do_load(buf, true, flags, NULL,
1141 &mod2, MODULE_CLASS_ANY, true); 1141 &mod2, MODULE_CLASS_ANY, true);
1142 if (error != 0 && error != EEXIST) { 1142 if (error != 0 && error != EEXIST) {
1143 module_error("recursive load failed for `%s' " 1143 module_error("recursive load failed for `%s' "
1144 "(`%s' required), error %d", mi->mi_name, 1144 "(`%s' required), error %d", mi->mi_name,
1145 buf, error); 1145 buf, error);
1146 goto fail; 1146 goto fail;
1147 } 1147 }
1148 mod->mod_required[mod->mod_nrequired++] = mod2; 1148 mod->mod_required[mod->mod_nrequired++] = mod2;
1149 } 1149 }
1150 } 1150 }
1151 1151
1152 /* 1152 /*
1153 * We loaded all needed modules successfully: perform global 1153 * We loaded all needed modules successfully: perform global
1154 * relocations and initialize. 1154 * relocations and initialize.
1155 */ 1155 */
1156 error = kobj_affix(mod->mod_kobj, mi->mi_name); 1156 error = kobj_affix(mod->mod_kobj, mi->mi_name);
1157 if (error != 0) { 1157 if (error != 0) {
1158 /* Cannot touch 'mi' as the module is now gone. */ 1158 /* Cannot touch 'mi' as the module is now gone. */
1159 module_error("unable to affix module `%s', error %d", name, 1159 module_error("unable to affix module `%s', error %d", name,
1160 error); 1160 error);
1161 goto fail2; 1161 goto fail2;
1162 } 1162 }
1163 1163
1164 if (filedict) { 1164 if (filedict) {
1165 if (!module_merge_dicts(filedict, props)) { 1165 if (!module_merge_dicts(filedict, props)) {
1166 module_error("module properties failed for %s", name); 1166 module_error("module properties failed for %s", name);
1167 error = EINVAL; 1167 error = EINVAL;
1168 goto fail; 1168 goto fail;
1169 } 1169 }
1170 } 1170 }
1171 /* 1171 /*
1172 * One last check for duplicate module name/alias 1172 * One last check for duplicate module name/alias
1173 */ 1173 */
1174 if ((aliasp = *mod->mod_info->mi_aliases) != NULL) 1174 if ((aliasp = *mod->mod_info->mi_aliases) != NULL)
1175 while (*aliasp != NULL) 1175 while (*aliasp != NULL)
1176 if (module_lookup(*aliasp) != NULL) { 1176 if (module_lookup(*aliasp) != NULL) {
1177 module_error("Module `%s' alias `%s' already " 1177 module_error("Module `%s' alias `%s' already "
1178 "exists", mod->mod_info->mi_name, *aliasp); 1178 "exists", mod->mod_info->mi_name, *aliasp);
1179 goto fail; 1179 goto fail;
1180 } 1180 }
1181 1181
1182 prev_active = module_active; 1182 prev_active = module_active;
1183 module_active = mod; 1183 module_active = mod;
1184 error = (*mi->mi_modcmd)(MODULE_CMD_INIT, filedict ? filedict : props); 1184 error = (*mi->mi_modcmd)(MODULE_CMD_INIT, filedict ? filedict : props);
1185 module_active = prev_active; 1185 module_active = prev_active;
1186 if (filedict) { 1186 if (filedict) {
1187 prop_object_release(filedict); 1187 prop_object_release(filedict);
1188 filedict = NULL; 1188 filedict = NULL;
1189 } 1189 }
1190 if (error != 0) { 1190 if (error != 0) {
1191 module_error("modcmd function failed for `%s', error %d", 1191 module_error("modcmd function failed for `%s', error %d",
1192 mi->mi_name, error); 1192 mi->mi_name, error);
1193 goto fail; 1193 goto fail;
1194 } 1194 }
1195 1195
1196 /* 1196 /*
1197 * If a recursive load already added a module with the same 1197 * If a recursive load already added a module with the same
1198 * name, abort. 1198 * name, abort.
1199 */ 1199 */
1200 mod2 = module_lookup(mi->mi_name); 1200 mod2 = module_lookup(mi->mi_name);
1201 if (mod2 && mod2 != mod) { 1201 if (mod2 && mod2 != mod) {
1202 module_error("recursive load causes duplicate module `%s'", 1202 module_error("recursive load causes duplicate module `%s'",
1203 mi->mi_name); 1203 mi->mi_name);
1204 error = EEXIST; 1204 error = EEXIST;
1205 goto fail1; 1205 goto fail1;
1206 } 1206 }
1207 1207
1208 /* 1208 /*
1209 * Good, the module loaded successfully. Put it onto the 1209 * Good, the module loaded successfully. Put it onto the
1210 * list and add references to its requisite modules. 1210 * list and add references to its requisite modules.
1211 */ 1211 */
1212 TAILQ_REMOVE(pending, mod, mod_chain); 1212 TAILQ_REMOVE(pending, mod, mod_chain);
1213 module_enqueue(mod); 1213 module_enqueue(mod);
1214 if (modp != NULL) { 1214 if (modp != NULL) {
1215 *modp = mod; 1215 *modp = mod;
1216 } 1216 }
1217 if (autoload && module_autotime > 0) { 1217 if (autoload && module_autotime > 0) {
1218 /* 1218 /*
1219 * Arrange to try unloading the module after 1219 * Arrange to try unloading the module after
1220 * a short delay unless auto-unload is disabled. 1220 * a short delay unless auto-unload is disabled.
1221 */ 1221 */
1222 mod->mod_autotime = time_second + module_autotime; 1222 mod->mod_autotime = time_second + module_autotime;
1223 mod->mod_flags |= MODFLG_AUTO_LOADED; 1223 mod->mod_flags |= MODFLG_AUTO_LOADED;
1224 module_thread_kick(); 1224 module_thread_kick();
1225 } 1225 }
1226 depth--; 1226 depth--;
1227 module_print("module `%s' loaded successfully", mi->mi_name); 1227 module_print("module `%s' loaded successfully", mi->mi_name);
1228 return 0; 1228 return 0;
1229 1229
1230 fail1: 1230 fail1:
1231 (*mi->mi_modcmd)(MODULE_CMD_FINI, NULL); 1231 (*mi->mi_modcmd)(MODULE_CMD_FINI, NULL);
1232 fail: 1232 fail:
1233 kobj_unload(mod->mod_kobj); 1233 kobj_unload(mod->mod_kobj);
1234 fail2: 1234 fail2:
1235 if (filedict != NULL) { 1235 if (filedict != NULL) {
1236 prop_object_release(filedict); 1236 prop_object_release(filedict);
1237 filedict = NULL; 1237 filedict = NULL;
1238 } 1238 }
1239 TAILQ_REMOVE(pending, mod, mod_chain); 1239 TAILQ_REMOVE(pending, mod, mod_chain);
1240 kmem_free(mod, sizeof(*mod)); 1240 kmem_free(mod, sizeof(*mod));
1241 depth--; 1241 depth--;
1242 return error; 1242 return error;
1243} 1243}
1244 1244
1245/* 1245/*
1246 * module_do_unload: 1246 * module_do_unload:
1247 * 1247 *
1248 * Helper routine: do the dirty work of unloading a module. 1248 * Helper routine: do the dirty work of unloading a module.
1249 */ 1249 */
1250static int 1250static int
1251module_do_unload(const char *name, bool load_requires_force) 1251module_do_unload(const char *name, bool load_requires_force)
1252{ 1252{
1253 module_t *mod, *prev_active; 1253 module_t *mod, *prev_active;
1254 int error; 1254 int error;
1255 u_int i; 1255 u_int i;
1256 1256
1257 KASSERT(kernconfig_is_held()); 1257 KASSERT(kernconfig_is_held());
1258 KASSERT(name != NULL); 1258 KASSERT(name != NULL);
1259 1259
1260 module_print("unload requested for '%s' (%s)", name, 1260 module_print("unload requested for '%s' (%s)", name,
1261 load_requires_force ? "TRUE" : "FALSE"); 1261 load_requires_force ? "TRUE" : "FALSE");
1262 mod = module_lookup(name); 1262 mod = module_lookup(name);
1263 if (mod == NULL) { 1263 if (mod == NULL) {
1264 module_error("module `%s' not found", name); 1264 module_error("module `%s' not found", name);
1265 return ENOENT; 1265 return ENOENT;
1266 } 1266 }
1267 if (mod->mod_refcnt != 0) { 1267 if (mod->mod_refcnt != 0) {
1268 module_print("module `%s' busy (%d refs)", name, 1268 module_print("module `%s' busy (%d refs)", name,
1269 mod->mod_refcnt); 1269 mod->mod_refcnt);
1270 return EBUSY; 1270 return EBUSY;
1271 } 1271 }
1272 1272
1273 /* 1273 /*
1274 * Builtin secmodels are there to stay. 1274 * Builtin secmodels are there to stay.
1275 */ 1275 */
1276 if (mod->mod_source == MODULE_SOURCE_KERNEL && 1276 if (mod->mod_source == MODULE_SOURCE_KERNEL &&
1277 mod->mod_info->mi_class == MODULE_CLASS_SECMODEL) { 1277 mod->mod_info->mi_class == MODULE_CLASS_SECMODEL) {
1278 module_print("cannot unload built-in secmodel module `%s'", 1278 module_print("cannot unload built-in secmodel module `%s'",
1279 name); 1279 name);
1280 return EPERM; 1280 return EPERM;
1281 } 1281 }
1282 1282
1283 prev_active = module_active; 1283 prev_active = module_active;
1284 module_active = mod; 1284 module_active = mod;
1285 error = (*mod->mod_info->mi_modcmd)(MODULE_CMD_FINI, NULL); 1285 error = (*mod->mod_info->mi_modcmd)(MODULE_CMD_FINI, NULL);
1286 module_active = prev_active; 1286 module_active = prev_active;
1287 if (error != 0) { 1287 if (error != 0) {
1288 module_print("cannot unload module `%s' error=%d", name, 1288 module_print("cannot unload module `%s' error=%d", name,
1289 error); 1289 error);
1290 return error; 1290 return error;
1291 } 1291 }
1292 module_count--; 1292 module_count--;
1293 TAILQ_REMOVE(&module_list, mod, mod_chain); 1293 TAILQ_REMOVE(&module_list, mod, mod_chain);
1294 for (i = 0; i < mod->mod_nrequired; i++) { 1294 for (i = 0; i < mod->mod_nrequired; i++) {
1295 mod->mod_required[i]->mod_refcnt--; 1295 mod->mod_required[i]->mod_refcnt--;
1296 } 1296 }
1297 module_print("unloaded module `%s'", name); 1297 module_print("unloaded module `%s'", name);
1298 if (mod->mod_kobj != NULL) { 1298 if (mod->mod_kobj != NULL) {
1299 kobj_unload(mod->mod_kobj); 1299 kobj_unload(mod->mod_kobj);
1300 } 1300 }
1301 if (mod->mod_source == MODULE_SOURCE_KERNEL) { 1301 if (mod->mod_source == MODULE_SOURCE_KERNEL) {
1302 mod->mod_nrequired = 0; /* will be re-parsed */ 1302 mod->mod_nrequired = 0; /* will be re-parsed */
1303 if (load_requires_force) 1303 if (load_requires_force)
1304 module_require_force(mod); 1304 module_require_force(mod);
1305 TAILQ_INSERT_TAIL(&module_builtins, mod, mod_chain); 1305 TAILQ_INSERT_TAIL(&module_builtins, mod, mod_chain);
1306 module_builtinlist++; 1306 module_builtinlist++;
1307 } else { 1307 } else {
1308 kmem_free(mod, sizeof(*mod)); 1308 kmem_free(mod, sizeof(*mod));
1309 } 1309 }
1310 module_gen++; 1310 module_gen++;
1311 1311
1312 return 0; 1312 return 0;
1313} 1313}
1314 1314
1315/* 1315/*
1316 * module_prime: 1316 * module_prime:
1317 * 1317 *
1318 * Push a module loaded by the bootloader onto our internal 1318 * Push a module loaded by the bootloader onto our internal
1319 * list. 1319 * list.
1320 */ 1320 */
1321int 1321int
1322module_prime(const char *name, void *base, size_t size) 1322module_prime(const char *name, void *base, size_t size)
1323{ 1323{
1324 __link_set_decl(modules, modinfo_t); 1324 __link_set_decl(modules, modinfo_t);
1325 modinfo_t *const *mip; 1325 modinfo_t *const *mip;
1326 module_t *mod; 1326 module_t *mod;
1327 int error; 1327 int error;
1328 1328
1329 /* Check for module name same as a built-in module */ 1329 /* Check for module name same as a built-in module */
1330 1330
1331 __link_set_foreach(mip, modules) { 1331 __link_set_foreach(mip, modules) {
1332 if (*mip == &module_dummy) 1332 if (*mip == &module_dummy)
1333 continue; 1333 continue;
1334 if (strcmp((*mip)->mi_name, name) == 0) { 1334 if (strcmp((*mip)->mi_name, name) == 0) {
1335 module_error("module `%s' pushed by boot loader " 1335 module_error("module `%s' pushed by boot loader "
1336 "already exists", name); 1336 "already exists", name);
1337 return EEXIST; 1337 return EEXIST;
1338 } 1338 }
1339 } 1339 }
1340 1340
1341 /* Also eliminate duplicate boolist entries */ 1341 /* Also eliminate duplicate boolist entries */
1342 1342
1343 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) { 1343 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) {
1344 if (strcmp(mod->mod_info->mi_name, name) == 0) { 1344 if (strcmp(mod->mod_info->mi_name, name) == 0) {
1345 module_error("duplicate bootlist entry for module " 1345 module_error("duplicate bootlist entry for module "
1346 "`%s'", name); 1346 "`%s'", name);
1347 return EEXIST; 1347 return EEXIST;
1348 } 1348 }
1349 } 1349 }
1350 1350
1351 mod = module_newmodule(MODULE_SOURCE_BOOT); 1351 mod = module_newmodule(MODULE_SOURCE_BOOT);
1352 if (mod == NULL) { 1352 if (mod == NULL) {
1353 return ENOMEM; 1353 return ENOMEM;
1354 } 1354 }
1355 1355
1356 error = kobj_load_mem(&mod->mod_kobj, name, base, size); 1356 error = kobj_load_mem(&mod->mod_kobj, name, base, size);
1357 if (error != 0) { 1357 if (error != 0) {
1358 kmem_free(mod, sizeof(*mod)); 1358 kmem_free(mod, sizeof(*mod));
1359 module_error("unable to load `%s' pushed by boot loader, " 1359 module_error("unable to load `%s' pushed by boot loader, "
1360 "error %d", name, error); 1360 "error %d", name, error);
1361 return error; 1361 return error;
1362 } 1362 }
1363 error = module_fetch_info(mod); 1363 error = module_fetch_info(mod);
1364 if (error != 0) { 1364 if (error != 0) {
1365 kobj_unload(mod->mod_kobj); 1365 kobj_unload(mod->mod_kobj);
1366 kmem_free(mod, sizeof(*mod)); 1366 kmem_free(mod, sizeof(*mod));
1367 module_error("unable to fetch_info for `%s' pushed by boot " 1367 module_error("unable to fetch_info for `%s' pushed by boot "
1368 "loader, error %d", name, error); 1368 "loader, error %d", name, error);
1369 return error; 1369 return error;
1370 } 1370 }
1371 1371
1372 TAILQ_INSERT_TAIL(&module_bootlist, mod, mod_chain); 1372 TAILQ_INSERT_TAIL(&module_bootlist, mod, mod_chain);
1373 1373
1374 return 0; 1374 return 0;
1375} 1375}
1376 1376
1377/* 1377/*
1378 * module_fetch_into: 1378 * module_fetch_into:
1379 * 1379 *
1380 * Fetch modinfo record from a loaded module. 1380 * Fetch modinfo record from a loaded module.
1381 */ 1381 */
1382static int 1382static int
1383module_fetch_info(module_t *mod) 1383module_fetch_info(module_t *mod)
1384{ 1384{
1385 int error; 1385 int error;
1386 void *addr; 1386 void *addr;
1387 size_t size; 1387 size_t size;
1388 1388
1389 /* 1389 /*
1390 * Find module info record and check compatibility. 1390 * Find module info record and check compatibility.
1391 */ 1391 */
1392 error = kobj_find_section(mod->mod_kobj, "link_set_modules", 1392 error = kobj_find_section(mod->mod_kobj, "link_set_modules",
1393 &addr, &size); 1393 &addr, &size);
1394 if (error != 0) { 1394 if (error != 0) {
1395 module_error("`link_set_modules' section not present, " 1395 module_error("`link_set_modules' section not present, "
1396 "error %d", error); 1396 "error %d", error);
1397 return error; 1397 return error;
1398 } 1398 }
1399 if (size != sizeof(modinfo_t **)) { 1399 if (size != sizeof(modinfo_t **)) {
1400 module_error("`link_set_modules' section wrong size %zu != %zu", 1400 module_error("`link_set_modules' section wrong size %zu != %zu",
1401 size, sizeof(modinfo_t **)); 1401 size, sizeof(modinfo_t **));
1402 return ENOEXEC; 1402 return ENOEXEC;
1403 } 1403 }
1404 mod->mod_info = *(modinfo_t **)addr; 1404 mod->mod_info = *(modinfo_t **)addr;
1405 1405
1406 return 0; 1406 return 0;
1407} 1407}
1408 1408
1409/* 1409/*
1410 * module_find_section: 1410 * module_find_section:
1411 * 1411 *
1412 * Allows a module that is being initialized to look up a section 1412 * Allows a module that is being initialized to look up a section
1413 * within its ELF object. 1413 * within its ELF object.
1414 */ 1414 */
1415int 1415int
1416module_find_section(const char *name, void **addr, size_t *size) 1416module_find_section(const char *name, void **addr, size_t *size)
1417{ 1417{
1418 1418
1419 KASSERT(kernconfig_is_held()); 1419 KASSERT(kernconfig_is_held());
1420 KASSERT(module_active != NULL); 1420 KASSERT(module_active != NULL);
1421 1421
1422 return kobj_find_section(module_active->mod_kobj, name, addr, size); 1422 return kobj_find_section(module_active->mod_kobj, name, addr, size);
1423} 1423}
1424 1424
1425/* 1425/*
1426 * module_thread: 1426 * module_thread:
1427 * 1427 *
1428 * Automatically unload modules. We try once to unload autoloaded 1428 * Automatically unload modules. We try once to unload autoloaded
1429 * modules after module_autotime seconds. If the system is under 1429 * modules after module_autotime seconds. If the system is under
1430 * severe memory pressure, we'll try unloading all modules, else if 1430 * severe memory pressure, we'll try unloading all modules, else if
1431 * module_autotime is zero, we don't try to unload, even if the 1431 * module_autotime is zero, we don't try to unload, even if the
1432 * module was previously scheduled for unload. 1432 * module was previously scheduled for unload.
1433 */ 1433 */
1434static void 1434static void
1435module_thread(void *cookie) 1435module_thread(void *cookie)
1436{ 1436{
1437 module_t *mod, *next; 1437 module_t *mod, *next;
1438 modinfo_t *mi; 1438 modinfo_t *mi;
1439 int error; 1439 int error;
1440 1440
1441 for (;;) { 1441 for (;;) {
1442 kernconfig_lock(); 1442 kernconfig_lock();
1443 for (mod = TAILQ_FIRST(&module_list); mod != NULL; mod = next) { 1443 for (mod = TAILQ_FIRST(&module_list); mod != NULL; mod = next) {
1444 next = TAILQ_NEXT(mod, mod_chain); 1444 next = TAILQ_NEXT(mod, mod_chain);
1445 1445
1446 /* skip built-in modules */ 1446 /* skip built-in modules */
1447 if (mod->mod_source == MODULE_SOURCE_KERNEL) 1447 if (mod->mod_source == MODULE_SOURCE_KERNEL)
1448 continue; 1448 continue;
1449 /* skip modules that weren't auto-loaded */ 1449 /* skip modules that weren't auto-loaded */
1450 if ((mod->mod_flags & MODFLG_AUTO_LOADED) == 0) 1450 if ((mod->mod_flags & MODFLG_AUTO_LOADED) == 0)
1451 continue; 1451 continue;
1452 1452
1453 if (uvmexp.free < uvmexp.freemin) { 1453 if (uvmexp.free < uvmexp.freemin) {
1454 module_thread_ticks = hz; 1454 module_thread_ticks = hz;
1455 } else if (module_autotime == 0 || 1455 } else if (module_autotime == 0 ||
1456 mod->mod_autotime == 0) { 1456 mod->mod_autotime == 0) {
1457 continue; 1457 continue;
1458 } else if (time_second < mod->mod_autotime) { 1458 } else if (time_second < mod->mod_autotime) {
1459 module_thread_ticks = hz; 1459 module_thread_ticks = hz;
1460 continue; 1460 continue;
1461 } else { 1461 } else {
1462 mod->mod_autotime = 0; 1462 mod->mod_autotime = 0;
1463 } 1463 }
1464 1464
1465 /* 1465 /*
1466 * If this module wants to avoid autounload then 1466 * If this module wants to avoid autounload then
1467 * skip it. Some modules can ping-pong in and out 1467 * skip it. Some modules can ping-pong in and out
1468 * because their use is transient but often.  1468 * because their use is transient but often.
1469 * Example: exec_script. 1469 * Example: exec_script.
1470 */ 1470 */
1471 mi = mod->mod_info; 1471 mi = mod->mod_info;
1472 error = (*mi->mi_modcmd)(MODULE_CMD_AUTOUNLOAD, NULL); 1472 error = (*mi->mi_modcmd)(MODULE_CMD_AUTOUNLOAD, NULL);
1473 if (error == 0 || error == ENOTTY) { 1473 if (error == 0 || error == ENOTTY) {
1474 (void)module_do_unload(mi->mi_name, false); 1474 (void)module_do_unload(mi->mi_name, false);
1475 } else 1475 } else
1476 module_print("module `%s' declined to be " 1476 module_print("module `%s' declined to be "
1477 "auto-unloaded error=%d", mi->mi_name, 1477 "auto-unloaded error=%d", mi->mi_name,
1478 error); 1478 error);
1479 } 1479 }
1480 kernconfig_unlock(); 1480 kernconfig_unlock();
1481 1481
1482 mutex_enter(&module_thread_lock); 1482 mutex_enter(&module_thread_lock);
1483 (void)cv_timedwait(&module_thread_cv, &module_thread_lock, 1483 (void)cv_timedwait(&module_thread_cv, &module_thread_lock,
1484 module_thread_ticks); 1484 module_thread_ticks);
1485 module_thread_ticks = 0; 1485 module_thread_ticks = 0;
1486 mutex_exit(&module_thread_lock); 1486 mutex_exit(&module_thread_lock);
1487 } 1487 }
1488} 1488}
1489 1489
1490/* 1490/*
1491 * module_thread: 1491 * module_thread:
1492 * 1492 *
1493 * Kick the module thread into action, perhaps because the 1493 * Kick the module thread into action, perhaps because the
1494 * system is low on memory. 1494 * system is low on memory.
1495 */ 1495 */
1496void 1496void
1497module_thread_kick(void) 1497module_thread_kick(void)
1498{ 1498{
1499 1499
1500 mutex_enter(&module_thread_lock); 1500 mutex_enter(&module_thread_lock);
1501 module_thread_ticks = hz; 1501 module_thread_ticks = hz;
1502 cv_broadcast(&module_thread_cv); 1502 cv_broadcast(&module_thread_cv);
1503 mutex_exit(&module_thread_lock); 1503 mutex_exit(&module_thread_lock);
1504} 1504}
1505 1505
1506#ifdef DDB 1506#ifdef DDB
1507/* 1507/*
1508 * module_whatis: 1508 * module_whatis:
1509 * 1509 *
1510 * Helper routine for DDB. 1510 * Helper routine for DDB.
1511 */ 1511 */
1512void 1512void
1513module_whatis(uintptr_t addr, void (*pr)(const char *, ...)) 1513module_whatis(uintptr_t addr, void (*pr)(const char *, ...))
1514{ 1514{
1515 module_t *mod; 1515 module_t *mod;
1516 size_t msize; 1516 size_t msize;
1517 vaddr_t maddr; 1517 vaddr_t maddr;
1518 1518
1519 TAILQ_FOREACH(mod, &module_list, mod_chain) { 1519 TAILQ_FOREACH(mod, &module_list, mod_chain) {
1520 if (mod->mod_kobj == NULL) { 1520 if (mod->mod_kobj == NULL) {
1521 continue; 1521 continue;
1522 } 1522 }
1523 if (kobj_stat(mod->mod_kobj, &maddr, &msize) != 0) 1523 if (kobj_stat(mod->mod_kobj, &maddr, &msize) != 0)
1524 continue; 1524 continue;
1525 if (addr < maddr || addr >= maddr + msize) { 1525 if (addr < maddr || addr >= maddr + msize) {
1526 continue; 1526 continue;
1527 } 1527 }
1528 (*pr)("%p is %p+%zu, in kernel module `%s'\n", 1528 (*pr)("%p is %p+%zu, in kernel module `%s'\n",
1529 (void *)addr, (void *)maddr, 1529 (void *)addr, (void *)maddr,
1530 (size_t)(addr - maddr), mod->mod_info->mi_name); 1530 (size_t)(addr - maddr), mod->mod_info->mi_name);
1531 } 1531 }
1532} 1532}
1533 1533
1534/* 1534/*
1535 * module_print_list: 1535 * module_print_list:
1536 * 1536 *
1537 * Helper routine for DDB. 1537 * Helper routine for DDB.
1538 */ 1538 */
1539void 1539void
1540module_print_list(void (*pr)(const char *, ...)) 1540module_print_list(void (*pr)(const char *, ...))
1541{ 1541{
1542 const char *src; 1542 const char *src;
1543 module_t *mod; 1543 module_t *mod;
1544 size_t msize; 1544 size_t msize;
1545 vaddr_t maddr; 1545 vaddr_t maddr;
1546 1546
1547 (*pr)("%16s %16s %8s %8s\n", "NAME", "TEXT/DATA", "SIZE", "SOURCE"); 1547 (*pr)("%16s %16s %8s %8s\n", "NAME", "TEXT/DATA", "SIZE", "SOURCE");
1548 1548
1549 TAILQ_FOREACH(mod, &module_list, mod_chain) { 1549 TAILQ_FOREACH(mod, &module_list, mod_chain) {
1550 switch (mod->mod_source) { 1550 switch (mod->mod_source) {
1551 case MODULE_SOURCE_KERNEL: 1551 case MODULE_SOURCE_KERNEL:
1552 src = "builtin"; 1552 src = "builtin";
1553 break; 1553 break;
1554 case MODULE_SOURCE_FILESYS: 1554 case MODULE_SOURCE_FILESYS:
1555 src = "filesys"; 1555 src = "filesys";
1556 break; 1556 break;
1557 case MODULE_SOURCE_BOOT: 1557 case MODULE_SOURCE_BOOT:
1558 src = "boot"; 1558 src = "boot";
1559 break; 1559 break;
1560 default: 1560 default:
1561 src = "unknown"; 1561 src = "unknown";
1562 break; 1562 break;
1563 } 1563 }
1564 if (mod->mod_kobj == NULL) { 1564 if (mod->mod_kobj == NULL) {
1565 maddr = 0; 1565 maddr = 0;
1566 msize = 0; 1566 msize = 0;
1567 } else if (kobj_stat(mod->mod_kobj, &maddr, &msize) != 0) 1567 } else if (kobj_stat(mod->mod_kobj, &maddr, &msize) != 0)
1568 continue; 1568 continue;
1569 (*pr)("%16s %16lx %8ld %8s\n", mod->mod_info->mi_name, 1569 (*pr)("%16s %16lx %8ld %8s\n", mod->mod_info->mi_name,
1570 (long)maddr, (long)msize, src); 1570 (long)maddr, (long)msize, src);
1571 } 1571 }
1572} 1572}
1573#endif /* DDB */ 1573#endif /* DDB */
1574 1574
1575static bool 1575static bool
1576module_merge_dicts(prop_dictionary_t existing_dict, 1576module_merge_dicts(prop_dictionary_t existing_dict,
1577 const prop_dictionary_t new_dict) 1577 const prop_dictionary_t new_dict)
1578{ 1578{
1579 prop_dictionary_keysym_t props_keysym; 1579 prop_dictionary_keysym_t props_keysym;
1580 prop_object_iterator_t props_iter; 1580 prop_object_iterator_t props_iter;
1581 prop_object_t props_obj; 1581 prop_object_t props_obj;
1582 const char *props_key; 1582 const char *props_key;
1583 bool error; 1583 bool error;
1584 1584
1585 if (new_dict == NULL) { /* nothing to merge */ 1585 if (new_dict == NULL) { /* nothing to merge */
1586 return true; 1586 return true;
1587 } 1587 }
1588 1588
1589 error = false; 1589 error = false;
1590 props_iter = prop_dictionary_iterator(new_dict); 1590 props_iter = prop_dictionary_iterator(new_dict);
1591 if (props_iter == NULL) { 1591 if (props_iter == NULL) {
1592 return false; 1592 return false;
1593 } 1593 }
1594 1594
1595 while ((props_obj = prop_object_iterator_next(props_iter)) != NULL) { 1595 while ((props_obj = prop_object_iterator_next(props_iter)) != NULL) {
1596 props_keysym = (prop_dictionary_keysym_t)props_obj; 1596 props_keysym = (prop_dictionary_keysym_t)props_obj;
1597 props_key = prop_dictionary_keysym_cstring_nocopy(props_keysym); 1597 props_key = prop_dictionary_keysym_cstring_nocopy(props_keysym);
1598 props_obj = prop_dictionary_get_keysym(new_dict, props_keysym); 1598 props_obj = prop_dictionary_get_keysym(new_dict, props_keysym);
1599 if ((props_obj == NULL) || !prop_dictionary_set(existing_dict, 1599 if ((props_obj == NULL) || !prop_dictionary_set(existing_dict,
1600 props_key, props_obj)) { 1600 props_key, props_obj)) {
1601 error = true; 1601 error = true;
1602 goto out; 1602 goto out;
1603 } 1603 }
1604 } 1604 }
1605 error = false; 1605 error = false;
1606 1606
1607out: 1607out:
1608 prop_object_iterator_release(props_iter); 1608 prop_object_iterator_release(props_iter);
1609 1609
1610 return !error; 1610 return !error;
1611} 1611}

cvs diff -r1.23.2.2 -r1.23.2.3 src/sys/kern/sys_module.c (switch to unified diff)

--- src/sys/kern/sys_module.c 2018/03/11 07:25:59 1.23.2.2
+++ src/sys/kern/sys_module.c 2018/03/11 08:32:21 1.23.2.3
@@ -1,276 +1,276 @@ @@ -1,276 +1,276 @@
1/* $NetBSD: sys_module.c,v 1.23.2.2 2018/03/11 07:25:59 pgoyette Exp $ */ 1/* $NetBSD: sys_module.c,v 1.23.2.3 2018/03/11 08:32:21 pgoyette Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * System calls relating to loadable modules. 30 * System calls relating to loadable modules.
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: sys_module.c,v 1.23.2.2 2018/03/11 07:25:59 pgoyette Exp $"); 34__KERNEL_RCSID(0, "$NetBSD: sys_module.c,v 1.23.2.3 2018/03/11 08:32:21 pgoyette Exp $");
35 35
36#ifdef _KERNEL_OPT 36#ifdef _KERNEL_OPT
37#include "opt_modular.h" 37#include "opt_modular.h"
38#endif 38#endif
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/systm.h> 41#include <sys/systm.h>
42#include <sys/proc.h> 42#include <sys/proc.h>
43#include <sys/namei.h> 43#include <sys/namei.h>
44#include <sys/kauth.h> 44#include <sys/kauth.h>
45#include <sys/kmem.h> 45#include <sys/kmem.h>
46#include <sys/kobj.h> 46#include <sys/kobj.h>
47#include <sys/module.h> 47#include <sys/module.h>
48#include <sys/syscall.h> 48#include <sys/syscall.h>
49#include <sys/syscallargs.h> 49#include <sys/syscallargs.h>
50 50
51/* 51/*
52 * Arbitrary limit to avoid DoS for excessive memory allocation. 52 * Arbitrary limit to avoid DoS for excessive memory allocation.
53 */ 53 */
54#define MAXPROPSLEN 4096 54#define MAXPROPSLEN 4096
55 55
56int 56int
57handle_modctl_load(const char *ml_filename, int ml_flags, const char *ml_props, 57handle_modctl_load(const char *ml_filename, int ml_flags, const char *ml_props,
58 size_t ml_propslen) 58 size_t ml_propslen)
59{ 59{
60 char *path; 60 char *path;
61 char *props; 61 char *props;
62 int error; 62 int error;
63 prop_dictionary_t dict; 63 prop_dictionary_t dict;
64 size_t propslen = 0; 64 size_t propslen = 0;
65 65
66 if ((ml_props != NULL && ml_propslen == 0) || 66 if ((ml_props != NULL && ml_propslen == 0) ||
67 (ml_props == NULL && ml_propslen > 0)) { 67 (ml_props == NULL && ml_propslen > 0)) {
68 return EINVAL; 68 return EINVAL;
69 } 69 }
70 70
71 path = PNBUF_GET(); 71 path = PNBUF_GET();
72 error = copyinstr(ml_filename, path, MAXPATHLEN, NULL); 72 error = copyinstr(ml_filename, path, MAXPATHLEN, NULL);
73 if (error != 0) 73 if (error != 0)
74 goto out1; 74 goto out1;
75 75
76 if (ml_props != NULL) { 76 if (ml_props != NULL) {
77 if (ml_propslen > MAXPROPSLEN) { 77 if (ml_propslen > MAXPROPSLEN) {
78 error = ENOMEM; 78 error = ENOMEM;
79 goto out1; 79 goto out1;
80 } 80 }
81 propslen = ml_propslen + 1; 81 propslen = ml_propslen + 1;
82 82
83 props = kmem_alloc(propslen, KM_SLEEP); 83 props = kmem_alloc(propslen, KM_SLEEP);
84 error = copyinstr(ml_props, props, propslen, NULL); 84 error = copyinstr(ml_props, props, propslen, NULL);
85 if (error != 0) 85 if (error != 0)
86 goto out2; 86 goto out2;
87 87
88 dict = prop_dictionary_internalize(props); 88 dict = prop_dictionary_internalize(props);
89 if (dict == NULL) { 89 if (dict == NULL) {
90 error = EINVAL; 90 error = EINVAL;
91 goto out2; 91 goto out2;
92 } 92 }
93 } else { 93 } else {
94 dict = NULL; 94 dict = NULL;
95 props = NULL; 95 props = NULL;
96 } 96 }
97 97
98 error = module_load(path, ml_flags, dict, MODULE_CLASS_ANY); 98 error = module_load(path, ml_flags, dict, MODULE_CLASS_ANY);
99 99
100 if (dict != NULL) { 100 if (dict != NULL) {
101 prop_object_release(dict); 101 prop_object_release(dict);
102 } 102 }
103 103
104out2: 104out2:
105 if (props != NULL) { 105 if (props != NULL) {
106 kmem_free(props, propslen); 106 kmem_free(props, propslen);
107 } 107 }
108out1: 108out1:
109 PNBUF_PUT(path); 109 PNBUF_PUT(path);
110 return error; 110 return error;
111} 111}
112 112
113static int 113static int
114handle_modctl_stat(struct iovec *iov, void *arg) 114handle_modctl_stat(struct iovec *iov, void *arg)
115{ 115{
116 modstat_t *ms, *mso; 116 modstat_t *ms, *mso;
117 modinfo_t *mi; 117 modinfo_t *mi;
118 module_t *mod; 118 module_t *mod;
119 vaddr_t addr; 119 vaddr_t addr;
120 size_t size; 120 size_t size;
121 size_t mslen; 121 size_t mslen;
122 int error; 122 int error;
123 int mscnt; 123 int mscnt;
124 bool stataddr; 124 bool stataddr;
125 const char * const aliasp[]; 125 const char * const *aliasp;
126 126
127 /* If not privileged, don't expose kernel addresses. */ 127 /* If not privileged, don't expose kernel addresses. */
128 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE, 128 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
129 0, (void *)(uintptr_t)MODCTL_STAT, NULL, NULL); 129 0, (void *)(uintptr_t)MODCTL_STAT, NULL, NULL);
130 stataddr = (error == 0); 130 stataddr = (error == 0);
131 131
132 kernconfig_lock(); 132 kernconfig_lock();
133 mscnt = 0; 133 mscnt = 0;
134 TAILQ_FOREACH(mod, &module_list, mod_chain) { 134 TAILQ_FOREACH(mod, &module_list, mod_chain) {
135 mscnt++; 135 mscnt++;
136 mi = mod->mod_info; 136 mi = mod->mod_info;
137 if ((aliasp = *mi->mi_aliases) != NULL) { 137 if ((aliasp = *mi->mi_aliases) != NULL) {
138 while (*aliasp++ != NULL) 138 while (*aliasp++ != NULL)
139 mslen++; 139 mslen++;
140 } 140 }
141 } 141 }
142 mslen = (mscnt+module_builtinlist+1) * sizeof(modstat_t); 142 mslen = (mscnt+module_builtinlist+1) * sizeof(modstat_t);
143 mso = kmem_zalloc(mslen, KM_SLEEP); 143 mso = kmem_zalloc(mslen, KM_SLEEP);
144 ms = mso; 144 ms = mso;
145 TAILQ_FOREACH(mod, &module_list, mod_chain) { 145 TAILQ_FOREACH(mod, &module_list, mod_chain) {
146 mi = mod->mod_info; 146 mi = mod->mod_info;
147 strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name)); 147 strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name));
148 if (mi->mi_required != NULL) { 148 if (mi->mi_required != NULL) {
149 strlcpy(ms->ms_required, mi->mi_required, 149 strlcpy(ms->ms_required, mi->mi_required,
150 sizeof(ms->ms_required)); 150 sizeof(ms->ms_required));
151 } 151 }
152 if (mod->mod_kobj != NULL && stataddr) { 152 if (mod->mod_kobj != NULL && stataddr) {
153 kobj_stat(mod->mod_kobj, &addr, &size); 153 kobj_stat(mod->mod_kobj, &addr, &size);
154 ms->ms_addr = addr; 154 ms->ms_addr = addr;
155 ms->ms_size = size; 155 ms->ms_size = size;
156 } 156 }
157 ms->ms_class = mi->mi_class; 157 ms->ms_class = mi->mi_class;
158 ms->ms_refcnt = mod->mod_refcnt; 158 ms->ms_refcnt = mod->mod_refcnt;
159 ms->ms_source = mod->mod_source; 159 ms->ms_source = mod->mod_source;
160 ms->ms_flags = mod->mod_flags; 160 ms->ms_flags = mod->mod_flags;
161 ms++; 161 ms++;
162 aliasp = *mi->mi_aliases; 162 aliasp = *mi->mi_aliases;
163 if (aliasp == NULL) 163 if (aliasp == NULL)
164 continue; 164 continue;
165 while (*aliasp) { 165 while (*aliasp) {
166 strlcpy(ms->ms_name, *aliasp, sizeof(ms->ms_name)); 166 strlcpy(ms->ms_name, *aliasp, sizeof(ms->ms_name));
167 strlcpy(ms->ms_required, mi->mi_name, 167 strlcpy(ms->ms_required, mi->mi_name,
168 sizeof(ms->ms_required)); 168 sizeof(ms->ms_required));
169 ms->ms_class = mi->mi_class; 169 ms->ms_class = mi->mi_class;
170 ms->ms_source = mod->mod_source; 170 ms->ms_source = mod->mod_source;
171 ms->ms_flags = mod->mod_flags | MODFLG_IS_ALIAS; 171 ms->ms_flags = mod->mod_flags | MODFLG_IS_ALIAS;
172 aliasp++; 172 aliasp++;
173 ms++; 173 ms++;
174 } 174 }
175 } 175 }
176 TAILQ_FOREACH(mod, &module_builtins, mod_chain) { 176 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
177 mi = mod->mod_info; 177 mi = mod->mod_info;
178 strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name)); 178 strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name));
179 if (mi->mi_required != NULL) { 179 if (mi->mi_required != NULL) {
180 strlcpy(ms->ms_required, mi->mi_required, 180 strlcpy(ms->ms_required, mi->mi_required,
181 sizeof(ms->ms_required)); 181 sizeof(ms->ms_required));
182 } 182 }
183 if (mod->mod_kobj != NULL && stataddr) { 183 if (mod->mod_kobj != NULL && stataddr) {
184 kobj_stat(mod->mod_kobj, &addr, &size); 184 kobj_stat(mod->mod_kobj, &addr, &size);
185 ms->ms_addr = addr; 185 ms->ms_addr = addr;
186 ms->ms_size = size; 186 ms->ms_size = size;
187 } 187 }
188 ms->ms_class = mi->mi_class; 188 ms->ms_class = mi->mi_class;
189 ms->ms_refcnt = -1; 189 ms->ms_refcnt = -1;
190 KASSERT(mod->mod_source == MODULE_SOURCE_KERNEL); 190 KASSERT(mod->mod_source == MODULE_SOURCE_KERNEL);
191 ms->ms_source = mod->mod_source; 191 ms->ms_source = mod->mod_source;
192 ms++; 192 ms++;
193 } 193 }
194 kernconfig_unlock(); 194 kernconfig_unlock();
195 error = copyout(mso, iov->iov_base, 195 error = copyout(mso, iov->iov_base,
196 min(mslen - sizeof(modstat_t), iov->iov_len)); 196 min(mslen - sizeof(modstat_t), iov->iov_len));
197 kmem_free(mso, mslen); 197 kmem_free(mso, mslen);
198 if (error == 0) { 198 if (error == 0) {
199 iov->iov_len = mslen - sizeof(modstat_t); 199 iov->iov_len = mslen - sizeof(modstat_t);
200 error = copyout(iov, arg, sizeof(*iov)); 200 error = copyout(iov, arg, sizeof(*iov));
201 } 201 }
202 202
203 return error; 203 return error;
204} 204}
205 205
206int 206int
207sys_modctl(struct lwp *l, const struct sys_modctl_args *uap, 207sys_modctl(struct lwp *l, const struct sys_modctl_args *uap,
208 register_t *retval) 208 register_t *retval)
209{ 209{
210 /* { 210 /* {
211 syscallarg(int) cmd; 211 syscallarg(int) cmd;
212 syscallarg(void *) arg; 212 syscallarg(void *) arg;
213 } */ 213 } */
214 char buf[MAXMODNAME]; 214 char buf[MAXMODNAME];
215 struct iovec iov; 215 struct iovec iov;
216 modctl_load_t ml; 216 modctl_load_t ml;
217 int error; 217 int error;
218 void *arg; 218 void *arg;
219#ifdef MODULAR 219#ifdef MODULAR
220 uintptr_t loadtype; 220 uintptr_t loadtype;
221#endif 221#endif
222 222
223 arg = SCARG(uap, arg); 223 arg = SCARG(uap, arg);
224 224
225 switch (SCARG(uap, cmd)) { 225 switch (SCARG(uap, cmd)) {
226 case MODCTL_LOAD: 226 case MODCTL_LOAD:
227 error = copyin(arg, &ml, sizeof(ml)); 227 error = copyin(arg, &ml, sizeof(ml));
228 if (error != 0) 228 if (error != 0)
229 break; 229 break;
230 error = handle_modctl_load(ml.ml_filename, ml.ml_flags, 230 error = handle_modctl_load(ml.ml_filename, ml.ml_flags,
231 ml.ml_props, ml.ml_propslen); 231 ml.ml_props, ml.ml_propslen);
232 break; 232 break;
233 233
234 case MODCTL_UNLOAD: 234 case MODCTL_UNLOAD:
235 error = copyinstr(arg, buf, sizeof(buf), NULL); 235 error = copyinstr(arg, buf, sizeof(buf), NULL);
236 if (error == 0) { 236 if (error == 0) {
237 error = module_unload(buf); 237 error = module_unload(buf);
238 } 238 }
239 break; 239 break;
240 240
241 case MODCTL_STAT: 241 case MODCTL_STAT:
242 error = copyin(arg, &iov, sizeof(iov)); 242 error = copyin(arg, &iov, sizeof(iov));
243 if (error != 0) { 243 if (error != 0) {
244 break; 244 break;
245 } 245 }
246 error = handle_modctl_stat(&iov, arg); 246 error = handle_modctl_stat(&iov, arg);
247 break; 247 break;
248 248
249 case MODCTL_EXISTS: 249 case MODCTL_EXISTS:
250#ifndef MODULAR 250#ifndef MODULAR
251 error = ENOSYS; 251 error = ENOSYS;
252#else 252#else
253 loadtype = (uintptr_t)arg; 253 loadtype = (uintptr_t)arg;
254 switch (loadtype) { /* 0 = modload, 1 = autoload */ 254 switch (loadtype) { /* 0 = modload, 1 = autoload */
255 case 0: /* FALLTHROUGH */ 255 case 0: /* FALLTHROUGH */
256 case 1: 256 case 1:
257 error = kauth_authorize_system(kauth_cred_get(), 257 error = kauth_authorize_system(kauth_cred_get(),
258 KAUTH_SYSTEM_MODULE, 0, 258 KAUTH_SYSTEM_MODULE, 0,
259 (void *)(uintptr_t)MODCTL_LOAD, 259 (void *)(uintptr_t)MODCTL_LOAD,
260 (void *)loadtype, NULL); 260 (void *)loadtype, NULL);
261 break; 261 break;
262 262
263 default: 263 default:
264 error = EINVAL; 264 error = EINVAL;
265 break; 265 break;
266 } 266 }
267#endif 267#endif
268 break; 268 break;
269 269
270 default: 270 default:
271 error = EINVAL; 271 error = EINVAL;
272 break; 272 break;
273 } 273 }
274 274
275 return error; 275 return error;
276} 276}