summaryrefslogtreecommitdiffstats
path: root/sys/kern/imgact_elf.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-10-10 15:33:01 +0000
committerkib <kib@FreeBSD.org>2009-10-10 15:33:01 +0000
commitedf781a8157d148cc0bb8786425a0a55a751abcc (patch)
tree975b6448c292f8a5dce85095da7f37285725c50a /sys/kern/imgact_elf.c
parent3547dab066949bdbc8814e75d38e8403275bd4d4 (diff)
downloadFreeBSD-src-edf781a8157d148cc0bb8786425a0a55a751abcc.zip
FreeBSD-src-edf781a8157d148cc0bb8786425a0a55a751abcc.tar.gz
Map PIE binaries at non-zero base address.
Discussed with: bz Reviewed by: kan Tested by: bz (i386, amd64), bsam (linux) MFC after: some time
Diffstat (limited to 'sys/kern/imgact_elf.c')
-rw-r--r--sys/kern/imgact_elf.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 3841d1f..e112fe1 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -688,7 +688,7 @@ __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, entry = 0, proghdr = 0;
+ u_long addr, et_dyn_addr, entry = 0, proghdr = 0;
int32_t osrel = 0;
int error = 0, i;
const char *interp = NULL, *newinterp = NULL;
@@ -736,9 +736,12 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
hdr->e_ident[EI_OSABI]);
return (ENOEXEC);
}
- if (hdr->e_type == ET_DYN &&
- (brand_info->flags & BI_CAN_EXEC_DYN) == 0)
- return (ENOEXEC);
+ if (hdr->e_type == ET_DYN) {
+ if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0)
+ return (ENOEXEC);
+ et_dyn_addr = ET_DYN_LOAD_ADDR;
+ } else
+ et_dyn_addr = 0;
sv = brand_info->sysvec;
if (interp != NULL && brand_info->interp_newpath != NULL)
newinterp = brand_info->interp_newpath;
@@ -786,7 +789,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
if ((error = __elfN(load_section)(vmspace,
imgp->object, phdr[i].p_offset,
- (caddr_t)(uintptr_t)phdr[i].p_vaddr,
+ (caddr_t)(uintptr_t)phdr[i].p_vaddr + et_dyn_addr,
phdr[i].p_memsz, phdr[i].p_filesz, prot,
sv->sv_pagesize)) != 0)
return (error);
@@ -800,11 +803,12 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
if (phdr[i].p_offset == 0 &&
hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize
<= phdr[i].p_filesz)
- proghdr = phdr[i].p_vaddr + hdr->e_phoff;
+ proghdr = phdr[i].p_vaddr + hdr->e_phoff +
+ et_dyn_addr;
- seg_addr = trunc_page(phdr[i].p_vaddr);
+ seg_addr = trunc_page(phdr[i].p_vaddr + et_dyn_addr);
seg_size = round_page(phdr[i].p_memsz +
- phdr[i].p_vaddr - seg_addr);
+ phdr[i].p_vaddr + et_dyn_addr - seg_addr);
/*
* Is this .text or .data? We can't use
@@ -826,7 +830,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
phdr[i].p_memsz)) {
text_size = seg_size;
text_addr = seg_addr;
- entry = (u_long)hdr->e_entry;
+ entry = (u_long)hdr->e_entry + et_dyn_addr;
} else {
data_size = seg_size;
data_addr = seg_addr;
@@ -834,7 +838,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
total_size += seg_size;
break;
case PT_PHDR: /* Program header table info */
- proghdr = phdr[i].p_vaddr;
+ proghdr = phdr[i].p_vaddr + et_dyn_addr;
break;
default:
break;
OpenPOWER on IntegriCloud