mirror of
https://github.com/freebsd/freebsd-src
synced 2024-07-22 10:48:02 +00:00
kern linker: Don't invoke dtors without having invoked ctors
I have a kernel module which fails to load because of an unrecognized
relocation type. link_elf_load_file() fails before the module's ctors
are invoked and it calls linker_file_unload(), which causes the module's
dtors to be executed, resulting in a kernel panic.
Add a flag to the linker file to ensure that dtors are not invoked if
unloading due to an error prior to ctors being invoked.
At the moment I only implemented this for link_elf_obj.c since
link_elf.c doesn't invoke dtors, but I refactored link_elf.c to make
them more similar.
Fixes: 9e575fadf4
("link_elf_obj: Invoke fini callbacks")
Reviewed by: zlei, kib
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D44559
This commit is contained in:
parent
43b4da4411
commit
7ef5c19b21
|
@ -657,6 +657,7 @@ linker_make_file(const char *pathname, linker_class_t lc)
|
|||
return (NULL);
|
||||
lf->ctors_addr = 0;
|
||||
lf->ctors_size = 0;
|
||||
lf->ctors_invoked = LF_NONE;
|
||||
lf->dtors_addr = 0;
|
||||
lf->dtors_size = 0;
|
||||
lf->refs = 1;
|
||||
|
|
|
@ -358,7 +358,7 @@ link_elf_error(const char *filename, const char *s)
|
|||
}
|
||||
|
||||
static void
|
||||
link_elf_invoke_ctors(caddr_t addr, size_t size)
|
||||
link_elf_invoke_cbs(caddr_t addr, size_t size)
|
||||
{
|
||||
void (**ctor)(void);
|
||||
size_t i, cnt;
|
||||
|
@ -373,6 +373,17 @@ link_elf_invoke_ctors(caddr_t addr, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
link_elf_invoke_ctors(linker_file_t lf)
|
||||
{
|
||||
KASSERT(lf->ctors_invoked == LF_NONE,
|
||||
("%s: file %s ctor state %d",
|
||||
__func__, lf->filename, lf->ctors_invoked));
|
||||
|
||||
link_elf_invoke_cbs(lf->ctors_addr, lf->ctors_size);
|
||||
lf->ctors_invoked = LF_CTORS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Actions performed after linking/loading both the preloaded kernel and any
|
||||
* modules; whether preloaded or dynamicly loaded.
|
||||
|
@ -403,7 +414,7 @@ link_elf_link_common_finish(linker_file_t lf)
|
|||
#endif
|
||||
|
||||
/* Invoke .ctors */
|
||||
link_elf_invoke_ctors(lf->ctors_addr, lf->ctors_size);
|
||||
link_elf_invoke_ctors(lf);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -658,6 +658,30 @@ link_elf_invoke_cbs(caddr_t addr, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
link_elf_invoke_ctors(linker_file_t lf)
|
||||
{
|
||||
KASSERT(lf->ctors_invoked == LF_NONE,
|
||||
("%s: file %s ctor state %d",
|
||||
__func__, lf->filename, lf->ctors_invoked));
|
||||
|
||||
link_elf_invoke_cbs(lf->ctors_addr, lf->ctors_size);
|
||||
lf->ctors_invoked = LF_CTORS;
|
||||
}
|
||||
|
||||
static void
|
||||
link_elf_invoke_dtors(linker_file_t lf)
|
||||
{
|
||||
KASSERT(lf->ctors_invoked != LF_DTORS,
|
||||
("%s: file %s ctor state %d",
|
||||
__func__, lf->filename, lf->ctors_invoked));
|
||||
|
||||
if (lf->ctors_invoked == LF_CTORS) {
|
||||
link_elf_invoke_cbs(lf->dtors_addr, lf->dtors_size);
|
||||
lf->ctors_invoked = LF_DTORS;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
link_elf_link_preload_finish(linker_file_t lf)
|
||||
{
|
||||
|
@ -684,7 +708,7 @@ link_elf_link_preload_finish(linker_file_t lf)
|
|||
/* Apply protections now that relocation processing is complete. */
|
||||
link_elf_protect(ef);
|
||||
|
||||
link_elf_invoke_cbs(lf->ctors_addr, lf->ctors_size);
|
||||
link_elf_invoke_ctors(lf);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1263,7 @@ link_elf_load_file(linker_class_t cls, const char *filename,
|
|||
#endif
|
||||
|
||||
link_elf_protect(ef);
|
||||
link_elf_invoke_cbs(lf->ctors_addr, lf->ctors_size);
|
||||
link_elf_invoke_ctors(lf);
|
||||
*result = lf;
|
||||
|
||||
out:
|
||||
|
@ -1259,7 +1283,7 @@ link_elf_unload_file(linker_file_t file)
|
|||
elf_file_t ef = (elf_file_t) file;
|
||||
u_int i;
|
||||
|
||||
link_elf_invoke_cbs(file->dtors_addr, file->dtors_size);
|
||||
link_elf_invoke_dtors(file);
|
||||
|
||||
/* Notify MD code that a module is being unloaded. */
|
||||
elf_cpu_unload_file(file);
|
||||
|
|
|
@ -82,6 +82,11 @@ struct linker_file {
|
|||
size_t size; /* size of file */
|
||||
caddr_t ctors_addr; /* address of .ctors/.init_array */
|
||||
size_t ctors_size; /* size of .ctors/.init_array */
|
||||
enum {
|
||||
LF_NONE = 0,
|
||||
LF_CTORS,
|
||||
LF_DTORS,
|
||||
} ctors_invoked; /* have we run ctors yet? */
|
||||
caddr_t dtors_addr; /* address of .dtors/.fini_array */
|
||||
size_t dtors_size; /* size of .dtors/.fini_array */
|
||||
int ndeps; /* number of dependencies */
|
||||
|
|
Loading…
Reference in a new issue