*/
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/mman.h>
-#include <linux/a.out.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/string.h>
#endif
static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
-static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file);
+static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
static struct linux_binfmt flat_format = {
.module = THIS_MODULE,
* Currently only a stub-function.
*/
-static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file)
+static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
{
printk("Process %s:%d received signr %d and should have core dumped\n",
current->comm, current->pid, (int) signr);
char * p = (char*)pp;
int argc = bprm->argc;
int envc = bprm->envc;
- char dummy;
+ char uninitialized_var(dummy);
sp = (unsigned long *) ((-(unsigned long)sizeof(char *))&(unsigned long) p);
kfree(buf);
out_free:
kfree(strm.workspace);
-out:
return retval;
}
unsigned long textpos = 0, datapos = 0, result;
unsigned long realdatastart = 0;
unsigned long text_len, data_len, bss_len, stack_len, flags;
- unsigned long memp = 0; /* for finding the brk area */
+ unsigned long len, reallen, memp = 0;
unsigned long extra, rlim;
unsigned long *reloc = 0, *rp;
struct inode *inode;
loff_t fpos;
unsigned long start_code, end_code;
int ret;
- int exec_fileno;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
- inode = bprm->file->f_dentry->d_inode;
+ inode = bprm->file->f_path.dentry->d_inode;
text_len = ntohl(hdr->data_start);
data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start);
if (strncmp(hdr->magic, "bFLT", 4)) {
/*
+ * Previously, here was a printk to tell people
+ * "BINFMT_FLAT: bad header magic".
+ * But for the kernel which also use ELF FD-PIC format, this
+ * error message is confusing.
* because a lot of people do not manage to produce good
- * flat binaries, we leave this printk to help them realise
- * the problem. We only print the error if its not a script file
*/
- if (strncmp(hdr->magic, "#!", 2))
- printk("BINFMT_FLAT: bad header magic\n");
ret = -ENOEXEC;
goto err;
}
printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename);
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%lx and 0x%lx)\n",
+ rev, FLAT_VERSION, OLD_FLAT_VERSION);
ret = -ENOEXEC;
goto err;
}
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 */
if (id == 0) {
result = flush_old_exec(bprm);
if (result) {
ret = result;
- goto err_close;
+ goto err;
}
/* OK, This is the point of no return */
- set_personality(PER_LINUX);
+ set_personality(PER_LINUX_32BIT);
}
/*
* calculate the extra space we need to map in
*/
- extra = max(bss_len + stack_len, relocs * sizeof(unsigned long));
+ extra = max_t(unsigned long, bss_len + stack_len,
+ relocs * sizeof(unsigned long));
/*
* there are a couple of cases here, the separate code/data
DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
down_write(¤t->mm->mmap_sem);
- textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE, 0);
+ textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
+ MAP_PRIVATE|MAP_EXECUTABLE, 0);
up_write(¤t->mm->mmap_sem);
if (!textpos || textpos >= (unsigned long) -4096) {
if (!textpos)
textpos = (unsigned long) -ENOMEM;
printk("Unable to mmap process text, errno %d\n", (int)-textpos);
ret = textpos;
- goto err_close;
+ goto err;
}
+ len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
down_write(¤t->mm->mmap_sem);
- realdatastart = do_mmap(0, 0, data_len + extra +
- MAX_SHARED_LIBS * sizeof(unsigned long),
- PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
+ realdatastart = do_mmap(0, 0, len,
+ PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
+ /* Remap to use all availabe slack region space */
+ if (realdatastart && (realdatastart < (unsigned long)-4096)) {
+ reallen = ksize((void *)realdatastart);
+ if (reallen > len) {
+ realdatastart = do_mremap(realdatastart, len,
+ reallen, MREMAP_FIXED, realdatastart);
+ }
+ }
up_write(¤t->mm->mmap_sem);
if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
if (!realdatastart)
realdatastart = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process data, errno %d\n",
- (int)-datapos);
+ (int)-realdatastart);
do_munmap(current->mm, textpos, text_len);
ret = realdatastart;
- goto err_close;
+ goto err;
}
datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
do_munmap(current->mm, textpos, text_len);
do_munmap(current->mm, realdatastart, data_len + extra);
ret = result;
- goto err_close;
+ goto err;
}
reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
} else {
+ len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
down_write(¤t->mm->mmap_sem);
- textpos = do_mmap(0, 0, text_len + data_len + extra +
- MAX_SHARED_LIBS * sizeof(unsigned long),
- PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
+ textpos = do_mmap(0, 0, len,
+ PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
+ /* Remap to use all availabe slack region space */
+ if (textpos && (textpos < (unsigned long) -4096)) {
+ reallen = ksize((void *)textpos);
+ if (reallen > len) {
+ textpos = do_mremap(textpos, len, reallen,
+ MREMAP_FIXED, textpos);
+ }
+ }
up_write(¤t->mm->mmap_sem);
+
if (!textpos || textpos >= (unsigned long) -4096) {
if (!textpos)
textpos = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process text/data, errno %d\n",
(int)-textpos);
ret = textpos;
- goto err_close;
+ goto err;
}
realdatastart = textpos + ntohl(hdr->data_start);
do_munmap(current->mm, textpos, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long));
ret = result;
- goto err_close;
+ goto err;
}
}
addr = calc_reloc(*rp, libinfo, id, 0);
if (addr == RELOC_FAILED) {
ret = -ENOEXEC;
- goto err_close;
+ goto err;
}
*rp = addr;
}
* __start to address 4 so that is okay).
*/
if (rev > OLD_FLAT_VERSION) {
+ unsigned long persistent = 0;
for (i=0; i < relocs; i++) {
unsigned long addr, relval;
relocated (of course, the address has to be
relocated first). */
relval = ntohl(reloc[i]);
+ if (flat_set_persistent (relval, &persistent))
+ continue;
addr = flat_get_relocate_addr(relval);
rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
if (rp == (unsigned long *)RELOC_FAILED) {
ret = -ENOEXEC;
- goto err_close;
+ goto err;
}
/* Get the pointer's value. */
- addr = flat_get_addr_from_rp(rp, relval, flags);
+ addr = flat_get_addr_from_rp(rp, relval, flags,
+ &persistent);
if (addr != 0) {
/*
* Do the relocation. PIC relocs in the data section are
addr = calc_reloc(addr, libinfo, id, 0);
if (addr == RELOC_FAILED) {
ret = -ENOEXEC;
- goto err_close;
+ goto err;
}
/* Write back the relocated pointer. */
stack_len);
return 0;
-err_close:
- sys_close(exec_fileno);
err:
return ret;
}
return register_binfmt(&flat_format);
}
-static void __exit exit_flat_binfmt(void)
-{
- unregister_binfmt(&flat_format);
-}
-
/****************************************************************************/
core_initcall(init_flat_binfmt);
-module_exit(exit_flat_binfmt);
/****************************************************************************/