/* Called through irix_syssgi() to map an elf image given an FD, * a phdr ptr USER_PHDRP in userspace, and a count CNT telling how many * phdrs there are in the USER_PHDRP array. We return the vaddr the * first phdr was successfully mapped to. */ unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt) { unsigned long type, vaddr, filesz, offset, flags; struct elf_phdr __user *hp; struct file *filp; int i, retval; pr_debug("irix_mapelf: fd[%d] user_phdrp[%p] cnt[%d]\n", fd, user_phdrp, cnt); /* First get the verification out of the way. */ hp = user_phdrp; if (!access_ok(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt))) { pr_debug("irix_mapelf: bad pointer to ELF PHDR!\n"); return -EFAULT; } dump_phdrs(user_phdrp, cnt); for (i = 0; i < cnt; i++, hp++) { if (__get_user(type, &hp->p_type)) return -EFAULT; if (type != PT_LOAD) { printk("irix_mapelf: One section is not PT_LOAD!\n"); return -ENOEXEC; } } filp = fget(fd); if (!filp) return -EACCES; if (!filp->f_op) { printk("irix_mapelf: Bogon filp!\n"); fput(filp); return -EACCES; } hp = user_phdrp; for (i = 0; i < cnt; i++, hp++) { int prot; retval = __get_user(vaddr, &hp->p_vaddr); retval |= __get_user(filesz, &hp->p_filesz); retval |= __get_user(offset, &hp->p_offset); retval |= __get_user(flags, &hp->p_flags); if (retval) return retval; prot = (flags & PF_R) ? PROT_READ : 0; prot |= (flags & PF_W) ? PROT_WRITE : 0; prot |= (flags & PF_X) ? PROT_EXEC : 0; down_write(¤t->mm->mmap_sem); retval = do_mmap(filp, (vaddr & 0xfffff000), (filesz + (vaddr & 0xfff)), prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), (offset & 0xfffff000)); up_write(¤t->mm->mmap_sem); if (retval != (vaddr & 0xfffff000)) { printk("irix_mapelf: do_mmap fails with %d!\n", retval); fput(filp); return retval; } } pr_debug("irix_mapelf: Success, returning %08lx\n", (unsigned long) user_phdrp->p_vaddr); fput(filp); if (__get_user(vaddr, &user_phdrp->p_vaddr)) return -EFAULT; return vaddr; }
/* These are the functions used to load ELF style executables and shared * libraries. There is no binary dependent code anywhere else. */ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct elfhdr elf_ex, interp_elf_ex; struct file *interpreter; struct elf_phdr *elf_phdata, *elf_ihdr, *elf_ephdr; unsigned int load_addr, elf_bss, elf_brk; unsigned int elf_entry, interp_load_addr = 0; unsigned int start_code, end_code, end_data, elf_stack; int retval, has_interp, has_ephdr, size, i; char *elf_interpreter; mm_segment_t old_fs; load_addr = 0; has_interp = has_ephdr = 0; elf_ihdr = elf_ephdr = NULL; elf_ex = *((struct elfhdr *) bprm->buf); retval = -ENOEXEC; if (verify_binary(&elf_ex, bprm)) goto out; /* * Telling -o32 static binaries from Linux and Irix apart from each * other is difficult. There are 2 differences to be noted for static * binaries from the 2 operating systems: * * 1) Irix binaries have their .text section before their .init * section. Linux binaries are just the opposite. * * 2) Irix binaries usually have <= 12 sections and Linux * binaries have > 20. * * We will use Method #2 since Method #1 would require us to read in * the section headers which is way too much overhead. This appears * to work for everything we have ran into so far. If anyone has a * better method to tell the binaries apart, I'm listening. */ if (elf_ex.e_shnum > 20) goto out; print_elfhdr(&elf_ex); /* Now read in all of the header information */ size = elf_ex.e_phentsize * elf_ex.e_phnum; if (size > 65536) goto out; elf_phdata = kmalloc(size, GFP_KERNEL); if (elf_phdata == NULL) { retval = -ENOMEM; goto out; } retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *)elf_phdata, size); if (retval < 0) goto out_free_ph; dump_phdrs(elf_phdata, elf_ex.e_phnum); /* Set some things for later. */ for (i = 0; i < elf_ex.e_phnum; i++) { switch (elf_phdata[i].p_type) { case PT_INTERP: has_interp = 1; elf_ihdr = &elf_phdata[i]; break; case PT_PHDR: has_ephdr = 1; elf_ephdr = &elf_phdata[i]; break; }; } pr_debug("\n"); elf_bss = 0; elf_brk = 0; elf_stack = 0xffffffff; elf_interpreter = NULL; start_code = 0xffffffff; end_code = 0; end_data = 0; /* * If we get a return value, we change the value to be ENOEXEC * so that we can exit gracefully and the main binary format * search loop in 'fs/exec.c' will move onto the next handler * which should be the normal ELF binary handler. */ retval = look_for_irix_interpreter(&elf_interpreter, &interpreter, &interp_elf_ex, elf_phdata, bprm, elf_ex.e_phnum); if (retval) { retval = -ENOEXEC; goto out_free_file; } if (elf_interpreter) { retval = verify_irix_interpreter(&interp_elf_ex); if (retval) goto out_free_interp; } /* OK, we are done with that, now set up the arg stuff, * and then start this sucker up. */ retval = -E2BIG; if (!bprm->sh_bang && !bprm->p) goto out_free_interp; /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) goto out_free_dentry; /* OK, This is the point of no return */ current->mm->end_data = 0; current->mm->end_code = 0; current->mm->mmap = NULL; current->flags &= ~PF_FORKNOEXEC; elf_entry = (unsigned int) elf_ex.e_entry; /* Do this so that we can load the interpreter, if need be. We will * change some of these later. */ setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); current->mm->start_stack = bprm->p; /* At this point, we assume that the image should be loaded at * fixed address, not at a variable address. */ old_fs = get_fs(); set_fs(get_ds()); map_executable(bprm->file, elf_phdata, elf_ex.e_phnum, &elf_stack, &load_addr, &start_code, &elf_bss, &end_code, &end_data, &elf_brk); if (elf_interpreter) { retval = map_interpreter(elf_phdata, &interp_elf_ex, interpreter, &interp_load_addr, elf_ex.e_phnum, old_fs, &elf_entry); kfree(elf_interpreter); if (retval) { set_fs(old_fs); printk("Unable to load IRIX ELF interpreter\n"); send_sig(SIGSEGV, current, 0); retval = 0; goto out_free_file; } } set_fs(old_fs); kfree(elf_phdata); set_personality(PER_IRIX32); set_binfmt(&irix_format); compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; bprm->p = (unsigned long) create_irix_tables((char *)bprm->p, bprm->argc, bprm->envc, (elf_interpreter ? &elf_ex : NULL), load_addr, interp_load_addr, regs, elf_ephdr); current->mm->start_brk = current->mm->brk = elf_brk; current->mm->end_code = end_code; current->mm->start_code = start_code; current->mm->end_data = end_data; current->mm->start_stack = bprm->p; /* Calling set_brk effectively mmaps the pages that we need for the * bss and break sections. */ set_brk(elf_bss, elf_brk); /* * IRIX maps a page at 0x200000 which holds some system * information. Programs depend on this. */ irix_map_prda_page(); padzero(elf_bss); pr_debug("(start_brk) %lx\n" , (long) current->mm->start_brk); pr_debug("(end_code) %lx\n" , (long) current->mm->end_code); pr_debug("(start_code) %lx\n" , (long) current->mm->start_code); pr_debug("(end_data) %lx\n" , (long) current->mm->end_data); pr_debug("(start_stack) %lx\n" , (long) current->mm->start_stack); pr_debug("(brk) %lx\n" , (long) current->mm->brk); #if 0 /* XXX No f*****g way dude... */ /* Why this, you ask??? Well SVr4 maps page 0 as read-only, * and some applications "depend" upon this behavior. * Since we do not have the power to recompile these, we * emulate the SVr4 behavior. Sigh. */ down_write(¤t->mm->mmap_sem); (void) do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); up_write(¤t->mm->mmap_sem); #endif start_thread(regs, elf_entry, bprm->p); if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); return 0; out: return retval; out_free_dentry: allow_write_access(interpreter); fput(interpreter); out_free_interp: kfree(elf_interpreter); out_free_file: out_free_ph: kfree(elf_phdata); goto out; }
/* Called through irix_syssgi() to map an elf image given an FD, * a phdr ptr USER_PHDRP in userspace, and a count CNT telling how many * phdrs there are in the USER_PHDRP array. We return the vaddr the * first phdr was successfully mapped to. */ unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt) { struct elf_phdr *hp; struct file *filp; int i, retval; #ifdef DEBUG_ELF printk("irix_mapelf: fd[%d] user_phdrp[%p] cnt[%d]\n", fd, user_phdrp, cnt); #endif /* First get the verification out of the way. */ hp = user_phdrp; retval = verify_area(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt)); if(retval) { #ifdef DEBUG_ELF printk("irix_mapelf: verify_area fails!\n"); #endif return retval; } #ifdef DEBUG_ELF dump_phdrs(user_phdrp, cnt); #endif for(i = 0; i < cnt; i++, hp++) if(hp->p_type != PT_LOAD) { printk("irix_mapelf: One section is not PT_LOAD!\n"); return -ENOEXEC; } filp = fget(fd); if (!filp) return -EACCES; if(!filp->f_op) { printk("irix_mapelf: Bogon filp!\n"); fput(filp); return -EACCES; } hp = user_phdrp; for(i = 0; i < cnt; i++, hp++) { int prot; prot = (hp->p_flags & PF_R) ? PROT_READ : 0; prot |= (hp->p_flags & PF_W) ? PROT_WRITE : 0; prot |= (hp->p_flags & PF_X) ? PROT_EXEC : 0; down_write(¤t->mm->mmap_sem); retval = do_mmap(filp, (hp->p_vaddr & 0xfffff000), (hp->p_filesz + (hp->p_vaddr & 0xfff)), prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), (hp->p_offset & 0xfffff000)); up_write(¤t->mm->mmap_sem); if(retval != (hp->p_vaddr & 0xfffff000)) { printk("irix_mapelf: do_mmap fails with %d!\n", retval); fput(filp); return retval; } } #ifdef DEBUG_ELF printk("irix_mapelf: Success, returning %08lx\n", user_phdrp->p_vaddr); #endif fput(filp); return user_phdrp->p_vaddr; }
/* This is much more generalized than the library routine read function, * so we keep this separate. Technically the library read function * is only provided so that we can read a.out libraries that have * an ELF header. */ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, struct file * interpreter, unsigned int *interp_load_addr) { struct elf_phdr *elf_phdata = NULL; struct elf_phdr *eppnt; unsigned int len; unsigned int load_addr; int elf_bss; int retval; unsigned int last_bss; int error; int i; unsigned int k; elf_bss = 0; last_bss = 0; error = load_addr = 0; print_elfhdr(interp_elf_ex); /* First of all, some simple consistency checks */ if ((interp_elf_ex->e_type != ET_EXEC && interp_elf_ex->e_type != ET_DYN) || !interpreter->f_op->mmap) { printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type); return 0xffffffff; } /* Now read in all of the header information */ if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) { printk("IRIX interp header bigger than a page (%d)\n", (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum)); return 0xffffffff; } elf_phdata = kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL); if (!elf_phdata) { printk("Cannot kmalloc phdata for IRIX interp.\n"); return 0xffffffff; } /* If the size of this structure has changed, then punt, since * we will be doing the wrong thing. */ if (interp_elf_ex->e_phentsize != 32) { printk("IRIX interp e_phentsize == %d != 32 ", interp_elf_ex->e_phentsize); kfree(elf_phdata); return 0xffffffff; } retval = kernel_read(interpreter, interp_elf_ex->e_phoff, (char *) elf_phdata, sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); dump_phdrs(elf_phdata, interp_elf_ex->e_phnum); eppnt = elf_phdata; for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { if (eppnt->p_type == PT_LOAD) { int elf_type = MAP_PRIVATE | MAP_DENYWRITE; int elf_prot = 0; unsigned long vaddr = 0; if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; elf_type |= MAP_FIXED; vaddr = eppnt->p_vaddr; pr_debug("INTERP do_mmap" "(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ", interpreter, vaddr, (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)), (unsigned long) elf_prot, (unsigned long) elf_type, (unsigned long) (eppnt->p_offset & 0xfffff000)); down_write(¤t->mm->mmap_sem); error = do_mmap(interpreter, vaddr, eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), elf_prot, elf_type, eppnt->p_offset & 0xfffff000); up_write(¤t->mm->mmap_sem); if (error < 0 && error > -1024) { printk("Aieee IRIX interp mmap error=%d\n", error); break; /* Real error */ } pr_debug("error=%08lx ", (unsigned long) error); if (!load_addr && interp_elf_ex->e_type == ET_DYN) { load_addr = error; pr_debug("load_addr = error "); } /* * Find the end of the file mapping for this phdr, and * keep track of the largest address we see for this. */ k = eppnt->p_vaddr + eppnt->p_filesz; if (k > elf_bss) elf_bss = k; /* Do the same thing for the memory mapping - between * elf_bss and last_bss is the bss section. */ k = eppnt->p_memsz + eppnt->p_vaddr; if (k > last_bss) last_bss = k; pr_debug("\n"); } } /* Now use mmap to map the library into memory. */ if (error < 0 && error > -1024) { pr_debug("got error %d\n", error); kfree(elf_phdata); return 0xffffffff; } /* Now fill out the bss section. First pad the last page up * to the page boundary, and then perform a mmap to make sure * that there are zero-mapped pages up to and including the * last bss page. */ pr_debug("padzero(%08lx) ", (unsigned long) (elf_bss)); padzero(elf_bss); len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */ pr_debug("last_bss[%08lx] len[%08lx]\n", (unsigned long) last_bss, (unsigned long) len); /* Map the last of the bss segment */ if (last_bss > len) { down_write(¤t->mm->mmap_sem); do_brk(len, (last_bss - len)); up_write(¤t->mm->mmap_sem); } kfree(elf_phdata); *interp_load_addr = load_addr; return ((unsigned int) interp_elf_ex->e_entry); }
/* These are the functions used to load ELF style executables and shared * libraries. There is no binary dependent code anywhere else. */ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct elfhdr elf_ex, interp_elf_ex; struct file *interpreter; struct elf_phdr *elf_phdata, *elf_ihdr, *elf_ephdr; unsigned int load_addr, elf_bss, elf_brk; unsigned int elf_entry, interp_load_addr = 0; unsigned int start_code, end_code, end_data, elf_stack; int retval, has_interp, has_ephdr, size, i; char *elf_interpreter; mm_segment_t old_fs; load_addr = 0; has_interp = has_ephdr = 0; elf_ihdr = elf_ephdr = 0; elf_ex = *((struct elfhdr *) bprm->buf); retval = -ENOEXEC; if (verify_binary(&elf_ex, bprm)) goto out; #ifdef DEBUG_ELF print_elfhdr(&elf_ex); #endif /* Now read in all of the header information */ size = elf_ex.e_phentsize * elf_ex.e_phnum; if (size > 65536) goto out; elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); if (elf_phdata == NULL) { retval = -ENOMEM; goto out; } retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *)elf_phdata, size); if (retval < 0) goto out_free_ph; #ifdef DEBUG_ELF dump_phdrs(elf_phdata, elf_ex.e_phnum); #endif /* Set some things for later. */ for(i = 0; i < elf_ex.e_phnum; i++) { switch(elf_phdata[i].p_type) { case PT_INTERP: has_interp = 1; elf_ihdr = &elf_phdata[i]; break; case PT_PHDR: has_ephdr = 1; elf_ephdr = &elf_phdata[i]; break; }; } #ifdef DEBUG_ELF printk("\n"); #endif elf_bss = 0; elf_brk = 0; elf_stack = 0xffffffff; elf_interpreter = NULL; start_code = 0xffffffff; end_code = 0; end_data = 0; retval = look_for_irix_interpreter(&elf_interpreter, &interpreter, &interp_elf_ex, elf_phdata, bprm, elf_ex.e_phnum); if (retval) goto out_free_file; if (elf_interpreter) { retval = verify_irix_interpreter(&interp_elf_ex); if(retval) goto out_free_interp; } /* OK, we are done with that, now set up the arg stuff, * and then start this sucker up. */ retval = -E2BIG; if (!bprm->sh_bang && !bprm->p) goto out_free_interp; /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) goto out_free_dentry; /* OK, This is the point of no return */ current->mm->end_data = 0; current->mm->end_code = 0; current->mm->mmap = NULL; current->flags &= ~PF_FORKNOEXEC; elf_entry = (unsigned int) elf_ex.e_entry; /* Do this so that we can load the interpreter, if need be. We will * change some of these later. */ current->mm->rss = 0; setup_arg_pages(bprm); current->mm->start_stack = bprm->p; /* At this point, we assume that the image should be loaded at * fixed address, not at a variable address. */ old_fs = get_fs(); set_fs(get_ds()); map_executable(bprm->file, elf_phdata, elf_ex.e_phnum, &elf_stack, &load_addr, &start_code, &elf_bss, &end_code, &end_data, &elf_brk); if(elf_interpreter) { retval = map_interpreter(elf_phdata, &interp_elf_ex, interpreter, &interp_load_addr, elf_ex.e_phnum, old_fs, &elf_entry); kfree(elf_interpreter); if(retval) { set_fs(old_fs); printk("Unable to load IRIX ELF interpreter\n"); send_sig(SIGSEGV, current, 0); retval = 0; goto out_free_file; } } set_fs(old_fs); kfree(elf_phdata); set_personality(PER_IRIX32); set_binfmt(&irix_format); compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; bprm->p = (unsigned long) create_irix_tables((char *)bprm->p, bprm->argc, bprm->envc, (elf_interpreter ? &elf_ex : NULL), load_addr, interp_load_addr, regs, elf_ephdr); current->mm->start_brk = current->mm->brk = elf_brk; current->mm->end_code = end_code; current->mm->start_code = start_code; current->mm->end_data = end_data; current->mm->start_stack = bprm->p; /* Calling set_brk effectively mmaps the pages that we need for the * bss and break sections. */ set_brk(elf_bss, elf_brk); /* * IRIX maps a page at 0x200000 which holds some system * information. Programs depend on this. */ irix_map_prda_page (); padzero(elf_bss); #ifdef DEBUG_ELF printk("(start_brk) %lx\n" , (long) current->mm->start_brk); printk("(end_code) %lx\n" , (long) current->mm->end_code); printk("(start_code) %lx\n" , (long) current->mm->start_code); printk("(end_data) %lx\n" , (long) current->mm->end_data); printk("(start_stack) %lx\n" , (long) current->mm->start_stack); printk("(brk) %lx\n" , (long) current->mm->brk); #endif #if 0 /* XXX No f*****g way dude... */ /* Why this, you ask??? Well SVr4 maps page 0 as read-only, * and some applications "depend" upon this behavior. * Since we do not have the power to recompile these, we * emulate the SVr4 behavior. Sigh. */ down_write(¤t->mm->mmap_sem); (void) do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); up_write(¤t->mm->mmap_sem); #endif start_thread(regs, elf_entry, bprm->p); if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); return 0; out: return retval; out_free_dentry: allow_write_access(interpreter); fput(interpreter); out_free_interp: if (elf_interpreter) kfree(elf_interpreter); out_free_file: out_free_ph: kfree (elf_phdata); goto out; }