[PATCH] flat binary loader doesn't check fd table full

In binfmt_flat.c, the flat binary loader should check file descriptor table
and install the fd on the file.

Convert the function to single-exit and fix this bug.

Signed-off-by: "Luke Yang" <luke.adi@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Luke Yang 2006-03-25 03:08:24 -08:00 committed by Linus Torvalds
parent f516342745
commit 1ad3dcc09c
1 changed files with 54 additions and 19 deletions

View File

@ -36,6 +36,7 @@
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/flat.h> #include <linux/flat.h>
#include <linux/syscalls.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/system.h> #include <asm/system.h>
@ -426,6 +427,8 @@ static int load_flat_file(struct linux_binprm * bprm,
int i, rev, relocs = 0; int i, rev, relocs = 0;
loff_t fpos; loff_t fpos;
unsigned long start_code, end_code; unsigned long start_code, end_code;
int ret;
int exec_fileno;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */ hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
inode = bprm->file->f_dentry->d_inode; inode = bprm->file->f_dentry->d_inode;
@ -450,7 +453,8 @@ static int load_flat_file(struct linux_binprm * bprm,
*/ */
if (strncmp(hdr->magic, "#!", 2)) if (strncmp(hdr->magic, "#!", 2))
printk("BINFMT_FLAT: bad header magic\n"); printk("BINFMT_FLAT: bad header magic\n");
return -ENOEXEC; ret = -ENOEXEC;
goto err;
} }
if (flags & FLAT_FLAG_KTRACE) if (flags & FLAT_FLAG_KTRACE)
@ -458,14 +462,16 @@ static int load_flat_file(struct linux_binprm * bprm,
if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) { if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and 0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION); printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and 0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION);
return -ENOEXEC; ret = -ENOEXEC;
goto err;
} }
/* Don't allow old format executables to use shared libraries */ /* Don't allow old format executables to use shared libraries */
if (rev == OLD_FLAT_VERSION && id != 0) { if (rev == OLD_FLAT_VERSION && id != 0) {
printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n", printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n",
(int) FLAT_VERSION); (int) FLAT_VERSION);
return -ENOEXEC; ret = -ENOEXEC;
goto err;
} }
/* /*
@ -478,7 +484,8 @@ static int load_flat_file(struct linux_binprm * bprm,
#ifndef CONFIG_BINFMT_ZFLAT #ifndef CONFIG_BINFMT_ZFLAT
if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) { if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
printk("Support for ZFLAT executables is not enabled.\n"); printk("Support for ZFLAT executables is not enabled.\n");
return -ENOEXEC; ret = -ENOEXEC;
goto err;
} }
#endif #endif
@ -490,14 +497,27 @@ static int load_flat_file(struct linux_binprm * bprm,
rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
if (rlim >= RLIM_INFINITY) if (rlim >= RLIM_INFINITY)
rlim = ~0; rlim = ~0;
if (data_len + bss_len > rlim) if (data_len + bss_len > rlim) {
return -ENOMEM; ret = -ENOMEM;
goto err;
}
/* check file descriptor */
exec_fileno = get_unused_fd();
if (exec_fileno < 0) {
ret = -EMFILE;
goto err;
}
get_file(bprm->file);
fd_install(exec_fileno, bprm->file);
/* Flush all traces of the currently running executable */ /* Flush all traces of the currently running executable */
if (id == 0) { if (id == 0) {
result = flush_old_exec(bprm); result = flush_old_exec(bprm);
if (result) if (result) {
return result; ret = result;
goto err_close;
}
/* OK, This is the point of no return */ /* OK, This is the point of no return */
set_personality(PER_LINUX); set_personality(PER_LINUX);
@ -527,7 +547,8 @@ static int load_flat_file(struct linux_binprm * bprm,
if (!textpos) if (!textpos)
textpos = (unsigned long) -ENOMEM; textpos = (unsigned long) -ENOMEM;
printk("Unable to mmap process text, errno %d\n", (int)-textpos); printk("Unable to mmap process text, errno %d\n", (int)-textpos);
return(textpos); ret = textpos;
goto err_close;
} }
down_write(&current->mm->mmap_sem); down_write(&current->mm->mmap_sem);
@ -542,7 +563,8 @@ static int load_flat_file(struct linux_binprm * bprm,
printk("Unable to allocate RAM for process data, errno %d\n", printk("Unable to allocate RAM for process data, errno %d\n",
(int)-datapos); (int)-datapos);
do_munmap(current->mm, textpos, text_len); do_munmap(current->mm, textpos, text_len);
return realdatastart; ret = realdatastart;
goto err_close;
} }
datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
@ -564,7 +586,8 @@ static int load_flat_file(struct linux_binprm * bprm,
printk("Unable to read data+bss, errno %d\n", (int)-result); printk("Unable to read data+bss, errno %d\n", (int)-result);
do_munmap(current->mm, textpos, text_len); do_munmap(current->mm, textpos, text_len);
do_munmap(current->mm, realdatastart, data_len + extra); do_munmap(current->mm, realdatastart, data_len + extra);
return result; ret = result;
goto err_close;
} }
reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len)); reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
@ -582,7 +605,8 @@ static int load_flat_file(struct linux_binprm * bprm,
textpos = (unsigned long) -ENOMEM; textpos = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process text/data, errno %d\n", printk("Unable to allocate RAM for process text/data, errno %d\n",
(int)-textpos); (int)-textpos);
return(textpos); ret = textpos;
goto err_close;
} }
realdatastart = textpos + ntohl(hdr->data_start); realdatastart = textpos + ntohl(hdr->data_start);
@ -627,7 +651,8 @@ static int load_flat_file(struct linux_binprm * bprm,
printk("Unable to read code+data+bss, errno %d\n",(int)-result); printk("Unable to read code+data+bss, errno %d\n",(int)-result);
do_munmap(current->mm, textpos, text_len + data_len + extra + do_munmap(current->mm, textpos, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long)); MAX_SHARED_LIBS * sizeof(unsigned long));
return result; ret = result;
goto err_close;
} }
} }
@ -690,8 +715,10 @@ static int load_flat_file(struct linux_binprm * bprm,
unsigned long addr; unsigned long addr;
if (*rp) { if (*rp) {
addr = calc_reloc(*rp, libinfo, id, 0); addr = calc_reloc(*rp, libinfo, id, 0);
if (addr == RELOC_FAILED) if (addr == RELOC_FAILED) {
return -ENOEXEC; ret = -ENOEXEC;
goto err_close;
}
*rp = addr; *rp = addr;
} }
} }
@ -718,8 +745,10 @@ static int load_flat_file(struct linux_binprm * bprm,
relval = ntohl(reloc[i]); relval = ntohl(reloc[i]);
addr = flat_get_relocate_addr(relval); addr = flat_get_relocate_addr(relval);
rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
if (rp == (unsigned long *)RELOC_FAILED) if (rp == (unsigned long *)RELOC_FAILED) {
return -ENOEXEC; ret = -ENOEXEC;
goto err_close;
}
/* Get the pointer's value. */ /* Get the pointer's value. */
addr = flat_get_addr_from_rp(rp, relval, flags); addr = flat_get_addr_from_rp(rp, relval, flags);
@ -731,8 +760,10 @@ static int load_flat_file(struct linux_binprm * bprm,
if ((flags & FLAT_FLAG_GOTPIC) == 0) if ((flags & FLAT_FLAG_GOTPIC) == 0)
addr = ntohl(addr); addr = ntohl(addr);
addr = calc_reloc(addr, libinfo, id, 0); addr = calc_reloc(addr, libinfo, id, 0);
if (addr == RELOC_FAILED) if (addr == RELOC_FAILED) {
return -ENOEXEC; ret = -ENOEXEC;
goto err_close;
}
/* Write back the relocated pointer. */ /* Write back the relocated pointer. */
flat_put_addr_at_rp(rp, addr, relval); flat_put_addr_at_rp(rp, addr, relval);
@ -752,6 +783,10 @@ static int load_flat_file(struct linux_binprm * bprm,
stack_len); stack_len);
return 0; return 0;
err_close:
sys_close(exec_fileno);
err:
return ret;
} }