summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_linker.c
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2011-01-05 09:58:41 +0000
committertrasz <trasz@FreeBSD.org>2011-01-05 09:58:41 +0000
commitaf6310a6666a5a9f5af85c7e784288791a6cbcd6 (patch)
treebe6970d17db17c3a0254911d71da2c677ec33039 /sys/kern/kern_linker.c
parent6b3c290093dd0d06e55cf974c1f7a721e5d9afb4 (diff)
downloadFreeBSD-src-af6310a6666a5a9f5af85c7e784288791a6cbcd6.zip
FreeBSD-src-af6310a6666a5a9f5af85c7e784288791a6cbcd6.tar.gz
Fix page fault that occurred when trying to initialize preloaded kernel module,
the dependency of which was preloaded, but failed to initialize. Previously, kernel dereferenced NULL pointer returned by modlist_lookup2(); now, when this happens, we unload the dependent module. Since the depended_files list is sorted in dependency order, this properly propagates, unloading modules that depend on failed ones. From the user point of view, this prevents the kernel from panicing when trying to boot kernel compiled without KDTRACE_HOOKS with dtraceall_load="YES" in /boot/loader.conf. Reviewed by: kib
Diffstat (limited to 'sys/kern/kern_linker.c')
-rw-r--r--sys/kern/kern_linker.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index 43ccd74..394e0e4 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -1584,6 +1584,12 @@ restart:
modname = mp->md_cval;
verinfo = mp->md_data;
mod = modlist_lookup2(modname, verinfo);
+ if (mod == NULL) {
+ printf("KLD file %s - cannot find "
+ "dependency \"%s\"\n",
+ lf->filename, modname);
+ goto fail;
+ }
/* Don't count self-dependencies */
if (lf == mod->container)
continue;
@@ -1600,11 +1606,9 @@ restart:
*/
error = LINKER_LINK_PRELOAD_FINISH(lf);
if (error) {
- TAILQ_REMOVE(&depended_files, lf, loaded);
printf("KLD file %s - could not finalize loading\n",
lf->filename);
- linker_file_unload(lf, LINKER_UNLOAD_FORCE);
- continue;
+ goto fail;
}
linker_file_register_modules(lf);
if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
@@ -1612,6 +1616,10 @@ restart:
sysinit_add(si_start, si_stop);
linker_file_register_sysctls(lf);
lf->flags |= LINKER_FILE_LINKED;
+ continue;
+fail:
+ TAILQ_REMOVE(&depended_files, lf, loaded);
+ linker_file_unload(lf, LINKER_UNLOAD_FORCE);
}
/* woohoo! we made it! */
}
OpenPOWER on IntegriCloud