libexec: detect short files
if an exec() fails partway through reading in the sections, the target process is already gone and a defunct process remains. sanity checking the binary beforehand helps that. test10 mutilates binaries and exec()s them on purpose; making an exec() fail cleanly in such cases seems like acceptable behaviour. fixes test10 on ARM. Change-Id: I1ed9bb200ce469d4d349073cadccad5503b2fcb0
This commit is contained in:
parent
57bab02d57
commit
298b41b523
8 changed files with 20 additions and 4 deletions
|
@ -131,7 +131,7 @@ void arch_boot_proc(struct boot_image *ip, struct proc *rp)
|
||||||
execi.stack_size = 32 * 1024; /* not too crazy as it must be preallocated */
|
execi.stack_size = 32 * 1024; /* not too crazy as it must be preallocated */
|
||||||
execi.proc_e = ip->endpoint;
|
execi.proc_e = ip->endpoint;
|
||||||
execi.hdr = (char *) mod->mod_start; /* phys mem direct */
|
execi.hdr = (char *) mod->mod_start; /* phys mem direct */
|
||||||
execi.hdr_len = mod->mod_end - mod->mod_start;
|
execi.filesize = execi.hdr_len = mod->mod_end - mod->mod_start;
|
||||||
strcpy(execi.progname, ip->proc_name);
|
strcpy(execi.progname, ip->proc_name);
|
||||||
execi.frame_len = 0;
|
execi.frame_len = 0;
|
||||||
|
|
||||||
|
|
|
@ -407,7 +407,7 @@ void arch_boot_proc(struct boot_image *ip, struct proc *rp)
|
||||||
execi.stack_size = 16 * 1024; /* not too crazy as it must be preallocated */
|
execi.stack_size = 16 * 1024; /* not too crazy as it must be preallocated */
|
||||||
execi.proc_e = ip->endpoint;
|
execi.proc_e = ip->endpoint;
|
||||||
execi.hdr = (char *) mod->mod_start; /* phys mem direct */
|
execi.hdr = (char *) mod->mod_start; /* phys mem direct */
|
||||||
execi.hdr_len = mod->mod_end - mod->mod_start;
|
execi.filesize = execi.hdr_len = mod->mod_end - mod->mod_start;
|
||||||
strlcpy(execi.progname, ip->proc_name, sizeof(execi.progname));
|
strlcpy(execi.progname, ip->proc_name, sizeof(execi.progname));
|
||||||
execi.frame_len = 0;
|
execi.frame_len = 0;
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,15 @@ int libexec_load_elf(struct exec_info *execi)
|
||||||
assert(execi->allocmem_prealloc);
|
assert(execi->allocmem_prealloc);
|
||||||
assert(execi->allocmem_ondemand);
|
assert(execi->allocmem_ondemand);
|
||||||
|
|
||||||
|
for (i = 0; i < hdr->e_phnum; i++) {
|
||||||
|
Elf_Phdr *ph = &phdr[i];
|
||||||
|
off_t file_limit = ph->p_offset + ph->p_filesz;
|
||||||
|
/* sanity check binary before wiping out the target process */
|
||||||
|
if(execi->filesize < file_limit) {
|
||||||
|
return ENOEXEC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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++) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ struct exec_info {
|
||||||
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 */
|
vir_bytes load_offset; /* Desired load offset */
|
||||||
|
off_t filesize; /* How big is the file */
|
||||||
|
|
||||||
/* Callback pointers for use by libexec */
|
/* Callback pointers for use by libexec */
|
||||||
libexec_loadfunc_t copymem; /* Copy callback */
|
libexec_loadfunc_t copymem; /* Copy callback */
|
||||||
|
|
|
@ -124,7 +124,7 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
|
||||||
execi.stack_size = DEFAULT_STACK_LIMIT;
|
execi.stack_size = DEFAULT_STACK_LIMIT;
|
||||||
execi.proc_e = proc_e;
|
execi.proc_e = proc_e;
|
||||||
execi.hdr = exec;
|
execi.hdr = exec;
|
||||||
execi.hdr_len = exec_len;
|
execi.filesize = execi.hdr_len = exec_len;
|
||||||
strncpy(execi.progname, progname, PROC_NAME_LEN-1);
|
strncpy(execi.progname, progname, PROC_NAME_LEN-1);
|
||||||
execi.progname[PROC_NAME_LEN-1] = '\0';
|
execi.progname[PROC_NAME_LEN-1] = '\0';
|
||||||
execi.frame_len = frame_len;
|
execi.frame_len = frame_len;
|
||||||
|
|
|
@ -312,6 +312,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
||||||
|
|
||||||
execi.args.proc_e = proc_e;
|
execi.args.proc_e = proc_e;
|
||||||
execi.args.frame_len = frame_len;
|
execi.args.frame_len = frame_len;
|
||||||
|
execi.args.filesize = execi.vp->v_size;
|
||||||
|
|
||||||
for (i = 0; exec_loaders[i].load_object != NULL; i++) {
|
for (i = 0; exec_loaders[i].load_object != NULL; i++) {
|
||||||
r = (*exec_loaders[i].load_object)(&execi.args);
|
r = (*exec_loaders[i].load_object)(&execi.args);
|
||||||
|
|
|
@ -276,6 +276,7 @@ void exec_bootproc(struct vmproc *vmp, struct boot_image *ip)
|
||||||
strlcpy(execi->progname, ip->proc_name, sizeof(execi->progname));
|
strlcpy(execi->progname, ip->proc_name, sizeof(execi->progname));
|
||||||
execi->frame_len = 0;
|
execi->frame_len = 0;
|
||||||
execi->opaque = &vmexeci;
|
execi->opaque = &vmexeci;
|
||||||
|
execi->filesize = ip->len;
|
||||||
|
|
||||||
vmexeci.ip = ip;
|
vmexeci.ip = ip;
|
||||||
vmexeci.vmp = vmp;
|
vmexeci.vmp = vmp;
|
||||||
|
|
|
@ -77,7 +77,11 @@ int n;
|
||||||
if ((pid = fork()) != 0) {
|
if ((pid = fork()) != 0) {
|
||||||
wait(&n); /* wait for some child (any one) */
|
wait(&n); /* wait for some child (any one) */
|
||||||
} else {
|
} else {
|
||||||
execl(name[n], name[n], (char *) 0);
|
/* a successful exec or a successful detection of a broken executable
|
||||||
|
* is ok
|
||||||
|
*/
|
||||||
|
if(execl(name[n], name[n], (char *) 0) < 0 && errno == ENOEXEC)
|
||||||
|
exit(0);
|
||||||
errct++;
|
errct++;
|
||||||
printf("Child execl didn't take. file=%s errno=%d\n", name[n], errno);
|
printf("Child execl didn't take. file=%s errno=%d\n", name[n], errno);
|
||||||
rmfiles();
|
rmfiles();
|
||||||
|
|
Loading…
Reference in a new issue