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
This commit is contained in:
kib 2009-10-10 15:33:01 +00:00
parent 3547dab066
commit edf781a815

View File

@ -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_size = 0, data_size = 0, total_size = 0;
u_long text_addr = 0, data_addr = 0; u_long text_addr = 0, data_addr = 0;
u_long seg_size, seg_addr; 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; int32_t osrel = 0;
int error = 0, i; int error = 0, i;
const char *interp = NULL, *newinterp = NULL; const char *interp = NULL, *newinterp = NULL;
@ -736,9 +736,12 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
hdr->e_ident[EI_OSABI]); hdr->e_ident[EI_OSABI]);
return (ENOEXEC); return (ENOEXEC);
} }
if (hdr->e_type == ET_DYN && if (hdr->e_type == ET_DYN) {
(brand_info->flags & BI_CAN_EXEC_DYN) == 0) if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0)
return (ENOEXEC); return (ENOEXEC);
et_dyn_addr = ET_DYN_LOAD_ADDR;
} else
et_dyn_addr = 0;
sv = brand_info->sysvec; sv = brand_info->sysvec;
if (interp != NULL && brand_info->interp_newpath != NULL) if (interp != NULL && brand_info->interp_newpath != NULL)
newinterp = brand_info->interp_newpath; newinterp = brand_info->interp_newpath;
@ -786,7 +789,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
if ((error = __elfN(load_section)(vmspace, if ((error = __elfN(load_section)(vmspace,
imgp->object, phdr[i].p_offset, 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, phdr[i].p_memsz, phdr[i].p_filesz, prot,
sv->sv_pagesize)) != 0) sv->sv_pagesize)) != 0)
return (error); return (error);
@ -800,11 +803,12 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
if (phdr[i].p_offset == 0 && if (phdr[i].p_offset == 0 &&
hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize
<= phdr[i].p_filesz) <= 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 + 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 * 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)) { phdr[i].p_memsz)) {
text_size = seg_size; text_size = seg_size;
text_addr = seg_addr; text_addr = seg_addr;
entry = (u_long)hdr->e_entry; entry = (u_long)hdr->e_entry + et_dyn_addr;
} else { } else {
data_size = seg_size; data_size = seg_size;
data_addr = seg_addr; data_addr = seg_addr;
@ -834,7 +838,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
total_size += seg_size; total_size += seg_size;
break; break;
case PT_PHDR: /* Program header table info */ case PT_PHDR: /* Program header table info */
proghdr = phdr[i].p_vaddr; proghdr = phdr[i].p_vaddr + et_dyn_addr;
break; break;
default: default:
break; break;