Deal with ASLR PIE executables, by recognizing that phdr != phdr->v_addr

for PT_PHDR headers when the program has been loader to a vaddr other than
then one specified (a randomized one), and modifying the relocation base
address appropriately (idea from elad)
This commit is contained in:
christos 2007-12-26 21:14:41 +00:00
parent 8b0637156f
commit 8636ab52f6
1 changed files with 17 additions and 12 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: headers.c,v 1.23 2007/12/07 20:34:04 ad Exp $ */
/* $NetBSD: headers.c,v 1.24 2007/12/26 21:14:41 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: headers.c,v 1.23 2007/12/07 20:34:04 ad Exp $");
__RCSID("$NetBSD: headers.c,v 1.24 2007/12/26 21:14:41 christos Exp $");
#endif /* not lint */
#include <err.h>
@ -291,36 +291,41 @@ _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
const Elf_Phdr *phlimit = phdr + phnum;
const Elf_Phdr *ph;
int nsegs = 0;
ptrdiff_t relocoffs = 0;
Elf_Addr vaddr;
obj = _rtld_obj_new();
for (ph = phdr; ph < phlimit; ++ph) {
vaddr = ph->p_vaddr + relocoffs;
dbg(("headers: relocoffs = %lx\n", (long)relocoffs));
switch (ph->p_type) {
case PT_PHDR:
assert((const Elf_Phdr *) ph->p_vaddr == phdr);
relocoffs = (char *)phdr - (char *)ph->p_vaddr;
break;
case PT_INTERP:
obj->interp = (const char *) ph->p_vaddr;
obj->interp = (const char *)vaddr;
break;
case PT_LOAD:
assert(nsegs < 2);
if (nsegs == 0) { /* First load segment */
obj->vaddrbase = round_down(ph->p_vaddr);
obj->mapbase = (caddr_t) obj->vaddrbase;
obj->relocbase = obj->mapbase - obj->vaddrbase;
obj->textsize = round_up(ph->p_vaddr +
ph->p_memsz) - obj->vaddrbase;
obj->vaddrbase = round_down(vaddr);
obj->mapbase = (caddr_t)obj->vaddrbase;
obj->relocbase = relocoffs ? (void *)relocoffs :
(obj->mapbase - obj->vaddrbase);
obj->textsize = round_up(vaddr + ph->p_memsz) -
obj->vaddrbase;
} else { /* Last load segment */
obj->mapsize = round_up(ph->p_vaddr +
ph->p_memsz) - obj->vaddrbase;
obj->mapsize = round_up(vaddr + ph->p_memsz) -
obj->vaddrbase;
}
++nsegs;
break;
case PT_DYNAMIC:
obj->dynamic = (Elf_Dyn *) ph->p_vaddr;
obj->dynamic = (Elf_Dyn *)vaddr;
break;
}
}