aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMarcelo Tosatti <marcelo.tosatti@cyclades.com>2005-01-11 03:18:34 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-11 03:18:34 -0800
commitd7300467ba8b26455993605bd4aef4740a900e67 (patch)
treef02cc76087c6986d327c0067787358860255185d /fs
parent0afec568aa9291e792fca96971d204ea6ba32f0d (diff)
downloadhistory-d7300467ba8b26455993605bd4aef4740a900e67.tar.gz
[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: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/binfmt_elf.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index eaa2c7026e60cd..a66bc8df6d6f9b 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -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;
}