📄 irixelf.c
字号:
*name = NULL; for(i = 0; i < pnum; i++, epp++) { if (epp->p_type != PT_INTERP) continue; /* It is illegal to have two interpreters for one executable. */ if (*name != NULL) goto out; *name = (char *) kmalloc((epp->p_filesz + strlen(IRIX_INTERP_PREFIX)), GFP_KERNEL); if (!*name) return -ENOMEM; strcpy(*name, IRIX_INTERP_PREFIX); retval = kernel_read(bprm->file, epp->p_offset, (*name + 16), epp->p_filesz); if (retval < 0) goto out; file = open_exec(*name); if (IS_ERR(file)) { retval = PTR_ERR(file); goto out; } retval = kernel_read(file, 0, bprm->buf, 128); if (retval < 0) goto dput_and_out; *interp_elf_ex = *(struct elfhdr *) bprm->buf; } *interpreter = file; return 0;dput_and_out: fput(file);out: kfree(*name); return retval;}static inline int verify_irix_interpreter(struct elfhdr *ihp){ if (memcmp(ihp->e_ident, ELFMAG, SELFMAG) != 0) return -ELIBBAD; return 0;}#define EXEC_MAP_FLAGS (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE)static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnum, unsigned int *estack, unsigned int *laddr, unsigned int *scode, unsigned int *ebss, unsigned int *ecode, unsigned int *edata, unsigned int *ebrk){ unsigned int tmp; int i, prot; for(i = 0; i < pnum; i++, epp++) { if(epp->p_type != PT_LOAD) continue; /* Map it. */ prot = (epp->p_flags & PF_R) ? PROT_READ : 0; prot |= (epp->p_flags & PF_W) ? PROT_WRITE : 0; prot |= (epp->p_flags & PF_X) ? PROT_EXEC : 0; down(¤t->mm->mmap_sem); (void) do_mmap(fp, (epp->p_vaddr & 0xfffff000), (epp->p_filesz + (epp->p_vaddr & 0xfff)), prot, EXEC_MAP_FLAGS, (epp->p_offset & 0xfffff000)); up(¤t->mm->mmap_sem); /* Fixup location tracking vars. */ if((epp->p_vaddr & 0xfffff000) < *estack) *estack = (epp->p_vaddr & 0xfffff000); if(!*laddr) *laddr = epp->p_vaddr - epp->p_offset; if(epp->p_vaddr < *scode) *scode = epp->p_vaddr; tmp = epp->p_vaddr + epp->p_filesz; if(tmp > *ebss) *ebss = tmp; if((epp->p_flags & PF_X) && *ecode < tmp) *ecode = tmp; if(*edata < tmp) *edata = tmp; tmp = epp->p_vaddr + epp->p_memsz; if(tmp > *ebrk) *ebrk = tmp; }}static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp, struct file *interp, unsigned int *iladdr, int pnum, mm_segment_t old_fs, unsigned int *eentry){ int i; *eentry = 0xffffffff; for(i = 0; i < pnum; i++, epp++) { if(epp->p_type != PT_INTERP) continue; /* We should have fielded this error elsewhere... */ if(*eentry != 0xffffffff) return -1; set_fs(old_fs); *eentry = load_irix_interp(ihp, interp, iladdr); old_fs = get_fs(); set_fs(get_ds()); fput(interp); if (*eentry == 0xffffffff) return -1; } return 0;}/* * IRIX maps a page at 0x200000 that holds information about the * process and the system, here we map the page and fill the * structure */void irix_map_prda_page (void){ unsigned long v; struct prda *pp; v = do_brk (PRDA_ADDRESS, PAGE_SIZE); if (v < 0) return; pp = (struct prda *) v; pp->prda_sys.t_pid = current->pid; pp->prda_sys.t_prid = read_32bit_cp0_register (CP0_PRID); pp->prda_sys.t_rpid = current->pid; /* We leave the rest set to zero */} /* 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 fucking 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(¤t->mm->mmap_sem); (void) do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); up(¤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;}/* This is really simpleminded and specialized - we are loading an * a.out library that is given an ELF header. */static int load_irix_library(struct file *file){ struct elfhdr elf_ex; struct elf_phdr *elf_phdata = NULL; unsigned int len = 0; int elf_bss = 0; int retval; unsigned int bss; int error; int i,j, k; error = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex)); if (error != sizeof(elf_ex)) return -ENOEXEC; if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0) return -ENOEXEC; /* First of all, some simple consistency checks. */ if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || !irix_elf_check_arch(&elf_ex) || !file->f_op->mmap) return -ENOEXEC; /* Now read in all of the header information. */ if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) return -ENOEXEC; elf_phdata = (struct elf_phdr *) kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL); if (elf_phdata == NULL) return -ENOMEM; retval = kernel_read(file, elf_ex.e_phoff, (char *) elf_phdata, sizeof(struct elf_phdr) * elf_ex.e_phnum); j = 0; for(i=0; i<elf_ex.e_phnum; i++) if((elf_phdata + i)->p_type == PT_LOAD) j++; if(j != 1) { kfree(elf_phdata); return -ENOEXEC; } while(elf_phdata->p_type != PT_LOAD) elf_phdata++; /* Now use mmap to map the library into memory. */ down(¤t->mm->mmap_sem); error = do_mmap(file, elf_phdata->p_vaddr & 0xfffff000, elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, elf_phdata->p_offset & 0xfffff000); up(¤t->mm->mmap_sem); k = elf_phdata->p_vaddr + elf_phdata->p_filesz; if (k > elf_bss) elf_bss = k; if (error != (elf_phdata->p_vaddr & 0xfffff000)) { kfree(elf_phdata); return error; } padzero(elf_bss); len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000; bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; if (bss > len) do_brk(len, bss-len);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -