diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 0e77131576b0..fe12d79e560f 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -101,7 +101,7 @@ struct dlerror_save { */ static const char *basename(const char *); static bool digest_dynamic(Obj_Entry *, int); -static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **, +static bool digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **, const Elf_Dyn **, const Elf_Dyn **); static bool digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *, const Elf_Dyn *); @@ -1580,7 +1580,7 @@ count_plts(const Elf_Dyn *dynp) * Process a shared object's DYNAMIC section, and save the important * information in its Obj_Entry structure. */ -static void +static bool digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, const Elf_Dyn **dyn_soname, const Elf_Dyn **dyn_runpath) { @@ -1604,7 +1604,7 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, obj->bind_now = false; dynp = obj->dynamic; if (dynp == NULL) - return; + return (true); obj->nplts = count_plts(dynp); if (obj->nplts != 0) obj->plts = xcalloc(obj->nplts, sizeof(*obj->plts)); @@ -1934,12 +1934,19 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, free(obj->plts); obj->plts = NULL; obj->nplts = 0; + pltrelsz = 0; } #endif - if (plttype == DT_RELA) { - for (i = 0; i < obj->nplts; i++) { - plt = &obj->plts[i]; + if (!(jmprel == pltrelsz && jmprel == pltgot)) { + _rtld_error("PLT dynamic tag mismatch"); + return (false); + } + + for (i = 0; i < obj->nplts; i++) { + plt = &obj->plts[i]; + plt->obj = obj; + if (plttype == DT_RELA) { plt->rela = (const Elf_Rela *) plt->rel; plt->rel = NULL; plt->relasize = plt->relsize; @@ -1966,6 +1973,8 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, if (obj->linkmap.l_refname != NULL) obj->linkmap.l_refname = obj->strtab + (unsigned long)obj-> linkmap.l_refname; + + return (true); } static bool @@ -1982,19 +1991,6 @@ static bool digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath, const Elf_Dyn *dyn_soname, const Elf_Dyn *dyn_runpath) { - Plt_Entry *plt; - unsigned long i; - - for (i = 0; i < obj->nplts; i++) { - plt = &obj->plts[i]; - if (plt->pltgot == NULL) - return (false); - if (plt->rel == NULL && plt->rela == NULL) - return (false); - if (plt->relsize == 0 && plt->relasize == 0) - return (false); - plt->obj = obj; - } if (obj->z_origin && !obj_resolve_origin(obj)) return (false); @@ -2017,8 +2013,8 @@ digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath, // any overflows at runtime. set_bounds_if_nonnull(obj->rel, obj->relsize); set_bounds_if_nonnull(obj->rela, obj->relasize); - for (i = 0; i < obj->nplts; i++) { - plt = &obj->plts[i]; + for (unsigned long i = 0; i < obj->nplts; i++) { + Plt_Entry *plt = &obj->plts[i]; set_bounds_if_nonnull(plt->rel, plt->relsize); set_bounds_if_nonnull(plt->rela, plt->relasize); } @@ -2049,7 +2045,8 @@ digest_dynamic(Obj_Entry *obj, int early) const Elf_Dyn *dyn_soname; const Elf_Dyn *dyn_runpath; - digest_dynamic1(obj, early, &dyn_rpath, &dyn_soname, &dyn_runpath); + if (!digest_dynamic1(obj, early, &dyn_rpath, &dyn_soname, &dyn_runpath)) + return (false); return (digest_dynamic2(obj, dyn_rpath, dyn_soname, dyn_runpath)); } @@ -2911,7 +2908,8 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info) #endif objtmp.dynamic = rtld_dynamic(&objtmp); - digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname, &dyn_runpath); + if (!digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname, &dyn_runpath)) + rtld_die(); assert(objtmp.needed == NULL); assert(!objtmp.textrel); ehdr = (Elf_Ehdr *)mapbase; @@ -2965,7 +2963,8 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info) if (aux_info[AT_OSRELDATE] != NULL) osreldate = aux_info[AT_OSRELDATE]->a_un.a_val; - digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname, dyn_runpath); + if (!digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname, dyn_runpath)) + rtld_die(); /* Replace the path with a dynamically allocated copy. */ obj_rtld.path = xstrdup(ld_path_rtld);