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
					
				@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user