]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] binfmt_elf fix return error codes and early corrupt binary detection
authorMarcelo Tosatti <marcelo.tosatti@cyclades.com>
Tue, 11 Jan 2005 11:18:34 +0000 (03:18 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 11 Jan 2005 11:18:34 +0000 (03:18 -0800)
With Solar Designer <solar@openwall.com>

The following patch changes the following on ELF parsing/loading code
(fs/binfmt_elf):

- Stronger validity checks on ELF files:
        treat e_phnum (program header count) < 1 as invalid
        treat p_filesz (file size) < 2 invalid on program header interp. case
 - Saner return error codes
 - Make sure SIGKILL is delivered on error handling

Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/binfmt_elf.c

index eaa2c7026e60cd2b281f2479c572d7e39347e5ef..a66bc8df6d6f9b6fe56242299089faf8d1129578 100644 (file)
@@ -322,7 +322,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
         */
        if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
                goto out;
-       if (interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr))
+       if (interp_elf_ex->e_phnum < 1 ||
+               interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr))
                goto out;
 
        /* Now read in all of the header information */
@@ -524,12 +525,13 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
        /* Now read in all of the header information */
 
-       retval = -ENOMEM;
        if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
                goto out;
-       if (loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
+       if (loc->elf_ex.e_phnum < 1 ||
+               loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
                goto out;
        size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
+       retval = -ENOMEM;
        elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
        if (!elf_phdata)
                goto out;
@@ -575,10 +577,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                         * is an a.out format binary
                         */
 
-                       retval = -ENOMEM;
+                       retval = -ENOEXEC;
                        if (elf_ppnt->p_filesz > PATH_MAX || 
-                           elf_ppnt->p_filesz == 0)
+                           elf_ppnt->p_filesz < 2)
                                goto out_free_file;
+
+                       retval = -ENOMEM;
                        elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
                                                           GFP_KERNEL);
                        if (!elf_interpreter)
@@ -593,7 +597,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                                goto out_free_interp;
                        }
                        /* make sure path is NULL terminated */
-                       retval = -EINVAL;
+                       retval = -ENOEXEC;
                        if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
                                goto out_free_interp;
 
@@ -868,8 +872,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                                                    interpreter,
                                                    &interp_load_addr);
                if (BAD_ADDR(elf_entry)) {
-                       printk(KERN_ERR "Unable to load interpreter\n");
-                       send_sig(SIGSEGV, current, 0);
+                       printk(KERN_ERR "Unable to load interpreter %.128s\n",
+                               elf_interpreter);
+                       force_sig(SIGSEGV, current);
                        retval = -ENOEXEC; /* Nobody gets to see this, but.. */
                        goto out_free_dentry;
                }