[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:
parent
f516342745
commit
1ad3dcc09c
|
@ -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(¤t->mm->mmap_sem);
|
down_write(¤t->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue