Commit d7300467 authored by Marcelo Tosatti's avatar Marcelo Tosatti Committed by Linus Torvalds

[PATCH] binfmt_elf fix return error codes and early corrupt binary detection

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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 0afec568
...@@ -322,7 +322,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, ...@@ -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)) if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
goto out; 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; goto out;
/* Now read in all of the header information */ /* 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) ...@@ -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 */ /* Now read in all of the header information */
retval = -ENOMEM;
if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr)) if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
goto out; 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; goto out;
size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr); size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
retval = -ENOMEM;
elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
if (!elf_phdata) if (!elf_phdata)
goto out; goto out;
...@@ -575,10 +577,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -575,10 +577,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
* is an a.out format binary * is an a.out format binary
*/ */
retval = -ENOMEM; retval = -ENOEXEC;
if (elf_ppnt->p_filesz > PATH_MAX || if (elf_ppnt->p_filesz > PATH_MAX ||
elf_ppnt->p_filesz == 0) elf_ppnt->p_filesz < 2)
goto out_free_file; goto out_free_file;
retval = -ENOMEM;
elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
GFP_KERNEL); GFP_KERNEL);
if (!elf_interpreter) if (!elf_interpreter)
...@@ -593,7 +597,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -593,7 +597,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
goto out_free_interp; goto out_free_interp;
} }
/* make sure path is NULL terminated */ /* make sure path is NULL terminated */
retval = -EINVAL; retval = -ENOEXEC;
if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0') if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
goto out_free_interp; goto out_free_interp;
...@@ -868,8 +872,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -868,8 +872,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
interpreter, interpreter,
&interp_load_addr); &interp_load_addr);
if (BAD_ADDR(elf_entry)) { if (BAD_ADDR(elf_entry)) {
printk(KERN_ERR "Unable to load interpreter\n"); printk(KERN_ERR "Unable to load interpreter %.128s\n",
send_sig(SIGSEGV, current, 0); elf_interpreter);
force_sig(SIGSEGV, current);
retval = -ENOEXEC; /* Nobody gets to see this, but.. */ retval = -ENOEXEC; /* Nobody gets to see this, but.. */
goto out_free_dentry; goto out_free_dentry;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment