X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=fs%2Fbinfmt_flat.c;h=a2796651e75690eb8e8a875146be852bfb1d637b;hb=6c28705418de012216161b14a2ff1dda3da3d786;hp=b1c902e319c13dfc82200753f54b4f99102dfb51;hpb=df88912a2165f56a7402db80126cf8ea075221fe;p=safe%2Fjmp%2Flinux-2.6 diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index b1c902e..a279665 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -16,12 +16,10 @@ */ #include -#include #include #include #include #include -#include #include #include #include @@ -43,6 +41,7 @@ #include #include #include +#include /****************************************************************************/ @@ -56,6 +55,18 @@ #define DBG_FLT(a...) #endif +/* + * User data (stack, data section and bss) needs to be aligned + * for the same reasons as SLAB memory is, and to the same amount. + * Avoid duplicating architecture specific code by using the same + * macro as with SLAB allocation: + */ +#ifdef ARCH_SLAB_MINALIGN +#define FLAT_DATA_ALIGN (ARCH_SLAB_MINALIGN) +#else +#define FLAT_DATA_ALIGN (sizeof(void *)) +#endif + #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */ #define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */ @@ -76,7 +87,7 @@ static int load_flat_shared_library(int id, struct lib_info *p); #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, @@ -91,7 +102,7 @@ static struct linux_binfmt flat_format = { * 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); @@ -114,22 +125,20 @@ static unsigned long create_flat_tables( char * p = (char*)pp; int argc = bprm->argc; int envc = bprm->envc; - char dummy; - - sp = (unsigned long *) ((-(unsigned long)sizeof(char *))&(unsigned long) p); + char uninitialized_var(dummy); - sp -= envc+1; - envp = sp; - sp -= argc+1; - argv = sp; + sp = (unsigned long *)p; + sp -= (envc + argc + 2) + 1 + (flat_argvp_envp_on_stack() ? 2 : 0); + sp = (unsigned long *) ((unsigned long)sp & -FLAT_DATA_ALIGN); + argv = sp + 1 + (flat_argvp_envp_on_stack() ? 2 : 0); + envp = argv + (argc + 1); - flat_stack_align(sp); if (flat_argvp_envp_on_stack()) { - --sp; put_user((unsigned long) envp, sp); - --sp; put_user((unsigned long) argv, sp); + put_user((unsigned long) envp, sp + 2); + put_user((unsigned long) argv, sp + 1); } - put_user(argc,--sp); + put_user(argc, sp); current->mm->arg_start = (unsigned long) p; while (argc-->0) { put_user((unsigned long) p, argv++); @@ -231,13 +240,13 @@ static int decompress_exec( 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"); @@ -245,7 +254,7 @@ static int decompress_exec( } } 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"); @@ -269,8 +278,6 @@ static int decompress_exec( ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); if (ret <= 0) break; - if (ret >= (unsigned long) -4096) - break; len -= ret; strm.next_in = buf; @@ -291,7 +298,6 @@ out_free_buf: kfree(buf); out_free: kfree(strm.workspace); -out: return retval; } @@ -327,7 +333,7 @@ calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp) "(%d != %d)", (unsigned) r, curid, id); goto failed; } else if ( ! p->lib_list[id].loaded && - load_flat_shared_library(id, p) > (unsigned long) -4096) { + IS_ERR_VALUE(load_flat_shared_library(id, p))) { printk("BINFMT_FLAT: failed to load library %d", id); goto failed; } @@ -420,8 +426,8 @@ static int load_flat_file(struct linux_binprm * bprm, 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; @@ -430,7 +436,7 @@ static int load_flat_file(struct linux_binprm * bprm, 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); @@ -446,12 +452,12 @@ static int load_flat_file(struct linux_binprm * bprm, 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; } @@ -460,7 +466,9 @@ static int load_flat_file(struct linux_binprm * bprm, 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; } @@ -510,13 +518,14 @@ static int load_flat_file(struct linux_binprm * bprm, } /* 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 @@ -531,9 +540,10 @@ static int load_flat_file(struct linux_binprm * bprm, 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 || IS_ERR_VALUE(textpos)) { if (!textpos) textpos = (unsigned long) -ENOMEM; printk("Unable to mmap process text, errno %d\n", (int)-textpos); @@ -541,22 +551,25 @@ static int load_flat_file(struct linux_binprm * bprm, 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 == 0 || IS_ERR_VALUE(realdatastart)) { 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; } - datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); + datapos = ALIGN(realdatastart + + MAX_SHARED_LIBS * sizeof(unsigned long), + FLAT_DATA_ALIGN); DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n", (int)(data_len + bss_len + stack_len), (int)datapos); @@ -572,7 +585,7 @@ static int load_flat_file(struct linux_binprm * bprm, result = bprm->file->f_op->read(bprm->file, (char *) datapos, data_len + (relocs * sizeof(unsigned long)), &fpos); } - if (result >= (unsigned long)-4096) { + if (IS_ERR_VALUE(result)) { 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); @@ -582,15 +595,17 @@ static int load_flat_file(struct linux_binprm * bprm, 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 || IS_ERR_VALUE(textpos)) { if (!textpos) textpos = (unsigned long) -ENOMEM; printk("Unable to allocate RAM for process text/data, errno %d\n", @@ -600,11 +615,14 @@ static int load_flat_file(struct linux_binprm * bprm, } realdatastart = textpos + ntohl(hdr->data_start); - datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); - reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) + - MAX_SHARED_LIBS * sizeof(unsigned long)); - memp = textpos; + datapos = ALIGN(realdatastart + + MAX_SHARED_LIBS * sizeof(unsigned long), + FLAT_DATA_ALIGN); + reloc = (unsigned long *) + (datapos + (ntohl(hdr->reloc_start) - text_len)); + memp = textpos; + memp_size = len; #ifdef CONFIG_BINFMT_ZFLAT /* * load it all in and treat it like a RAM load from now on @@ -621,7 +639,7 @@ static int load_flat_file(struct linux_binprm * bprm, fpos = 0; result = bprm->file->f_op->read(bprm->file, (char *) textpos, text_len, &fpos); - if (result < (unsigned long) -4096) + if (!IS_ERR_VALUE(result)) result = decompress_exec(bprm, text_len, (char *) datapos, data_len + (relocs * sizeof(unsigned long)), 0); } @@ -631,13 +649,13 @@ static int load_flat_file(struct linux_binprm * bprm, fpos = 0; result = bprm->file->f_op->read(bprm->file, (char *) textpos, text_len, &fpos); - if (result < (unsigned long) -4096) { + if (!IS_ERR_VALUE(result)) { fpos = ntohl(hdr->data_start); result = bprm->file->f_op->read(bprm->file, (char *) datapos, data_len + (relocs * sizeof(unsigned long)), &fpos); } } - if (result >= (unsigned long)-4096) { + if (IS_ERR_VALUE(result)) { 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)); @@ -662,10 +680,12 @@ static int load_flat_file(struct linux_binprm * bprm, * 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) @@ -726,6 +746,7 @@ static int load_flat_file(struct linux_binprm * bprm, * __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; @@ -733,6 +754,8 @@ static int load_flat_file(struct linux_binprm * bprm, 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) { @@ -741,7 +764,8 @@ static int load_flat_file(struct linux_binprm * bprm, } /* 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 @@ -768,8 +792,8 @@ static int load_flat_file(struct linux_binprm * bprm, /* 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; @@ -802,15 +826,22 @@ static int load_flat_shared_library(int id, struct lib_info *libs) if (IS_ERR(bprm.file)) return res; + bprm.cred = prepare_exec_creds(); + res = -ENOMEM; + if (!bprm.cred) + goto out; + res = prepare_binprm(&bprm); - if (res <= (unsigned long)-4096) + if (!IS_ERR_VALUE(res)) res = load_flat_file(&bprm, libs, id, NULL); - if (bprm.file) { - allow_write_access(bprm.file); - fput(bprm.file); - bprm.file = NULL; - } + + abort_creds(bprm.cred); + +out: + allow_write_access(bprm.file); + fput(bprm.file); + return(res); } @@ -844,10 +875,10 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs) stack_len = TOP_OF_ARGS - bprm->p; /* the strings */ stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */ stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */ - + stack_len += FLAT_DATA_ALIGN - 1; /* reserve for upcoming alignment */ res = load_flat_file(bprm, &libinfo, 0, &stack_len); - if (res > (unsigned long)-4096) + if (IS_ERR_VALUE(res)) return res; /* Update data segment pointers for all libraries */ @@ -858,7 +889,7 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs) (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); @@ -892,15 +923,14 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs) /* 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; } @@ -911,14 +941,8 @@ static int __init init_flat_binfmt(void) 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); /****************************************************************************/