libexec: add load_offset feature, used for ld.so
. ld.so is linked at 0 but it can relocate itself; we wish to load ld.so higher though to trap NULL dereferences. if we know we have to execute ld.so, vfs tells libexec to put it higher.
This commit is contained in:
parent
ad898517ac
commit
31d8526346
3 changed files with 13 additions and 7 deletions
|
@ -159,11 +159,11 @@ int libexec_load_elf(struct exec_info *execi)
|
||||||
if(execi->clearproc) execi->clearproc(execi);
|
if(execi->clearproc) execi->clearproc(execi);
|
||||||
|
|
||||||
for (i = 0; i < hdr->e_phnum; i++) {
|
for (i = 0; i < hdr->e_phnum; i++) {
|
||||||
vir_bytes seg_membytes, page_offset, vaddr;
|
vir_bytes seg_membytes, page_offset, p_vaddr, vaddr;
|
||||||
vir_bytes chunk, vfileend, vmemend;
|
vir_bytes chunk, vfileend, vmemend;
|
||||||
Elf_Phdr *ph = &phdr[i];
|
Elf_Phdr *ph = &phdr[i];
|
||||||
if (ph->p_type != PT_LOAD || ph->p_memsz == 0) continue;
|
if (ph->p_type != PT_LOAD || ph->p_memsz == 0) continue;
|
||||||
vaddr = ph->p_vaddr;
|
vaddr = p_vaddr = ph->p_vaddr + execi->load_offset;
|
||||||
seg_membytes = ph->p_memsz;
|
seg_membytes = ph->p_memsz;
|
||||||
page_offset = vaddr % PAGE_SIZE;
|
page_offset = vaddr % PAGE_SIZE;
|
||||||
vaddr -= page_offset;
|
vaddr -= page_offset;
|
||||||
|
@ -183,19 +183,19 @@ int libexec_load_elf(struct exec_info *execi)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Copy executable section into it */
|
/* Copy executable section into it */
|
||||||
if(execi->copymem(execi, ph->p_offset, ph->p_vaddr, ph->p_filesz) != OK) {
|
if(execi->copymem(execi, ph->p_offset, p_vaddr, ph->p_filesz) != OK) {
|
||||||
if(execi->clearproc) execi->clearproc(execi);
|
if(execi->clearproc) execi->clearproc(execi);
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ELF_DEBUG
|
#if ELF_DEBUG
|
||||||
printf("copied 0x%lx-0x%lx\n", ph->p_vaddr, ph->p_vaddr+ph->p_filesz);
|
printf("copied 0x%lx-0x%lx\n", p_vaddr, p_vaddr+ph->p_filesz);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Clear remaining bits */
|
/* Clear remaining bits */
|
||||||
vfileend = ph->p_vaddr + ph->p_filesz;
|
vfileend = p_vaddr + ph->p_filesz;
|
||||||
vmemend = vaddr + seg_membytes;
|
vmemend = vaddr + seg_membytes;
|
||||||
if((chunk = ph->p_vaddr - vaddr) > 0) {
|
if((chunk = p_vaddr - vaddr) > 0) {
|
||||||
#if ELF_DEBUG
|
#if ELF_DEBUG
|
||||||
printf("start clearing 0x%lx-0x%lx\n", vaddr, vaddr+chunk);
|
printf("start clearing 0x%lx-0x%lx\n", vaddr, vaddr+chunk);
|
||||||
#endif
|
#endif
|
||||||
|
@ -220,7 +220,7 @@ int libexec_load_elf(struct exec_info *execi)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* record entry point and lowest load vaddr for caller */
|
/* record entry point and lowest load vaddr for caller */
|
||||||
execi->pc = hdr->e_entry;
|
execi->pc = hdr->e_entry + execi->load_offset;
|
||||||
execi->load_base = startv;
|
execi->load_base = startv;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
|
@ -27,6 +27,7 @@ struct exec_info {
|
||||||
gid_t new_gid; /* Process GID after exec */
|
gid_t new_gid; /* Process GID after exec */
|
||||||
int allow_setuid; /* Allow set{u,g}id execution? */
|
int allow_setuid; /* Allow set{u,g}id execution? */
|
||||||
vir_bytes stack_size; /* Desired stack size */
|
vir_bytes stack_size; /* Desired stack size */
|
||||||
|
vir_bytes load_offset; /* Desired load offset */
|
||||||
|
|
||||||
/* Callback pointers for use by libexec */
|
/* Callback pointers for use by libexec */
|
||||||
libexec_loadfunc_t copymem; /* Copy callback */
|
libexec_loadfunc_t copymem; /* Copy callback */
|
||||||
|
|
|
@ -286,6 +286,11 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
||||||
FAILCHECK(r);
|
FAILCHECK(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ld.so is linked at 0, but it can relocate itself; we
|
||||||
|
* want it higher to trap NULL pointer dereferences.
|
||||||
|
*/
|
||||||
|
execi.args.load_offset = 0x10000;
|
||||||
|
|
||||||
/* Remember it */
|
/* Remember it */
|
||||||
strlcpy(execi.execname, finalexec, PATH_MAX);
|
strlcpy(execi.execname, finalexec, PATH_MAX);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue