Convert all panics from the link_elf_obj kernel linker for object
files format into printfs and errors to caller. Some leaks of resources are there, but the same leaks are present in other error pathes. With the change, the kernel at least boots even when module with unexpected or corrupted ELF structure is preloaded. Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
This commit is contained in:
parent
5e67bb7b19
commit
3cfce8e4df
@ -140,7 +140,7 @@ static int link_elf_each_function_name(linker_file_t,
|
||||
static int link_elf_each_function_nameval(linker_file_t,
|
||||
linker_function_nameval_callback_t,
|
||||
void *);
|
||||
static void link_elf_reloc_local(linker_file_t);
|
||||
static int link_elf_reloc_local(linker_file_t);
|
||||
static long link_elf_symtab_get(linker_file_t, const Elf_Sym **);
|
||||
static long link_elf_strtab_get(linker_file_t, caddr_t *);
|
||||
|
||||
@ -405,15 +405,26 @@ link_elf_link_preload(linker_class_t cls, const char *filename,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pb != ef->nprogtab)
|
||||
panic("lost progbits");
|
||||
if (rl != ef->nreltab)
|
||||
panic("lost reltab");
|
||||
if (ra != ef->nrelatab)
|
||||
panic("lost relatab");
|
||||
if (pb != ef->nprogtab) {
|
||||
printf("%s: lost progbits\n", filename);
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (rl != ef->nreltab) {
|
||||
printf("%s: lost reltab\n", filename);
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (ra != ef->nrelatab) {
|
||||
printf("%s: lost relatab\n", filename);
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Local intra-module relocations */
|
||||
link_elf_reloc_local(lf);
|
||||
error = link_elf_reloc_local(lf);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
|
||||
*result = lf;
|
||||
return (0);
|
||||
@ -634,8 +645,11 @@ link_elf_load_file(linker_class_t cls, const char *filename,
|
||||
ef->relatab = malloc(ef->nrelatab * sizeof(*ef->relatab),
|
||||
M_LINKER, M_WAITOK | M_ZERO);
|
||||
|
||||
if (symtabindex == -1)
|
||||
panic("lost symbol table index");
|
||||
if (symtabindex == -1) {
|
||||
link_elf_error(filename, "lost symbol table index");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
/* Allocate space for and load the symbol table */
|
||||
ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
|
||||
ef->ddbsymtab = malloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK);
|
||||
@ -650,8 +664,11 @@ link_elf_load_file(linker_class_t cls, const char *filename,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (symstrindex == -1)
|
||||
panic("lost symbol string index");
|
||||
if (symstrindex == -1) {
|
||||
link_elf_error(filename, "lost symbol string index");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
/* Allocate space for and load the symbol strings */
|
||||
ef->ddbstrcnt = shdr[symstrindex].sh_size;
|
||||
ef->ddbstrtab = malloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK);
|
||||
@ -884,19 +901,35 @@ link_elf_load_file(linker_class_t cls, const char *filename,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pb != ef->nprogtab)
|
||||
panic("lost progbits");
|
||||
if (rl != ef->nreltab)
|
||||
panic("lost reltab");
|
||||
if (ra != ef->nrelatab)
|
||||
panic("lost relatab");
|
||||
if (mapbase != (vm_offset_t)ef->address + mapsize)
|
||||
panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n",
|
||||
if (pb != ef->nprogtab) {
|
||||
link_elf_error(filename, "lost progbits");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (rl != ef->nreltab) {
|
||||
link_elf_error(filename, "lost reltab");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (ra != ef->nrelatab) {
|
||||
link_elf_error(filename, "lost relatab");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (mapbase != (vm_offset_t)ef->address + mapsize) {
|
||||
printf(
|
||||
"%s: mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n",
|
||||
filename != NULL ? filename : "<none>",
|
||||
(u_long)mapbase, ef->address, (u_long)mapsize,
|
||||
(u_long)(vm_offset_t)ef->address + mapsize);
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Local intra-module relocations */
|
||||
link_elf_reloc_local(lf);
|
||||
error = link_elf_reloc_local(lf);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
|
||||
/* Pull in dependencies */
|
||||
VOP_UNLOCK(nd.ni_vp, 0);
|
||||
@ -1034,12 +1067,16 @@ relocate_file(elf_file_t ef)
|
||||
/* Perform relocations without addend if there are any: */
|
||||
for (i = 0; i < ef->nreltab; i++) {
|
||||
rel = ef->reltab[i].rel;
|
||||
if (rel == NULL)
|
||||
panic("lost a reltab!");
|
||||
if (rel == NULL) {
|
||||
link_elf_error(ef->lf.filename, "lost a reltab!");
|
||||
return (ENOEXEC);
|
||||
}
|
||||
rellim = rel + ef->reltab[i].nrel;
|
||||
base = findbase(ef, ef->reltab[i].sec);
|
||||
if (base == 0)
|
||||
panic("lost base for reltab");
|
||||
if (base == 0) {
|
||||
link_elf_error(ef->lf.filename, "lost base for reltab");
|
||||
return (ENOEXEC);
|
||||
}
|
||||
for ( ; rel < rellim; rel++) {
|
||||
symidx = ELF_R_SYM(rel->r_info);
|
||||
if (symidx >= ef->ddbsymcnt)
|
||||
@ -1053,7 +1090,7 @@ relocate_file(elf_file_t ef)
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
printf("link_elf_obj: symbol %s undefined\n",
|
||||
symname);
|
||||
return ENOENT;
|
||||
return (ENOENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1061,12 +1098,17 @@ relocate_file(elf_file_t ef)
|
||||
/* Perform relocations with addend if there are any: */
|
||||
for (i = 0; i < ef->nrelatab; i++) {
|
||||
rela = ef->relatab[i].rela;
|
||||
if (rela == NULL)
|
||||
panic("lost a relatab!");
|
||||
if (rela == NULL) {
|
||||
link_elf_error(ef->lf.filename, "lost a relatab!");
|
||||
return (ENOEXEC);
|
||||
}
|
||||
relalim = rela + ef->relatab[i].nrela;
|
||||
base = findbase(ef, ef->relatab[i].sec);
|
||||
if (base == 0)
|
||||
panic("lost base for relatab");
|
||||
if (base == 0) {
|
||||
link_elf_error(ef->lf.filename,
|
||||
"lost base for relatab");
|
||||
return (ENOEXEC);
|
||||
}
|
||||
for ( ; rela < relalim; rela++) {
|
||||
symidx = ELF_R_SYM(rela->r_info);
|
||||
if (symidx >= ef->ddbsymcnt)
|
||||
@ -1080,7 +1122,7 @@ relocate_file(elf_file_t ef)
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
printf("link_elf_obj: symbol %s undefined\n",
|
||||
symname);
|
||||
return ENOENT;
|
||||
return (ENOENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1092,7 +1134,7 @@ relocate_file(elf_file_t ef)
|
||||
*/
|
||||
elf_obj_cleanup_globals_cache(ef);
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1375,7 +1417,7 @@ link_elf_fix_link_set(elf_file_t ef)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
link_elf_reloc_local(linker_file_t lf)
|
||||
{
|
||||
elf_file_t ef = (elf_file_t)lf;
|
||||
@ -1393,12 +1435,16 @@ link_elf_reloc_local(linker_file_t lf)
|
||||
/* Perform relocations without addend if there are any: */
|
||||
for (i = 0; i < ef->nreltab; i++) {
|
||||
rel = ef->reltab[i].rel;
|
||||
if (rel == NULL)
|
||||
panic("lost a reltab!");
|
||||
if (rel == NULL) {
|
||||
link_elf_error(ef->lf.filename, "lost a reltab");
|
||||
return (ENOEXEC);
|
||||
}
|
||||
rellim = rel + ef->reltab[i].nrel;
|
||||
base = findbase(ef, ef->reltab[i].sec);
|
||||
if (base == 0)
|
||||
panic("lost base for reltab");
|
||||
if (base == 0) {
|
||||
link_elf_error(ef->lf.filename, "lost base for reltab");
|
||||
return (ENOEXEC);
|
||||
}
|
||||
for ( ; rel < rellim; rel++) {
|
||||
symidx = ELF_R_SYM(rel->r_info);
|
||||
if (symidx >= ef->ddbsymcnt)
|
||||
@ -1415,12 +1461,16 @@ link_elf_reloc_local(linker_file_t lf)
|
||||
/* Perform relocations with addend if there are any: */
|
||||
for (i = 0; i < ef->nrelatab; i++) {
|
||||
rela = ef->relatab[i].rela;
|
||||
if (rela == NULL)
|
||||
panic("lost a relatab!");
|
||||
if (rela == NULL) {
|
||||
link_elf_error(ef->lf.filename, "lost a relatab!");
|
||||
return (ENOEXEC);
|
||||
}
|
||||
relalim = rela + ef->relatab[i].nrela;
|
||||
base = findbase(ef, ef->relatab[i].sec);
|
||||
if (base == 0)
|
||||
panic("lost base for relatab");
|
||||
if (base == 0) {
|
||||
link_elf_error(ef->lf.filename, "lost base for reltab");
|
||||
return (ENOEXEC);
|
||||
}
|
||||
for ( ; rela < relalim; rela++) {
|
||||
symidx = ELF_R_SYM(rela->r_info);
|
||||
if (symidx >= ef->ddbsymcnt)
|
||||
@ -1433,6 +1483,7 @@ link_elf_reloc_local(linker_file_t lf)
|
||||
elf_obj_lookup);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static long
|
||||
|
Loading…
x
Reference in New Issue
Block a user