From 31d8526346b8737a4117bbc433d4b15788915771 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Fri, 10 Aug 2012 18:27:23 +0200 Subject: [PATCH] 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. --- lib/libexec/exec_elf.c | 14 +++++++------- lib/libexec/libexec.h | 1 + servers/vfs/exec.c | 5 +++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/libexec/exec_elf.c b/lib/libexec/exec_elf.c index 3fc9f71c6..ab451a980 100644 --- a/lib/libexec/exec_elf.c +++ b/lib/libexec/exec_elf.c @@ -159,11 +159,11 @@ int libexec_load_elf(struct exec_info *execi) if(execi->clearproc) execi->clearproc(execi); 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; Elf_Phdr *ph = &phdr[i]; 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; page_offset = vaddr % PAGE_SIZE; vaddr -= page_offset; @@ -183,19 +183,19 @@ int libexec_load_elf(struct exec_info *execi) #endif /* 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); return ENOMEM; } #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 /* Clear remaining bits */ - vfileend = ph->p_vaddr + ph->p_filesz; + vfileend = p_vaddr + ph->p_filesz; vmemend = vaddr + seg_membytes; - if((chunk = ph->p_vaddr - vaddr) > 0) { + if((chunk = p_vaddr - vaddr) > 0) { #if ELF_DEBUG printf("start clearing 0x%lx-0x%lx\n", vaddr, vaddr+chunk); #endif @@ -220,7 +220,7 @@ int libexec_load_elf(struct exec_info *execi) #endif /* 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; return OK; diff --git a/lib/libexec/libexec.h b/lib/libexec/libexec.h index 5169c4b21..69da9cb29 100644 --- a/lib/libexec/libexec.h +++ b/lib/libexec/libexec.h @@ -27,6 +27,7 @@ struct exec_info { gid_t new_gid; /* Process GID after exec */ int allow_setuid; /* Allow set{u,g}id execution? */ vir_bytes stack_size; /* Desired stack size */ + vir_bytes load_offset; /* Desired load offset */ /* Callback pointers for use by libexec */ libexec_loadfunc_t copymem; /* Copy callback */ diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index 2f6acb82e..cf49447bf 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -286,6 +286,11 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, 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 */ strlcpy(execi.execname, finalexec, PATH_MAX); -- 2.44.0