*/
#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>
#include <linux/personality.h>
#include <linux/init.h>
#include <linux/flat.h>
+#include <linux/syscalls.h>
#include <asm/byteorder.h>
#include <asm/system.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);
ret = 10;
if (buf[3] & EXTRA_FIELD) {
ret += 2 + buf[10] + (buf[11] << 8);
- if (unlikely(LBUFSIZE == ret)) {
+ if (unlikely(LBUFSIZE <= ret)) {
DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n");
goto out_free_buf;
}
}
if (buf[3] & ORIG_NAME) {
- for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
+ while (ret < LBUFSIZE && buf[ret++] != 0)
;
if (unlikely(LBUFSIZE == ret)) {
DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
}
}
if (buf[3] & COMMENT) {
- for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
+ while (ret < LBUFSIZE && buf[ret++] != 0)
;
if (unlikely(LBUFSIZE == ret)) {
DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n");
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 extra, rlim;
+ unsigned long len, memp = 0;
+ unsigned long memp_size, extra, rlim;
unsigned long *reloc = 0, *rp;
struct inode *inode;
int i, rev, relocs = 0;
loff_t fpos;
unsigned long start_code, end_code;
+ int ret;
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");
- return -ENOEXEC;
+ ret = -ENOEXEC;
+ goto err;
}
if (flags & FLAT_FLAG_KTRACE)
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);
- return -ENOEXEC;
+ 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;
}
/* Don't allow old format executables to use shared libraries */
if (rev == OLD_FLAT_VERSION && id != 0) {
printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n",
(int) FLAT_VERSION);
- return -ENOEXEC;
+ ret = -ENOEXEC;
+ goto err;
}
/*
#ifndef CONFIG_BINFMT_ZFLAT
if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
printk("Support for ZFLAT executables is not enabled.\n");
- return -ENOEXEC;
+ ret = -ENOEXEC;
+ goto err;
}
#endif
rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
if (rlim >= RLIM_INFINITY)
rlim = ~0;
- if (data_len + bss_len > rlim)
- return -ENOMEM;
+ if (data_len + bss_len > rlim) {
+ ret = -ENOMEM;
+ goto err;
+ }
/* Flush all traces of the currently running executable */
if (id == 0) {
result = flush_old_exec(bprm);
- if (result)
- return result;
+ if (result) {
+ ret = result;
+ 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);
- return(textpos);
+ ret = textpos;
+ goto err;
}
+ len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
+ len = PAGE_ALIGN(len);
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);
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);
- return realdatastart;
+ ret = realdatastart;
+ goto err;
}
datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
printk("Unable to read data+bss, errno %d\n", (int)-result);
do_munmap(current->mm, textpos, text_len);
do_munmap(current->mm, realdatastart, data_len + extra);
- return result;
+ ret = result;
+ goto err;
}
reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
memp = realdatastart;
-
+ memp_size = len;
} else {
+ len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
+ len = PAGE_ALIGN(len);
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);
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);
- return(textpos);
+ ret = textpos;
+ goto err;
}
realdatastart = textpos + ntohl(hdr->data_start);
reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) +
MAX_SHARED_LIBS * sizeof(unsigned long));
memp = textpos;
-
+ memp_size = len;
#ifdef CONFIG_BINFMT_ZFLAT
/*
* load it all in and treat it like a RAM load from now on
printk("Unable to read code+data+bss, errno %d\n",(int)-result);
do_munmap(current->mm, textpos, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long));
- return result;
+ ret = result;
+ goto err;
}
}
* set up the brk stuff, uses any slack left in data/bss/stack
* allocation. We put the brk after the bss (between the bss
* and stack) like other platforms.
+ * Userspace code relies on the stack pointer starting out at
+ * an address right at the end of a page.
*/
current->mm->start_brk = datapos + data_len + bss_len;
current->mm->brk = (current->mm->start_brk + 3) & ~3;
- current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len;
+ current->mm->context.end_brk = memp + memp_size - stack_len;
}
if (flags & FLAT_FLAG_KTRACE)
unsigned long addr;
if (*rp) {
addr = calc_reloc(*rp, libinfo, id, 0);
- if (addr == RELOC_FAILED)
- return -ENOEXEC;
+ if (addr == RELOC_FAILED) {
+ ret = -ENOEXEC;
+ 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)
- return -ENOEXEC;
+ if (rp == (unsigned long *)RELOC_FAILED) {
+ ret = -ENOEXEC;
+ 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
if ((flags & FLAT_FLAG_GOTPIC) == 0)
addr = ntohl(addr);
addr = calc_reloc(addr, libinfo, id, 0);
- if (addr == RELOC_FAILED)
- return -ENOEXEC;
+ if (addr == RELOC_FAILED) {
+ ret = -ENOEXEC;
+ goto err;
+ }
/* Write back the relocated pointer. */
flat_put_addr_at_rp(rp, addr, relval);
/* zero the BSS, BRK and stack areas */
memset((void*)(datapos + data_len), 0, bss_len +
- (memp + ksize((void *) memp) - stack_len - /* end brk */
- libinfo->lib_list[id].start_brk) + /* start brk */
+ (memp + memp_size - stack_len - /* end brk */
+ libinfo->lib_list[id].start_brk) + /* start brk */
stack_len);
return 0;
+err:
+ return ret;
}
(libinfo.lib_list[j].loaded)?
libinfo.lib_list[j].start_data:UNLOADED_LIB;
- compute_creds(bprm);
+ install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
set_binfmt(&flat_format);
/* Stash our initial stack pointer into the mm structure */
current->mm->start_stack = (unsigned long )sp;
-
+#ifdef FLAT_PLAT_INIT
+ FLAT_PLAT_INIT(regs);
+#endif
DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n",
(int)regs, (int)start_addr, (int)current->mm->start_stack);
start_thread(regs, start_addr, current->mm->start_stack);
- if (current->ptrace & PT_PTRACED)
- send_sig(SIGTRAP, current, 0);
-
return 0;
}
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);
/****************************************************************************/