aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2025-11-26 18:15:48 +0000
committerMark Johnston <markj@FreeBSD.org>2025-12-01 14:19:18 +0000
commit72b114169bd56ec157d746a2df87b3a4617065b3 (patch)
treea53e2759f290bfe315ce01a6bc1bdfbefd547c4f
parent5f529f9e292a30c065c316ed5fd0d23e07b26e5c (diff)
linker: Avoid invoking eventhandlers on incompletely loaded files
We do not invoke the kld_load eventhandler until after the file is fully linked, so don't invoke the kld_unload_try or kld_unload event handlers unless the file is fully linked either. In my case, the dtrace SDT kld_unload_try handler was running before relocations were processed against the file, and that caused problems when sdt_kld_unload_probes() accesses elements of a linker set. Move the kld_unload handler invocation earlier, to after sysuninits have been run. This is a bit more consistent with the kld_load handler. PR: 291238 Reviewed by: imp, emaste, kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D53938
-rw-r--r--sys/kern/kern_linker.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index e2f63cbc0c5a..9559b5233a3e 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -703,9 +703,11 @@ linker_file_unload(linker_file_t file, int flags)
/* Give eventhandlers a chance to prevent the unload. */
error = 0;
- EVENTHANDLER_INVOKE(kld_unload_try, file, &error);
- if (error != 0)
- return (EBUSY);
+ if ((file->flags & LINKER_FILE_LINKED) != 0) {
+ EVENTHANDLER_INVOKE(kld_unload_try, file, &error);
+ if (error != 0)
+ return (EBUSY);
+ }
KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
" informing modules\n"));
@@ -768,10 +770,12 @@ linker_file_unload(linker_file_t file, int flags)
* Don't try to run SYSUNINITs if we are unloaded due to a
* link error.
*/
- if (file->flags & LINKER_FILE_LINKED) {
+ if ((file->flags & LINKER_FILE_LINKED) != 0) {
file->flags &= ~LINKER_FILE_LINKED;
linker_file_unregister_sysctls(file);
linker_file_sysuninit(file);
+ EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address,
+ file->size);
}
TAILQ_REMOVE(&linker_files, file, link);
@@ -788,9 +792,6 @@ linker_file_unload(linker_file_t file, int flags)
LINKER_UNLOAD(file);
- EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address,
- file->size);
-
if (file->filename) {
free(file->filename, M_LINKER);
file->filename = NULL;