diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c --- a/libexec/rtld-elf/map_object.c +++ b/libexec/rtld-elf/map_object.c @@ -98,6 +98,7 @@ char *note_map; size_t note_map_len; Elf_Addr text_end; + Elf_Addr entry; hdr = get_elf_header(fd, path, sb, &phdr); if (hdr == NULL) @@ -119,6 +120,7 @@ segs = alloca(sizeof(segs[0]) * hdr->e_phnum); stack_flags = PF_X | PF_R | PF_W; text_end = 0; + entry = 0; while (phdr < phlimit) { switch (phdr->p_type) { case PT_INTERP: @@ -242,6 +244,18 @@ goto error1; } + /* Check if this segment contains the entry point */ + if (hdr->e_entry != 0 && + hdr->e_entry >= segs[i]->p_vaddr && + hdr->e_entry < segs[i]->p_vaddr + segs[i]->p_memsz) { + if (!(data_prot & PROT_EXEC)) { + _rtld_error("%s: entry point is not executable", + path); + goto error1; + } + entry = hdr->e_entry; + } + /* Do BSS setup */ if (segs[i]->p_filesz != segs[i]->p_memsz) { /* Clear any BSS in the last page of the segment. */ @@ -306,8 +320,9 @@ obj->vaddrbase = base_vaddr; obj->relocbase = mapbase - base_vaddr; obj->dynamic = (const Elf_Dyn *)(obj->relocbase + phdyn->p_vaddr); - if (hdr->e_entry != 0) - obj->entry = (caddr_t)(obj->relocbase + hdr->e_entry); + /* non-zero iff hdr->e_entry points into an executable segment */ + if (entry != 0) + obj->entry = (caddr_t)(obj->relocbase + entry); if (phdr_vaddr != 0) { obj->phdr = (const Elf_Phdr *)(obj->relocbase + phdr_vaddr); } else { diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -1004,6 +1004,10 @@ lock_release(rtld_bind_lock, &lockstate); + if (obj_main->entry == 0) { + _rtld_error("no valid entry point"); + rtld_die(); + } dbg("transferring control to program entry point = %p", obj_main->entry);