summaryrefslogtreecommitdiffstats
path: root/sys/kern/imgact_elf.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-10-18 12:57:48 +0000
committerkib <kib@FreeBSD.org>2009-10-18 12:57:48 +0000
commit2eb5677d22f46ebdb90a9deb2ca9aedd32e0eadd (patch)
treee29341de244b43883a2110f347e11b59715f73f5 /sys/kern/imgact_elf.c
parent04ed7ad878f2337842722490833d752a981f88e6 (diff)
downloadFreeBSD-src-2eb5677d22f46ebdb90a9deb2ca9aedd32e0eadd.zip
FreeBSD-src-2eb5677d22f46ebdb90a9deb2ca9aedd32e0eadd.tar.gz
If ET_DYN binary has non-zero base address for some reason, honour it
and do not relocate the binary to ET_DYN_LOAD_ADDR. This allows for the binary author to influence address map of the process. In particular, when the binary is actually an interpeter, this allows to have almost usual process address map. Communicate the relocation bias of the mapping for interpeter-less ET_DYN binary, that is interperter itself, in AT_BASE aux entry. This way, rtld is able to find its dynamic structure and relocate itself. Note that mapbase in the rtld is still wrong and requires further fixing. Reported and tested by: rwatson Discussed with: kan MFC after: 3 days
Diffstat (limited to 'sys/kern/imgact_elf.c')
-rw-r--r--sys/kern/imgact_elf.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index e112fe1..56cd66f 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -688,9 +688,9 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
u_long text_size = 0, data_size = 0, total_size = 0;
u_long text_addr = 0, data_addr = 0;
u_long seg_size, seg_addr;
- u_long addr, et_dyn_addr, entry = 0, proghdr = 0;
+ u_long addr, baddr, et_dyn_addr, entry = 0, proghdr = 0;
int32_t osrel = 0;
- int error = 0, i;
+ int error = 0, i, n;
const char *interp = NULL, *newinterp = NULL;
Elf_Brandinfo *brand_info;
char *path;
@@ -719,14 +719,22 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff);
if (!aligned(phdr, Elf_Addr))
return (ENOEXEC);
+ n = 0;
+ baddr = 0;
for (i = 0; i < hdr->e_phnum; i++) {
+ if (phdr[i].p_type == PT_LOAD) {
+ if (n == 0)
+ baddr = phdr[i].p_vaddr;
+ n++;
+ continue;
+ }
if (phdr[i].p_type == PT_INTERP) {
/* Path to interpreter */
if (phdr[i].p_filesz > MAXPATHLEN ||
phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE)
return (ENOEXEC);
interp = imgp->image_header + phdr[i].p_offset;
- break;
+ continue;
}
}
@@ -739,7 +747,14 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
if (hdr->e_type == ET_DYN) {
if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0)
return (ENOEXEC);
- et_dyn_addr = ET_DYN_LOAD_ADDR;
+ /*
+ * Honour the base load address from the dso if it is
+ * non-zero for some reason.
+ */
+ if (baddr == 0)
+ et_dyn_addr = ET_DYN_LOAD_ADDR;
+ else
+ et_dyn_addr = 0;
} else
et_dyn_addr = 0;
sv = brand_info->sysvec;
@@ -910,7 +925,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
return (error);
}
} else
- addr = 0;
+ addr = et_dyn_addr;
/*
* Construct auxargs table (used by the fixup routine)
OpenPOWER on IntegriCloud