]> Zhao Yanbai Git Server - minix.git/commitdiff
libexec: detect short files 92/292/2
authorBen Gras <ben@minix3.org>
Mon, 4 Feb 2013 00:49:48 +0000 (01:49 +0100)
committerBen Gras <ben@minix3.org>
Mon, 4 Feb 2013 11:04:35 +0000 (12:04 +0100)
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

kernel/arch/earm/protect.c
kernel/arch/i386/protect.c
lib/libexec/exec_elf.c
lib/libexec/libexec.h
servers/rs/exec.c
servers/vfs/exec.c
servers/vm/main.c
test/test10.c

index c2afc447ed6bbaeceab4070741386cfd43634a16..7a6f759b2c4f924efa4c8f79612e174d5cad7846 100644 (file)
@@ -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.proc_e = ip->endpoint;
                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);
                execi.frame_len = 0;
 
index a95397c481c1e1b936a8755d1a7c97db34f43451..7594e23613fd10dfeab9219604c7f7fa55f1ff9c 100644 (file)
@@ -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.proc_e = ip->endpoint;
                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));
                execi.frame_len = 0;
 
index a2096f1de94e30e49237735611ac0d4a66632fe7..4645ec638532eff72fe40fa32390cee205ec4ffd 100644 (file)
@@ -156,6 +156,15 @@ int libexec_load_elf(struct exec_info *execi)
        assert(execi->allocmem_prealloc);
        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);
 
        for (i = 0; i < hdr->e_phnum; i++) {
index 69da9cb298bfe275bc8d2fc7729b67fd387dd63f..8b6db7618888fdc72584834684a842470b2dde6f 100644 (file)
@@ -28,6 +28,7 @@ struct exec_info {
     int allow_setuid;                   /* Allow set{u,g}id execution? */
     vir_bytes stack_size;              /* Desired stack size */
     vir_bytes load_offset;             /* Desired load offset */
+    off_t filesize;                    /* How big is the file */
 
     /* Callback pointers for use by libexec */
     libexec_loadfunc_t copymem;                /* Copy callback */
index 7dd908de1aebd7004f28a6bea9ba32b25e87bc8f..d0c950f67c004dd1b3dd59ce1c8d617abbbb6c40 100644 (file)
@@ -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.proc_e = proc_e;
        execi.hdr = exec;
-       execi.hdr_len = exec_len;
+       execi.filesize = execi.hdr_len = exec_len;
        strncpy(execi.progname, progname, PROC_NAME_LEN-1);
        execi.progname[PROC_NAME_LEN-1] = '\0';
        execi.frame_len = frame_len;
index cf49447bf1716d24912a2d60c32d9cbe3f9546ab..b3f6f56ce0b154bef0e6f71d667a100ff79020c4 100644 (file)
@@ -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.frame_len = frame_len;
+  execi.args.filesize = execi.vp->v_size;
 
   for (i = 0; exec_loaders[i].load_object != NULL; i++) {
       r = (*exec_loaders[i].load_object)(&execi.args);
index d40a0b62170e716533c358b9a682289b0a346a0e..f2b7c2f5f50cf0a856dfef4358a4806d3169dab1 100644 (file)
@@ -276,6 +276,7 @@ void exec_bootproc(struct vmproc *vmp, struct boot_image *ip)
         strlcpy(execi->progname, ip->proc_name, sizeof(execi->progname));
         execi->frame_len = 0;
        execi->opaque = &vmexeci;
+       execi->filesize = ip->len;
 
        vmexeci.ip = ip;
        vmexeci.vmp = vmp;
index 152b560bf47e8a4965824ca0b2b0e8f1afa5ff3a..040b0f33a9177221367724038b9bc235dbf25b62 100644 (file)
@@ -77,7 +77,11 @@ int n;
   if ((pid = fork()) != 0) {
        wait(&n);               /* wait for some child (any one) */
   } 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++;
        printf("Child execl didn't take. file=%s errno=%d\n", name[n], errno);
        rmfiles();