link_elf_obj: Invoke fini callbacks
This is required for KASAN: when a module is unloaded, poisoned regions (e.g., pad areas between global variables) are left as such, so if they are reused as KLDs are loaded, false positives can arise. Reported by: pho, Jenkins Reviewed by: kib MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D31339
This commit is contained in:
parent
98bfb9dac2
commit
9e575fadf4
@ -613,6 +613,8 @@ linker_make_file(const char *pathname, linker_class_t lc)
|
||||
return (NULL);
|
||||
lf->ctors_addr = 0;
|
||||
lf->ctors_size = 0;
|
||||
lf->dtors_addr = 0;
|
||||
lf->dtors_size = 0;
|
||||
lf->refs = 1;
|
||||
lf->userrefs = 0;
|
||||
lf->flags = 0;
|
||||
|
@ -544,6 +544,17 @@ link_elf_link_preload(linker_class_t cls, const char *filename,
|
||||
lf->ctors_addr = ef->progtab[pb].addr;
|
||||
lf->ctors_size = shdr[i].sh_size;
|
||||
}
|
||||
} else if ((ef->progtab[pb].name != NULL &&
|
||||
strcmp(ef->progtab[pb].name, ".dtors") == 0) ||
|
||||
shdr[i].sh_type == SHT_FINI_ARRAY) {
|
||||
if (lf->dtors_addr != 0) {
|
||||
printf(
|
||||
"%s: multiple dtor sections in %s\n",
|
||||
__func__, filename);
|
||||
} else {
|
||||
lf->dtors_addr = ef->progtab[pb].addr;
|
||||
lf->dtors_size = shdr[i].sh_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update all symbol values with the offset. */
|
||||
@ -612,7 +623,7 @@ link_elf_link_preload(linker_class_t cls, const char *filename,
|
||||
}
|
||||
|
||||
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;
|
||||
@ -653,7 +664,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_ctors(lf->ctors_addr, lf->ctors_size);
|
||||
link_elf_invoke_cbs(lf->ctors_addr, lf->ctors_size);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1012,6 +1023,19 @@ link_elf_load_file(linker_class_t cls, const char *filename,
|
||||
lf->ctors_size =
|
||||
shdr[i].sh_size;
|
||||
}
|
||||
} else if (!strcmp(ef->progtab[pb].name,
|
||||
".dtors") ||
|
||||
shdr[i].sh_type == SHT_FINI_ARRAY) {
|
||||
if (lf->dtors_addr != 0) {
|
||||
printf(
|
||||
"%s: multiple dtor sections in %s\n",
|
||||
__func__, filename);
|
||||
} else {
|
||||
lf->dtors_addr =
|
||||
(caddr_t)mapbase;
|
||||
lf->dtors_size =
|
||||
shdr[i].sh_size;
|
||||
}
|
||||
}
|
||||
} else if (shdr[i].sh_type == SHT_PROGBITS)
|
||||
ef->progtab[pb].name = "<<PROGBITS>>";
|
||||
@ -1196,7 +1220,7 @@ link_elf_load_file(linker_class_t cls, const char *filename,
|
||||
#endif
|
||||
|
||||
link_elf_protect(ef);
|
||||
link_elf_invoke_ctors(lf->ctors_addr, lf->ctors_size);
|
||||
link_elf_invoke_cbs(lf->ctors_addr, lf->ctors_size);
|
||||
*result = lf;
|
||||
|
||||
out:
|
||||
@ -1216,6 +1240,8 @@ 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);
|
||||
|
||||
/* Notify MD code that a module is being unloaded. */
|
||||
elf_cpu_unload_file(file);
|
||||
|
||||
|
@ -82,8 +82,10 @@ struct linker_file {
|
||||
int id; /* unique id */
|
||||
caddr_t address; /* load address */
|
||||
size_t size; /* size of file */
|
||||
caddr_t ctors_addr; /* address of .ctors */
|
||||
size_t ctors_size; /* size of .ctors */
|
||||
caddr_t ctors_addr; /* address of .ctors/.init_array */
|
||||
size_t ctors_size; /* size of .ctors/.init_array */
|
||||
caddr_t dtors_addr; /* address of .dtors/.fini_array */
|
||||
size_t dtors_size; /* size of .dtors/.fini_array */
|
||||
int ndeps; /* number of dependencies */
|
||||
linker_file_t* deps; /* list of dependencies */
|
||||
STAILQ_HEAD(, common_symbol) common; /* list of common symbols */
|
||||
|
Loading…
Reference in New Issue
Block a user