summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wright <chrisw@osdl.org>2004-11-09 18:33:00 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-11-09 18:33:00 -0800
commitad49d6baabfe0950d559e8becd2121fd02483cd8 (patch)
tree1e66ef5200123e7896d8762579bfdffa1348f528
parentbea14a1c8795473a3d0dfcae64d0ef2992a29e3d (diff)
[PATCH] binfmt_elf: handle partial reads gracefully
Make sure kernel reads full size of elf data. Error out if mmap fails when mapping any sections of the executable. Make sure interpreter string is NULL terminated. Signed-off-by: Chris Wright <chrisw@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/binfmt_elf.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index cea19a8ad438..9d16fc257332 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -335,9 +335,12 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
goto out;
retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size);
- error = retval;
- if (retval < 0)
+ error = -EIO;
+ if (retval != size) {
+ if (retval < 0)
+ error = retval;
goto out_close;
+ }
eppnt = elf_phdata;
for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
@@ -532,8 +535,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
goto out;
retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size);
- if (retval < 0)
+ if (retval != size) {
+ if (retval >= 0)
+ retval = -EIO;
goto out_free_ph;
+ }
files = current->files; /* Refcounted so ok */
retval = unshare_files();
@@ -580,8 +586,14 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
retval = kernel_read(bprm->file, elf_ppnt->p_offset,
elf_interpreter,
elf_ppnt->p_filesz);
- if (retval < 0)
+ if (retval != elf_ppnt->p_filesz) {
+ if (retval >= 0)
+ retval = -EIO;
goto out_free_interp;
+ }
+ /* make sure path is NULL terminated */
+ elf_interpreter[elf_ppnt->p_filesz - 1] = '\0';
+
/* If the program interpreter is one of these two,
* then assume an iBCS2 image. Otherwise assume
* a native linux image.
@@ -616,8 +628,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (IS_ERR(interpreter))
goto out_free_interp;
retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
- if (retval < 0)
+ if (retval != BINPRM_BUF_SIZE) {
+ if (retval >= 0)
+ retval = -EIO;
goto out_free_dentry;
+ }
/* Get the exec headers */
loc->interp_ex = *((struct exec *) bprm->buf);
@@ -776,8 +791,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
}
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
- if (BAD_ADDR(error))
- continue;
+ if (BAD_ADDR(error)) {
+ send_sig(SIGKILL, current, 0);
+ goto out_free_dentry;
+ }
if (!load_addr_set) {
load_addr_set = 1;