DF-0060 / fix.diff
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -240,8 +240,14 @@ case DT_HASH: { /* From src/libexec/rtld-elf/rtld.c */ + Elf_Addr hoff = dp->d_un.d_ptr; + if (hoff >= lf->size || + hoff + 2 * sizeof(Elf_Hashelt) > lf->size) { + kprintf("link_elf: DT_HASH out of bounds\n"); + return ENOEXEC; + } const Elf_Hashelt *hashtab = (const Elf_Hashelt *) - (ef->address + dp->d_un.d_ptr); + (ef->address + hoff); ef->nbuckets = hashtab[0]; ef->nchains = hashtab[1]; ef->buckets = hashtab + 2; @@ -249,23 +255,27 @@ break; } case DT_STRTAB: - ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr); + if (dp->d_un.d_ptr < lf->size) + ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr); break; case DT_STRSZ: ef->strsz = dp->d_un.d_val; break; case DT_SYMTAB: - ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr); + if (dp->d_un.d_ptr < lf->size) + ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr); break; case DT_SYMENT: if (dp->d_un.d_val != sizeof(Elf_Sym)) return ENOEXEC; break; case DT_PLTGOT: - ef->got = (Elf_Addr *) (ef->address + dp->d_un.d_ptr); + if (dp->d_un.d_ptr < lf->size) + ef->got = (Elf_Addr *) (ef->address + dp->d_un.d_ptr); break; case DT_REL: - ef->rel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr); + if (dp->d_un.d_ptr < lf->size) + ef->rel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr); break; case DT_RELSZ: ef->relsize = dp->d_un.d_val; @@ -275,13 +285,15 @@ return ENOEXEC; break; case DT_JMPREL: - ef->pltrel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr); + if (dp->d_un.d_ptr < lf->size) + ef->pltrel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr); break; case DT_PLTRELSZ: ef->pltrelsize = dp->d_un.d_val; break; case DT_RELA: - ef->rela = (const Elf_Rela *) (ef->address + dp->d_un.d_ptr); + if (dp->d_un.d_ptr < lf->size) + ef->rela = (const Elf_Rela *) (ef->address + dp->d_un.d_ptr); break; case DT_RELASZ: ef->relasize = dp->d_un.d_val; |