Ensure that circular dependencies do not panic the machine by doubly

locking the same file. Remove the special self-dependant case previously
introduced, as the general case handles it properly.
This commit is contained in:
rumble 2008-01-19 00:57:35 +00:00
parent 9df302c742
commit 8a7c44d074

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_module.c,v 1.6 2008/01/18 16:41:46 rumble Exp $ */
/* $NetBSD: kern_module.c,v 1.7 2008/01/19 00:57:35 rumble Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.6 2008/01/18 16:41:46 rumble Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.7 2008/01/19 00:57:35 rumble Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -388,6 +388,7 @@ module_do_load(const char *filename, bool isdep, bool force, module_t **modp)
int error;
size_t len;
u_int i;
bool closed = false;
KASSERT(mutex_owned(&module_lock));
@ -429,8 +430,9 @@ module_do_load(const char *filename, bool isdep, bool force, module_t **modp)
return error;
}
error = kobj_load(mod->mod_kobj);
if (error != 0)
if (error != 0) {
module_error("unable to load kernel object");
}
mod->mod_source = MODULE_SOURCE_FILESYS;
}
TAILQ_INSERT_TAIL(&pending, mod, mod_chain);
@ -505,6 +507,14 @@ module_do_load(const char *filename, bool isdep, bool force, module_t **modp)
goto fail;
}
/*
* Close the kobj before handling dependencies since we're done
* with it and don't want to open an already locked file if a
* circular dependency exists.
*/
kobj_close(mod->mod_kobj);
closed = true;
/*
* Now try to load any requisite modules.
*/
@ -555,7 +565,8 @@ module_do_load(const char *filename, bool isdep, bool force, module_t **modp)
* list and add references to its requisite modules.
*/
module_count++;
kobj_close(mod->mod_kobj);
if (!closed)
kobj_close(mod->mod_kobj);
TAILQ_REMOVE(&pending, mod, mod_chain);
TAILQ_INSERT_TAIL(&module_list, mod, mod_chain);
for (i = 0; i < mod->mod_nrequired; i++) {
@ -567,8 +578,10 @@ module_do_load(const char *filename, bool isdep, bool force, module_t **modp)
}
depth--;
return 0;
fail:
kobj_close(mod->mod_kobj);
if (!closed)
kobj_close(mod->mod_kobj);
TAILQ_REMOVE(&pending, mod, mod_chain);
kobj_unload(mod->mod_kobj);
kmem_free(mod, sizeof(*mod));