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
This commit is contained in:
Mark Johnston
2025-11-26 18:15:48 +00:00
parent 5f529f9e29
commit 72b114169b
+8 -7
View File
@@ -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;