static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct file *interpreter = NULL; /* to shut gcc up */ unsigned long load_addr = 0, load_bias = 0; int load_addr_set = 0; char * elf_interpreter = NULL; unsigned int interpreter_type = INTERPRETER_NONE; unsigned char ibcs2_interpreter = 0; unsigned long error; struct elf_phdr * elf_ppnt, *elf_phdata; unsigned long elf_bss, k, elf_brk; int elf_exec_fileno; int retval, i; unsigned int size; unsigned long elf_entry, interp_load_addr = 0; unsigned long start_code, end_code, start_data, end_data; unsigned long reloc_func_desc = 0; struct elfhdr elf_ex; struct elfhdr interp_elf_ex; struct exec interp_ex; char passed_fileno[6]; struct files_struct *files; /* Get the exec-header */ elf_ex = *((struct elfhdr *) bprm->buf); retval = -ENOEXEC; /* First of all, some simple consistency checks */ if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0) goto out; if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) goto out; if (!elf_check_arch(&elf_ex)) goto out; if (!bprm->file->f_op||!bprm->file->f_op->mmap) goto out; /* Now read in all of the header information */ if (elf_ex.e_phentsize != sizeof(struct elf_phdr)) goto out; if (elf_ex.e_phnum < 1 || elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr)) goto out; size = elf_ex.e_phnum * sizeof(struct elf_phdr); retval = -ENOMEM; elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); if (!elf_phdata) goto out; retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *) elf_phdata, size); if (retval != size) { if (retval >= 0) retval = -EIO; goto out_free_ph; } files = current->files; /* Refcounted so ok */ retval = unshare_files(); if (retval < 0) goto out_free_ph; if (files == current->files) { put_files_struct(files); files = NULL; } /* exec will make our files private anyway, but for the a.out loader stuff we need to do it earlier */ retval = get_unused_fd(); if (retval < 0) goto out_free_fh; get_file(bprm->file); fd_install(elf_exec_fileno = retval, bprm->file); elf_ppnt = elf_phdata; elf_bss = 0; elf_brk = 0; start_code = ~0UL; end_code = 0; start_data = 0; end_data = 0; for (i = 0; i < elf_ex.e_phnum; i++) { if (elf_ppnt->p_type == PT_INTERP) { /* This is the program interpreter used for * shared libraries - for now assume that this * is an a.out format binary */ retval = -ENOEXEC; if (elf_ppnt->p_filesz > PATH_MAX || elf_ppnt->p_filesz < 2) goto out_free_file; retval = -ENOMEM; elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, GFP_KERNEL); if (!elf_interpreter) goto out_free_file; retval = kernel_read(bprm->file, elf_ppnt->p_offset, elf_interpreter, elf_ppnt->p_filesz); if (retval != elf_ppnt->p_filesz) { if (retval >= 0) retval = -EIO; goto out_free_interp; } /* make sure path is NULL terminated */ retval = -ENOEXEC; if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0') goto out_free_interp; /* If the program interpreter is one of these two, * then assume an iBCS2 image. Otherwise assume * a native linux image. */ if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) ibcs2_interpreter = 1; #if 0 printk("Using ELF interpreter %s\n", elf_interpreter); #endif SET_PERSONALITY(elf_ex, ibcs2_interpreter); interpreter = open_exec(elf_interpreter); retval = PTR_ERR(interpreter); if (IS_ERR(interpreter)) goto out_free_interp; retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE); if (retval != BINPRM_BUF_SIZE) { if (retval >= 0) retval = -EIO; goto out_free_dentry; } /* Get the exec headers */ interp_ex = *((struct exec *) bprm->buf); interp_elf_ex = *((struct elfhdr *) bprm->buf); break; } elf_ppnt++; } /* Some simple consistency checks for the interpreter */ if (elf_interpreter) { interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; /* Now figure out which format our binary is */ if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && (N_MAGIC(interp_ex) != QMAGIC)) interpreter_type = INTERPRETER_ELF; if (memcmp(interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) interpreter_type &= ~INTERPRETER_ELF; retval = -ELIBBAD; if (!interpreter_type) goto out_free_dentry; /* Make sure only one type was selected */ if ((interpreter_type & INTERPRETER_ELF) && interpreter_type != INTERPRETER_ELF) { // FIXME - ratelimit this before re-enabling // printk(KERN_WARNING "ELF: Ambiguous type, using ELF\n"); interpreter_type = INTERPRETER_ELF; } /* Verify the interpreter has a valid arch */ if ((interpreter_type == INTERPRETER_ELF) && !elf_check_arch(&interp_elf_ex)) goto out_free_dentry; } else { /* Executables without an interpreter also need a personality */ SET_PERSONALITY(elf_ex, ibcs2_interpreter); } /* OK, we are done with that, now set up the arg stuff, and then start this sucker up */ if (!bprm->sh_bang) { char * passed_p; if (interpreter_type == INTERPRETER_AOUT) { sprintf(passed_fileno, "%d", elf_exec_fileno); passed_p = passed_fileno; if (elf_interpreter) { retval = copy_strings_kernel(1,&passed_p,bprm); if (retval) goto out_free_dentry; bprm->argc++; } } } else { /* Executables without an interpreter also need a personality */ SET_PERSONALITY(elf_ex, ibcs2_interpreter); } /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) goto out_free_dentry; /* Discard our unneeded old files struct */ if (files) { steal_locks(files); put_files_struct(files); files = NULL; } /* OK, This is the point of no return */ current->mm->start_data = 0; current->mm->end_data = 0; current->mm->end_code = 0; current->mm->mmap = NULL; current->flags &= ~PF_FORKNOEXEC; elf_entry = (unsigned long) 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; retval = setup_arg_pages(bprm); if (retval < 0) { send_sig(SIGKILL, current, 0); return retval; } current->mm->start_stack = bprm->p; /* Now we do a little grungy work by mmaping the ELF image into the correct location in memory. At this point, we assume that the image should be loaded at fixed address, not at a variable address. */ for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { int elf_prot = 0, elf_flags; unsigned long vaddr; if (elf_ppnt->p_type != PT_LOAD) continue; if (unlikely (elf_brk > elf_bss)) { unsigned long nbyte; /* There was a PT_LOAD segment with p_memsz > p_filesz before this one. Map anonymous pages, if needed, and clear the area. */ retval = set_brk (elf_bss + load_bias, elf_brk + load_bias); if (retval) { send_sig(SIGKILL, current, 0); goto out_free_dentry; } nbyte = ELF_PAGEOFFSET(elf_bss); if (nbyte) { nbyte = ELF_MIN_ALIGN - nbyte; if (nbyte > elf_brk - elf_bss) nbyte = elf_brk - elf_bss; clear_user((void *) elf_bss + load_bias, nbyte); } } if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE; vaddr = elf_ppnt->p_vaddr; if (elf_ex.e_type == ET_EXEC || load_addr_set) { elf_flags |= MAP_FIXED; } else if (elf_ex.e_type == ET_DYN) { /* Try and get dynamic programs out of the way of the default mmap base, as well as whatever program they might try to exec. This is because the brk will follow the loader, and is not movable. */ load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); } error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); if (BAD_ADDR(error)) { send_sig(SIGKILL, current, 0); goto out_free_dentry; } if (!load_addr_set) { load_addr_set = 1; load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset); if (elf_ex.e_type == ET_DYN) { load_bias += error - ELF_PAGESTART(load_bias + vaddr); load_addr += load_bias; reloc_func_desc = load_addr; } } k = elf_ppnt->p_vaddr; if (k < start_code) start_code = k; if (start_data < k) start_data = k; /* * Check to see if the section's size will overflow the * allowed task size. Note that p_filesz must always be * <= p_memsz so it is only necessary to check p_memsz. */ if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz || elf_ppnt->p_memsz > TASK_SIZE || TASK_SIZE - elf_ppnt->p_memsz < k) { /* set_brk can never work. Avoid overflows. */ send_sig(SIGKILL, current, 0); goto out_free_dentry; } k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; if (k > elf_bss) elf_bss = k; if ((elf_ppnt->p_flags & PF_X) && end_code < k) end_code = k; if (end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; if (k > elf_brk) elf_brk = k; } elf_entry += load_bias; elf_bss += load_bias; elf_brk += load_bias; start_code += load_bias; end_code += load_bias; start_data += load_bias; end_data += load_bias; /* Calling set_brk effectively mmaps the pages that we need * for the bss and break sections. We must do this before * mapping in the interpreter, to make sure it doesn't wind * up getting placed where the bss needs to go. */ retval = set_brk(elf_bss, elf_brk); if (retval) { send_sig(SIGKILL, current, 0); goto out_free_dentry; } padzero(elf_bss); if (elf_interpreter) { if (interpreter_type == INTERPRETER_AOUT) elf_entry = load_aout_interp(&interp_ex, interpreter); else elf_entry = load_elf_interp(&interp_elf_ex, interpreter, &interp_load_addr); if (BAD_ADDR(elf_entry)) { printk(KERN_ERR "Unable to load interpreter %.128s\n", elf_interpreter); force_sig(SIGSEGV, current); retval = -ENOEXEC; /* Nobody gets to see this, but.. */ goto out_free_dentry; } reloc_func_desc = interp_load_addr; allow_write_access(interpreter); fput(interpreter); kfree(elf_interpreter); } kfree(elf_phdata); if (interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno); set_binfmt(&elf_format); compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; bprm->p = (unsigned long) create_elf_tables((char *)bprm->p, bprm->argc, bprm->envc, &elf_ex, load_addr, load_bias, interp_load_addr, (interpreter_type == INTERPRETER_AOUT ? 0 : 1)); /* N.B. passed_fileno might not be initialized? */ if (interpreter_type == INTERPRETER_AOUT) current->mm->arg_start += strlen(passed_fileno) + 1; current->mm->start_brk = current->mm->brk = elf_brk; current->mm->end_code = end_code; current->mm->start_code = start_code; current->mm->start_data = start_data; current->mm->end_data = end_data; current->mm->start_stack = bprm->p; #if 0 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("(start_data) %lx\n" , (long) current->mm->start_data); 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 (current->personality & MMAP_PAGE_ZERO) { /* 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. */ /* N.B. Shouldn't the size here be PAGE_SIZE?? */ down_write(¤t->mm->mmap_sem); error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); up_write(¤t->mm->mmap_sem); } #ifdef ELF_PLAT_INIT /* * The ABI may specify that certain registers be set up in special * ways (on i386 %edx is the address of a DT_FINI function, for * example. In addition, it may also specify (eg, PowerPC64 ELF) * that the e_entry field is the address of the function descriptor * for the startup routine, rather than the address of the startup * routine itself. This macro performs whatever initialization to * the regs structure is required as well as any relocations to the * function descriptor entries when executing dynamically linked apps. */ ELF_PLAT_INIT(regs, reloc_func_desc); #endif start_thread(regs, elf_entry, bprm->p); if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); retval = 0; out: return retval; /* error cleanup */ out_free_dentry: allow_write_access(interpreter); if (interpreter) fput(interpreter); out_free_interp: if (elf_interpreter) kfree(elf_interpreter); out_free_file: sys_close(elf_exec_fileno); out_free_fh: if (files) { put_files_struct(current->files); current->files = files; } out_free_ph: kfree(elf_phdata); goto out; }
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, struct image_info * info) { struct elfhdr elf_ex; struct elfhdr interp_elf_ex; struct exec interp_ex; int interpreter_fd = -1; /* avoid warning */ abi_ulong load_addr, load_bias; int load_addr_set = 0; unsigned int interpreter_type = INTERPRETER_NONE; unsigned char ibcs2_interpreter; int i; abi_ulong mapped_addr; struct elf_phdr * elf_ppnt; struct elf_phdr *elf_phdata; abi_ulong elf_bss, k, elf_brk; int retval; char * elf_interpreter; abi_ulong elf_entry, interp_load_addr = 0; int status; abi_ulong start_code, end_code, start_data, end_data; abi_ulong reloc_func_desc = 0; abi_ulong elf_stack; char passed_fileno[6]; ibcs2_interpreter = 0; status = 0; load_addr = 0; load_bias = 0; elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ #ifdef BSWAP_NEEDED bswap_ehdr(&elf_ex); #endif /* First of all, some simple consistency checks */ if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) || (! elf_check_arch(elf_ex.e_machine))) { return -ENOEXEC; } bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p); bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p); bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p); if (!bprm->p) { retval = -E2BIG; } /* Now read in all of the header information */ elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum); if (elf_phdata == NULL) { return -ENOMEM; } retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET); if(retval > 0) { retval = read(bprm->fd, (char *) elf_phdata, elf_ex.e_phentsize * elf_ex.e_phnum); } if (retval < 0) { perror("load_elf_binary"); exit(-1); free (elf_phdata); return -errno; } #ifdef BSWAP_NEEDED elf_ppnt = elf_phdata; for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) { bswap_phdr(elf_ppnt); } #endif elf_ppnt = elf_phdata; elf_bss = 0; elf_brk = 0; elf_stack = ~((abi_ulong)0UL); elf_interpreter = NULL; start_code = ~((abi_ulong)0UL); end_code = 0; start_data = 0; end_data = 0; interp_ex.a_info = 0; for(i=0;i < elf_ex.e_phnum; i++) { if (elf_ppnt->p_type == PT_INTERP) { if ( elf_interpreter != NULL ) { free (elf_phdata); free(elf_interpreter); close(bprm->fd); return -EINVAL; } /* This is the program interpreter used for * shared libraries - for now assume that this * is an a.out format binary */ elf_interpreter = (char *)malloc(elf_ppnt->p_filesz); if (elf_interpreter == NULL) { free (elf_phdata); close(bprm->fd); return -ENOMEM; } retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); if(retval >= 0) { retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz); } if(retval < 0) { perror("load_elf_binary2"); exit(-1); } /* If the program interpreter is one of these two, then assume an iBCS2 image. Otherwise assume a native linux image. */ /* JRP - Need to add X86 lib dir stuff here... */ if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) { ibcs2_interpreter = 1; } #if 0 printf("Using ELF interpreter %s\n", elf_interpreter); #endif if (retval >= 0) { retval = open(path(elf_interpreter), O_RDONLY); if(retval >= 0) { interpreter_fd = retval; } else { perror(elf_interpreter); exit(-1); /* retval = -errno; */ } } if (retval >= 0) { retval = lseek(interpreter_fd, 0, SEEK_SET); if(retval >= 0) { retval = read(interpreter_fd,bprm->buf,128); } } if (retval >= 0) { interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */ interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */ } if (retval < 0) { perror("load_elf_binary3"); exit(-1); free (elf_phdata); free(elf_interpreter); close(bprm->fd); return retval; } } elf_ppnt++; } /* Some simple consistency checks for the interpreter */ if (elf_interpreter){ interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; /* Now figure out which format our binary is */ if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && (N_MAGIC(interp_ex) != QMAGIC)) { interpreter_type = INTERPRETER_ELF; } if (interp_elf_ex.e_ident[0] != 0x7f || strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) { interpreter_type &= ~INTERPRETER_ELF; } if (!interpreter_type) { free(elf_interpreter); free(elf_phdata); close(bprm->fd); return -ELIBBAD; } } /* OK, we are done with that, now set up the arg stuff, and then start this sucker up */ { char * passed_p; if (interpreter_type == INTERPRETER_AOUT) { snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd); passed_p = passed_fileno; if (elf_interpreter) { bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p); bprm->argc++; } } if (!bprm->p) { if (elf_interpreter) { free(elf_interpreter); } free (elf_phdata); close(bprm->fd); return -E2BIG; } } /* OK, This is the point of no return */ info->end_data = 0; info->end_code = 0; info->start_mmap = (abi_ulong)ELF_START_MMAP; info->mmap = 0; info->elf_flags = elf_ex.e_flags; elf_entry = (abi_ulong) elf_ex.e_entry; /* Do this so that we can load the interpreter, if need be. We will change some of these later */ info->rss = 0; bprm->p = setup_arg_pages(bprm->p, bprm, info); info->start_stack = bprm->p; /* Now we do a little grungy work by mmaping the ELF image into * the correct location in memory. At this point, we assume that * the image should be loaded at fixed address, not at a variable * address. */ for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { int elf_prot = 0; int elf_flags = 0; abi_ulong error; if (elf_ppnt->p_type != PT_LOAD) continue; if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; elf_flags = MAP_PRIVATE | MAP_DENYWRITE; if (elf_ex.e_type == ET_EXEC || load_addr_set) { elf_flags |= MAP_FIXED; } else if (elf_ex.e_type == ET_DYN) { /* Try and get dynamic programs out of the way of the default mmap base, as well as whatever program they might try to exec. This is because the brk will follow the loader, and is not movable. */ /* NOTE: for qemu, we do a big mmap to get enough space without hardcoding any address */ error = target_mmap(0, ET_DYN_MAP_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); if (error == -1) { perror("mmap"); exit(-1); } load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr); } error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr), (elf_ppnt->p_filesz + TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), elf_prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), bprm->fd, (elf_ppnt->p_offset - TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); if (error == -1) { perror("mmap"); exit(-1); } #ifdef LOW_ELF_STACK if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr); #endif if (!load_addr_set) { load_addr_set = 1; load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; if (elf_ex.e_type == ET_DYN) { load_bias += error - TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr); load_addr += load_bias; reloc_func_desc = load_bias; } } k = elf_ppnt->p_vaddr; if (k < start_code) start_code = k; if (start_data < k) start_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; if (k > elf_bss) elf_bss = k; if ((elf_ppnt->p_flags & PF_X) && end_code < k) end_code = k; if (end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; if (k > elf_brk) elf_brk = k; } elf_entry += load_bias; elf_bss += load_bias; elf_brk += load_bias; start_code += load_bias; end_code += load_bias; start_data += load_bias; end_data += load_bias; if (elf_interpreter) { if (interpreter_type & 1) { elf_entry = load_aout_interp(&interp_ex, interpreter_fd); } else if (interpreter_type & 2) { elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd, &interp_load_addr); } reloc_func_desc = interp_load_addr; close(interpreter_fd); free(elf_interpreter); if (elf_entry == ~((abi_ulong)0UL)) { printf("Unable to load interpreter\n"); free(elf_phdata); exit(-1); return 0; } } free(elf_phdata); if (loglevel) load_symbols(&elf_ex, bprm->fd); if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); #ifdef LOW_ELF_STACK info->start_stack = bprm->p = elf_stack - 4; #endif bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex, load_addr, load_bias, interp_load_addr, (interpreter_type == INTERPRETER_AOUT ? 0 : 1), info); info->load_addr = reloc_func_desc; info->start_brk = info->brk = elf_brk; info->end_code = end_code; info->start_code = start_code; info->start_data = start_data; info->end_data = end_data; info->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); padzero(elf_bss, elf_brk); #if 0 printf("(start_brk) %x\n" , info->start_brk); printf("(end_code) %x\n" , info->end_code); printf("(start_code) %x\n" , info->start_code); printf("(end_data) %x\n" , info->end_data); printf("(start_stack) %x\n" , info->start_stack); printf("(brk) %x\n" , info->brk); #endif if ( info->personality == PER_SVR4 ) { /* 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. */ mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, -1, 0); } info->entry = elf_entry; return 0; }
static int CVE_2010_0307_linux2_6_27_31_load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) { struct file *interpreter = NULL; /* to shut gcc up */ unsigned long load_addr = 0, load_bias = 0; int load_addr_set = 0; char * elf_interpreter = NULL; unsigned long error; struct elf_phdr *elf_ppnt, *elf_phdata; unsigned long elf_bss, elf_brk; int elf_exec_fileno; int retval, i; unsigned int size; unsigned long elf_entry; unsigned long interp_load_addr = 0; unsigned long start_code, end_code, start_data, end_data; unsigned long reloc_func_desc = 0; int executable_stack = EXSTACK_DEFAULT; unsigned long def_flags = 0; struct { struct elfhdr elf_ex; struct elfhdr interp_elf_ex; } *loc; loc = kmalloc(sizeof(*loc), GFP_KERNEL); if (!loc) { retval = -ENOMEM; goto out_ret; } /* Get the exec-header */ loc->elf_ex = *((struct elfhdr *)bprm->buf); retval = -ENOEXEC; /* First of all, some simple consistency checks */ if (memcmp(loc->elf_ex.e_ident, ELFMAG, SELFMAG) != 0) goto out; if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN) goto out; if (!elf_check_arch(&loc->elf_ex)) goto out; if (!bprm->file->f_op||!bprm->file->f_op->mmap) goto out; /* Now read in all of the header information */ if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr)) goto out; if (loc->elf_ex.e_phnum < 1 || loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr)) goto out; size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr); retval = -ENOMEM; elf_phdata = kmalloc(size, GFP_KERNEL); if (!elf_phdata) goto out; retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *)elf_phdata, size); if (retval != size) { if (retval >= 0) retval = -EIO; goto out_free_ph; } retval = get_unused_fd(); if (retval < 0) goto out_free_ph; get_file(bprm->file); fd_install(elf_exec_fileno = retval, bprm->file); elf_ppnt = elf_phdata; elf_bss = 0; elf_brk = 0; start_code = ~0UL; end_code = 0; start_data = 0; end_data = 0; for (i = 0; i < loc->elf_ex.e_phnum; i++) { if (elf_ppnt->p_type == PT_INTERP) { /* This is the program interpreter used for * shared libraries - for now assume that this * is an a.out format binary */ retval = -ENOEXEC; if (elf_ppnt->p_filesz > PATH_MAX || elf_ppnt->p_filesz < 2) goto out_free_file; retval = -ENOMEM; elf_interpreter = kmalloc(elf_ppnt->p_filesz, GFP_KERNEL); if (!elf_interpreter) goto out_free_file; retval = kernel_read(bprm->file, elf_ppnt->p_offset, elf_interpreter, elf_ppnt->p_filesz); if (retval != elf_ppnt->p_filesz) { if (retval >= 0) retval = -EIO; goto out_free_interp; } /* make sure path is NULL terminated */ retval = -ENOEXEC; if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0') goto out_free_interp; /* * The early SET_PERSONALITY here is so that the lookup * for the interpreter happens in the namespace of the * to-be-execed image. SET_PERSONALITY can select an * alternate root. * * However, SET_PERSONALITY is NOT allowed to switch * this task into the new images's memory mapping * policy - that is, TASK_SIZE must still evaluate to * that which is appropriate to the execing application. * This is because exit_mmap() needs to have TASK_SIZE * evaluate to the size of the old image. * * So if (say) a 64-bit application is execing a 32-bit * application it is the architecture's responsibility * to defer changing the value of TASK_SIZE until the * switch really is going to happen - do this in * flush_thread(). - akpm */ SET_PERSONALITY(loc->elf_ex, 0); interpreter = open_exec(elf_interpreter); retval = PTR_ERR(interpreter); if (IS_ERR(interpreter)) goto out_free_interp; /* * If the binary is not readable then enforce * mm->dumpable = 0 regardless of the interpreter's * permissions. */ if (file_permission(interpreter, MAY_READ) < 0) bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE); if (retval != BINPRM_BUF_SIZE) { if (retval >= 0) retval = -EIO; goto out_free_dentry; } /* Get the exec headers */ loc->interp_elf_ex = *((struct elfhdr *)bprm->buf); break; } elf_ppnt++; } elf_ppnt = elf_phdata; for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) if (elf_ppnt->p_type == PT_GNU_STACK) { if (elf_ppnt->p_flags & PF_X) executable_stack = EXSTACK_ENABLE_X; else executable_stack = EXSTACK_DISABLE_X; break; } /* Some simple consistency checks for the interpreter */ if (elf_interpreter) { retval = -ELIBBAD; /* Not an ELF interpreter */ if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) goto out_free_dentry; /* Verify the interpreter has a valid arch */ if (!elf_check_arch(&loc->interp_elf_ex)) goto out_free_dentry; } else { /* Executables without an interpreter also need a personality */ SET_PERSONALITY(loc->elf_ex, 0); } /* 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->flags &= ~PF_FORKNOEXEC; current->mm->def_flags = def_flags; /* Do this immediately, since STACK_TOP as used in setup_arg_pages may depend on the personality. */ SET_PERSONALITY(loc->elf_ex, 0); if (elf_read_implies_exec(loc->elf_ex, executable_stack)) current->personality |= READ_IMPLIES_EXEC; if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) current->flags |= PF_RANDOMIZE; arch_pick_mmap_layout(current->mm); /* Do this so that we can load the interpreter, if need be. We will change some of these later */ current->mm->free_area_cache = current->mm->mmap_base; current->mm->cached_hole_size = 0; retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), executable_stack); if (retval < 0) { send_sig(SIGKILL, current, 0); goto out_free_dentry; } current->mm->start_stack = bprm->p; /* Now we do a little grungy work by mmaping the ELF image into the correct location in memory. */ for(i = 0, elf_ppnt = elf_phdata; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { int elf_prot = 0, elf_flags; unsigned long k, vaddr; if (elf_ppnt->p_type != PT_LOAD) continue; if (unlikely (elf_brk > elf_bss)) { unsigned long nbyte; /* There was a PT_LOAD segment with p_memsz > p_filesz before this one. Map anonymous pages, if needed, and clear the area. */ retval = set_brk (elf_bss + load_bias, elf_brk + load_bias); if (retval) { send_sig(SIGKILL, current, 0); goto out_free_dentry; } nbyte = ELF_PAGEOFFSET(elf_bss); if (nbyte) { nbyte = ELF_MIN_ALIGN - nbyte; if (nbyte > elf_brk - elf_bss) nbyte = elf_brk - elf_bss; if (clear_user((void __user *)elf_bss + load_bias, nbyte)) { /* * This bss-zeroing can fail if the ELF * file specifies odd protections. So * we don't check the return value */ } } } if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE; vaddr = elf_ppnt->p_vaddr; if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { elf_flags |= MAP_FIXED; } else if (loc->elf_ex.e_type == ET_DYN) { /* Try and get dynamic programs out of the way of the * default mmap base, as well as whatever program they * might try to exec. This is because the brk will * follow the loader, and is not movable. */ #ifdef CONFIG_X86 load_bias = 0; #else load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); #endif } error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags, 0); if (BAD_ADDR(error)) { send_sig(SIGKILL, current, 0); retval = IS_ERR((void *)error) ? PTR_ERR((void*)error) : -EINVAL; goto out_free_dentry; } if (!load_addr_set) { load_addr_set = 1; load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset); if (loc->elf_ex.e_type == ET_DYN) { load_bias += error - ELF_PAGESTART(load_bias + vaddr); load_addr += load_bias; reloc_func_desc = load_bias; } } k = elf_ppnt->p_vaddr; if (k < start_code) start_code = k; if (start_data < k) start_data = k; /* * Check to see if the section's size will overflow the * allowed task size. Note that p_filesz must always be * <= p_memsz so it is only necessary to check p_memsz. */ if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz || elf_ppnt->p_memsz > TASK_SIZE || TASK_SIZE - elf_ppnt->p_memsz < k) { /* set_brk can never work. Avoid overflows. */ send_sig(SIGKILL, current, 0); retval = -EINVAL; goto out_free_dentry; } k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; if (k > elf_bss) elf_bss = k; if ((elf_ppnt->p_flags & PF_X) && end_code < k) end_code = k; if (end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; if (k > elf_brk) elf_brk = k; } loc->elf_ex.e_entry += load_bias; elf_bss += load_bias; elf_brk += load_bias; start_code += load_bias; end_code += load_bias; start_data += load_bias; end_data += load_bias; /* Calling set_brk effectively mmaps the pages that we need * for the bss and break sections. We must do this before * mapping in the interpreter, to make sure it doesn't wind * up getting placed where the bss needs to go. */ retval = set_brk(elf_bss, elf_brk); if (retval) { send_sig(SIGKILL, current, 0); goto out_free_dentry; } if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) { send_sig(SIGSEGV, current, 0); retval = -EFAULT; /* Nobody gets to see this, but.. */ goto out_free_dentry; } if (elf_interpreter) { unsigned long uninitialized_var(interp_map_addr); elf_entry = load_elf_interp(&loc->interp_elf_ex, interpreter, &interp_map_addr, load_bias); if (!IS_ERR((void *)elf_entry)) { /* * load_elf_interp() returns relocation * adjustment */ interp_load_addr = elf_entry; elf_entry += loc->interp_elf_ex.e_entry; } if (BAD_ADDR(elf_entry)) { force_sig(SIGSEGV, current); retval = IS_ERR((void *)elf_entry) ? (int)elf_entry : -EINVAL; goto out_free_dentry; } reloc_func_desc = interp_load_addr; allow_write_access(interpreter); fput(interpreter); kfree(elf_interpreter); } else { elf_entry = loc->elf_ex.e_entry; if (BAD_ADDR(elf_entry)) { force_sig(SIGSEGV, current); retval = -EINVAL; goto out_free_dentry; } } kfree(elf_phdata); sys_close(elf_exec_fileno); set_binfmt(&elf_format); #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES retval = arch_setup_additional_pages(bprm, executable_stack); if (retval < 0) { send_sig(SIGKILL, current, 0); goto out; } #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; retval = create_elf_tables(bprm, &loc->elf_ex, load_addr, interp_load_addr); if (retval < 0) { send_sig(SIGKILL, current, 0); goto out; } /* N.B. passed_fileno might not be initialized? */ current->mm->end_code = end_code; current->mm->start_code = start_code; current->mm->start_data = start_data; current->mm->end_data = end_data; current->mm->start_stack = bprm->p; #ifdef arch_randomize_brk if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) current->mm->brk = current->mm->start_brk = arch_randomize_brk(current->mm); #endif if (current->personality & MMAP_PAGE_ZERO) { /* 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); error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); up_write(¤t->mm->mmap_sem); } #ifdef ELF_PLAT_INIT /* * The ABI may specify that certain registers be set up in special * ways (on i386 %edx is the address of a DT_FINI function, for * example. In addition, it may also specify (eg, PowerPC64 ELF) * that the e_entry field is the address of the function descriptor * for the startup routine, rather than the address of the startup * routine itself. This macro performs whatever initialization to * the regs structure is required as well as any relocations to the * function descriptor entries when executing dynamically links apps. */ ELF_PLAT_INIT(regs, reloc_func_desc); #endif start_thread(regs, elf_entry, bprm->p); retval = 0; out: kfree(loc); out_ret: return retval; /* error cleanup */ out_free_dentry: allow_write_access(interpreter); if (interpreter) fput(interpreter); out_free_interp: kfree(elf_interpreter); out_free_file: sys_close(elf_exec_fileno); out_free_ph: kfree(elf_phdata); goto out; }
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct elfhdr elf_ex; struct elfhdr interp_elf_ex; struct file * file; struct exec interp_ex; struct inode *interpreter_inode; unsigned int load_addr; unsigned int interpreter_type = INTERPRETER_NONE; int i; int old_fs; int error; struct elf_phdr * elf_ppnt, *elf_phdata; int elf_exec_fileno; unsigned int elf_bss, k, elf_brk; int retval; char * elf_interpreter; unsigned int elf_entry; int status; unsigned int start_code, end_code, end_data; unsigned int elf_stack; char passed_fileno[6]; status = 0; load_addr = 0; elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ if (elf_ex.e_ident[0] != 0x7f || strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) return -ENOEXEC; /* First of all, some simple consistency checks */ if(elf_ex.e_type != ET_EXEC || (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) || (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops || !bprm->inode->i_op->default_file_ops->mmap)){ return -ENOEXEC; }; /* Now read in all of the header information */ elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * elf_ex.e_phnum, GFP_KERNEL); old_fs = get_fs(); set_fs(get_ds()); retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata, elf_ex.e_phentsize * elf_ex.e_phnum); set_fs(old_fs); if (retval < 0) { kfree (elf_phdata); return retval; } elf_ppnt = elf_phdata; elf_bss = 0; elf_brk = 0; elf_exec_fileno = open_inode(bprm->inode, O_RDONLY); if (elf_exec_fileno < 0) { kfree (elf_phdata); return elf_exec_fileno; } file = current->files->fd[elf_exec_fileno]; elf_stack = 0xffffffff; elf_interpreter = NULL; start_code = 0; end_code = 0; end_data = 0; old_fs = get_fs(); set_fs(get_ds()); for(i=0;i < elf_ex.e_phnum; i++){ if(elf_ppnt->p_type == PT_INTERP) { /* This is the program interpreter used for shared libraries - for now assume that this is an a.out format binary */ elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, GFP_KERNEL); retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter, elf_ppnt->p_filesz); #if 0 printk("Using ELF interpreter %s\n", elf_interpreter); #endif if(retval >= 0) retval = namei(elf_interpreter, &interpreter_inode); if(retval >= 0) retval = read_exec(interpreter_inode,0,bprm->buf,128); if(retval >= 0){ interp_ex = *((struct exec *) bprm->buf); /* exec-header */ interp_elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ }; if(retval < 0) { kfree (elf_phdata); kfree(elf_interpreter); return retval; }; }; elf_ppnt++; }; set_fs(old_fs); /* Some simple consistency checks for the interpreter */ if(elf_interpreter){ interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; if(retval < 0) { kfree(elf_interpreter); kfree(elf_phdata); return -ELIBACC; }; /* Now figure out which format our binary is */ if((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && (N_MAGIC(interp_ex) != QMAGIC)) interpreter_type = INTERPRETER_ELF; if (interp_elf_ex.e_ident[0] != 0x7f || strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) interpreter_type &= ~INTERPRETER_ELF; if(!interpreter_type) { kfree(elf_interpreter); kfree(elf_phdata); return -ELIBBAD; }; } /* OK, we are done with that, now set up the arg stuff, and then start this sucker up */ if (!bprm->sh_bang) { char * passed_p; if(interpreter_type == INTERPRETER_AOUT) { sprintf(passed_fileno, "%d", elf_exec_fileno); passed_p = passed_fileno; if(elf_interpreter) { bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2); bprm->argc++; }; }; if (!bprm->p) { if(elf_interpreter) { kfree(elf_interpreter); } kfree (elf_phdata); return -E2BIG; } } /* OK, This is the point of no return */ flush_old_exec(bprm); current->mm->end_data = 0; current->mm->end_code = 0; current->mm->start_mmap = ELF_START_MMAP; current->mm->mmap = NULL; 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; bprm->p += change_ldt(0, bprm->page); current->mm->start_stack = bprm->p; /* Now we do a little grungy work by mmaping the ELF image into the correct location in memory. 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()); elf_ppnt = elf_phdata; for(i=0;i < elf_ex.e_phnum; i++){ if(elf_ppnt->p_type == PT_INTERP) { /* Set these up so that we are able to load the interpreter */ /* Now load the interpreter into user address space */ set_fs(old_fs); if(interpreter_type & 1) elf_entry = load_aout_interp(&interp_ex, interpreter_inode); if(interpreter_type & 2) elf_entry = load_elf_interp(&interp_elf_ex, interpreter_inode); old_fs = get_fs(); set_fs(get_ds()); iput(interpreter_inode); kfree(elf_interpreter); if(elf_entry == 0xffffffff) { printk("Unable to load interpreter\n"); kfree(elf_phdata); send_sig(SIGSEGV, current, 0); return 0; }; }; if(elf_ppnt->p_type == PT_LOAD) { error = do_mmap(file, elf_ppnt->p_vaddr & 0xfffff000, elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, elf_ppnt->p_offset & 0xfffff000); #ifdef LOW_ELF_STACK if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) elf_stack = elf_ppnt->p_vaddr & 0xfffff000; #endif if(!load_addr) load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; k = elf_ppnt->p_vaddr; if(k > start_code) start_code = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; if(k > elf_bss) elf_bss = k; if((elf_ppnt->p_flags | PROT_WRITE) && end_code < k) end_code = k; if(end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; if(k > elf_brk) elf_brk = k; }; elf_ppnt++; }; set_fs(old_fs); kfree(elf_phdata); if(interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno); /* The following 3 lines need a little bit of work if we are loading an iBCS2 binary. We should initially load it this way, and if we get a lcall7, then we should look to see if the iBCS2 execution profile is present. If it is, then switch to that, otherwise bomb. */ current->personality = PER_LINUX; current->lcall7 = no_lcall7; current->signal_map = current->signal_invmap = ident_map; current->executable = bprm->inode; bprm->inode->i_count++; #ifdef LOW_ELF_STACK current->start_stack = p = elf_stack - 4; #endif bprm->p -= MAX_ARG_PAGES*PAGE_SIZE; bprm->p = (unsigned long) create_elf_tables((char *)bprm->p, bprm->argc, bprm->envc, (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL), load_addr, (interpreter_type == INTERPRETER_AOUT ? 0 : 1)); if(interpreter_type == INTERPRETER_AOUT) current->mm->arg_start += strlen(passed_fileno) + 1; 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; current->suid = current->euid = bprm->e_uid; current->sgid = current->egid = bprm->e_gid; /* Calling sys_brk effectively mmaps the pages that we need for the bss and break sections */ current->mm->brk = (elf_bss + 0xfff) & 0xfffff000; sys_brk((elf_brk + 0xfff) & 0xfffff000); padzero(elf_bss); /* 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. */ error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); regs->eip = elf_entry; /* eip, magic happens :-) */ regs->esp = bprm->p; /* stack pointer */ if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); return 0; }
static int load_elf_binary(struct linux_binprm *bprm) { struct pt_regs regs; int interpreter_fd = -1; unsigned long load_addr = 0, load_bias; int load_addr_set = 0; char * elf_interpreter = NULL; unsigned int interpreter_type = INTERPRETER_NONE; unsigned long error; struct elf_phdr * elf_ppnt, *elf_phdata; unsigned long elf_bss, k, elf_brk; int elf_exec_fileno; int retval, size, i; unsigned long elf_entry, interp_load_addr = 0; unsigned long start_code, end_code, end_data; struct elfhdr elf_ex; struct elfhdr interp_elf_ex; struct exec interp_ex; char passed_fileno[6]; /* Get the exec-header */ elf_ex = *((struct elfhdr *) bprm->buf); my_print("[debug]here to run elf\n"); retval = -ENOEXEC; /* First of all, some simple consistency checks */ if (elf_ex.e_ident[0] != 0x7f || strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0) goto out; //my_print("[ender]1\n"); if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) goto out; if (!elf_check_arch(elf_ex.e_machine)) goto out; //my_print("[ender]2\n"); /* Now read in all of the header information */ if (elf_ex.e_phentsize != sizeof(struct elf_phdr) || elf_ex.e_phnum < 1 || elf_ex.e_phnum > 65536 / sizeof(struct elf_phdr)) goto out; // my_print("[ender]3\n"); retval = -ENOMEM; size = elf_ex.e_phentsize * elf_ex.e_phnum; elf_phdata = (struct elf_phdr *) malloc(size); if (!elf_phdata) goto out; retval = read_exec(bprm->fd, elf_ex.e_phoff, (char *) elf_phdata, size, 1); if (retval < 0) goto out_free_ph; //my_print("[ender]4\n"); elf_exec_fileno = dup(bprm->fd); lseek(elf_exec_fileno, 0, SEEK_SET); elf_ppnt = elf_phdata; elf_bss = 0; elf_brk = 0; start_code = ~0UL; end_code = 0; end_data = 0; /* look for interpreter */ for (i = 0; i < elf_ex.e_phnum; i++) { if (elf_ppnt->p_type == PT_INTERP) { retval = -ENOEXEC; if (elf_interpreter || elf_ppnt->p_filesz < 2 || elf_ppnt->p_filesz > PAGE_SIZE) goto out_free_dentry; /* This is the program interpreter used for * shared libraries - for now assume that this * is an a.out format binary */ retval = -ENOMEM; elf_interpreter = (char *)malloc(elf_ppnt->p_filesz); if (!elf_interpreter) goto out_free_file; retval = read_exec(bprm->fd, elf_ppnt->p_offset, elf_interpreter, elf_ppnt->p_filesz, 1); if (retval < 0) goto out_free_interp; elf_interpreter[elf_ppnt->p_filesz - 1] = 0; #if 0 /* If the program interpreter is one of these two, * then assume an iBCS2 image. Otherwise assume * a native linux image. */ if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) ibcs2_interpreter = 1; #endif log_debug(LOG_LINEXEC_EXEC, "Using ELF interpreter: %s", elf_interpreter); if( elf_interpreter[0] == '/'){ char tmp [MAX_PATH]; change_path_to_relative(tmp, elf_interpreter); free(elf_interpreter); //elf_interpreter = (char *)malloc(elf_ppnt->p_filesz); elf_interpreter = (char *)malloc(strlen(tmp)+1); if (!elf_interpreter) goto out_free_file; strcpy(elf_interpreter, tmp); } interpreter_fd = open(elf_interpreter, O_RDONLY); my_print("[debug]open elf_interpreter %s\n", elf_interpreter); if (interpreter_fd < 0) { retval = -errno; goto out_free_interp; } #if 0 retval = permission(interpreter_dentry->d_inode, MAY_EXEC); if (retval < 0) goto out_free_dentry; #endif retval = read_exec(interpreter_fd, 0, bprm->buf, 128, 1); if (retval < 0) goto out_free_dentry; /* Get the exec headers */ interp_ex = *((struct exec *) bprm->buf); interp_elf_ex = *((struct elfhdr *) bprm->buf); } elf_ppnt++; //my_print("[ender]6\n"); } /* Some simple consistency checks for the interpreter */ if (elf_interpreter) { interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; /* Now figure out which format our binary is */ if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && (N_MAGIC(interp_ex) != QMAGIC)) interpreter_type = INTERPRETER_ELF; if (interp_elf_ex.e_ident[0] != 0x7f || strncmp(&interp_elf_ex.e_ident[1], "ELF", 3) != 0) interpreter_type &= ~INTERPRETER_ELF; retval = -ELIBBAD; if (!interpreter_type) goto out_free_dentry; /* Make sure only one type was selected */ if ((interpreter_type & INTERPRETER_ELF) && interpreter_type != INTERPRETER_ELF) { printf("ELF: Ambiguous type, using ELF\n"); interpreter_type = INTERPRETER_ELF; } } //my_print("[ender]7\n"); /* OK, we are done with that, now set up the arg stuff, and then start this sucker up */ if (!bprm->sh_bang) { char * passed_p; if (interpreter_type == INTERPRETER_AOUT) { sprintf(passed_fileno, "%d", elf_exec_fileno); passed_p = passed_fileno; if (elf_interpreter) { bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p); bprm->argc++; } } retval = -E2BIG; if (!bprm->p) goto out_free_dentry; } #if 0 /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) goto out_free_dentry; #endif /* OK, This is the point of no return */ current->end_data = 0; current->end_code = 0; #if 0 current->mm->mmap = NULL; current->flags &= ~PF_FORKNOEXEC; #endif elf_entry = (unsigned long) elf_ex.e_entry; //printf("[ender]8\n"); #if 0 /* Do this immediately, since STACK_TOP as used in setup_arg_pages may depend on the personality. */ SET_PERSONALITY(elf_ex, ibcs2_interpreter); #endif /* Do this so that we can load the interpreter, if need be. We will change some of these later */ // current->mm->rss = 0; bprm->p = setup_arg_pages(bprm->p, bprm); current->start_stack = bprm->p; /* Try and get dynamic programs out of the way of the default mmap base, as well as whatever program they might try to exec. This is because the brk will follow the loader, and is not movable. */ load_bias = ELF_PAGESTART(elf_ex.e_type==ET_DYN ? ELF_ET_DYN_BASE : 0); #ifdef __VERBOSE__ printf("load_bias: %08lX\n", load_bias); #endif /* Now we do a little grungy work by mmaping the ELF image into the correct location in memory. At this point, we assume that the image should be loaded at fixed address, not at a variable address. */ for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { int elf_prot = 0, elf_flags; unsigned long vaddr; if (elf_ppnt->p_type != PT_LOAD) continue; if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; elf_flags = MAP_PRIVATE; // |MAP_DENYWRITE|MAP_EXECUTABLE; vaddr = elf_ppnt->p_vaddr; if (elf_ex.e_type == ET_EXEC || load_addr_set) { elf_flags |= MAP_FIXED; } //my_print("[ender]9\n"); #ifdef __VERBOSE__ printf("mapping: %08lX\n", ELF_PAGESTART(load_bias + vaddr)); #endif error = do_mmap(bprm->fd, ELF_PAGESTART(load_bias + vaddr), (elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), elf_prot, elf_flags, (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); #ifdef __VERBOSE__ printf("error: %08lX\n", error); #endif if (!load_addr_set) { load_addr_set = 1; load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset); #ifdef __VERBOSE__ printf("load_addr: %08lX, vaddr: %08lX\n", load_addr, vaddr); #endif if (elf_ex.e_type == ET_DYN) { load_bias += error - ELF_PAGESTART(load_bias + vaddr); load_addr += error; #ifdef __VERBOSE__ printf("new\nload_bias: %08lX, load_addr: %08lX\n", load_bias, load_addr); #endif } } k = elf_ppnt->p_vaddr; if (k < start_code) start_code = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; if (k > elf_bss) elf_bss = k; if ((elf_ppnt->p_flags & PF_X) && end_code < k) end_code = k; if (end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; if (k > elf_brk) elf_brk = k; } close(bprm->fd); elf_entry += load_bias; elf_bss += load_bias; elf_brk += load_bias; start_code += load_bias; end_code += load_bias; end_data += load_bias; if (elf_interpreter) { if (interpreter_type == INTERPRETER_AOUT) { elf_entry = load_aout_interp(&interp_ex, interpreter_fd); } else { elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd, &interp_load_addr); } close(interpreter_fd); if (elf_entry == ~0UL) { printf("Unable to load interpreter %.128s\n", elf_interpreter); free(elf_interpreter); free(elf_phdata); //send_sig(SIGSEGV, current, 0); exit(1); return 0; } free(elf_interpreter); } free(elf_phdata); if (interpreter_type != INTERPRETER_AOUT) close(elf_exec_fileno); #if 0 #ifndef VM_STACK_FLAGS current->executable = dget(bprm->dentry); #endif #endif bprm->p = (unsigned long)create_elf_tables((char *)bprm->p, bprm->argc, bprm->envc, (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL), load_addr, load_bias, interp_load_addr, (interpreter_type == INTERPRETER_AOUT ? 0 : 1)); #if 0 /* N.B. passed_fileno might not be initialized? */ if (interpreter_type == INTERPRETER_AOUT) current->arg_start += strlen(passed_fileno) + 1; #endif current->start_brk = current->brk = elf_brk; current->end_code = end_code; current->start_code = start_code; current->end_data = end_data; current->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); padzero(elf_bss); log_debug(LOG_LINEXEC_EXEC,"start_brk: %lx" , current->start_brk); log_debug(LOG_LINEXEC_EXEC,"end_code: %lx" , current->end_code); log_debug(LOG_LINEXEC_EXEC,"start_code: %lx" , current->start_code); log_debug(LOG_LINEXEC_EXEC,"end_data: %lx" , current->end_data); log_debug(LOG_LINEXEC_EXEC,"start_stack: %lx" , current->start_stack); log_debug(LOG_LINEXEC_EXEC,"brk: %lx" , current->brk); /* * The ABI may specify that certain registers be set up in special * ways (on i386 %edx is the address of a DT_FINI function, for * example. This macro performs whatever initialization to * the regs structure is required. */ ELF_PLAT_INIT((®s)); regs.eip = elf_entry; regs.esp = bprm->p; #if 0 if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); #endif #ifndef __DEBUG__ // dumpMemoryMap(); log_verbose(LOG_LINEXEC_EXEC, "[transfering control to Linux executable]"); //getchar(); //printf("[ender]11\n"); ASM_EXEC_JUMP(regs); printf("You should never see this message!\n"); #else printf("execve() finished, but in debug mode. exiting...\n"); #endif retval = 0; out: return retval; /* error cleanup */ out_free_dentry: close(interpreter_fd); out_free_interp: if (elf_interpreter) { free(elf_interpreter); } out_free_file: close(elf_exec_fileno); out_free_ph: free(elf_phdata); goto out; }
static inline int do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct file * file; struct dentry *interpreter_dentry = NULL; /* to shut gcc up */ unsigned long load_addr = 0, load_bias; int load_addr_set = 0; char * elf_interpreter = NULL; unsigned int interpreter_type = INTERPRETER_NONE; unsigned char ibcs2_interpreter = 0; mm_segment_t old_fs; unsigned long error; struct elf_phdr * elf_ppnt, *elf_phdata; unsigned long elf_bss, k, elf_brk; int elf_exec_fileno; int retval, size, i; unsigned long elf_entry, interp_load_addr = 0; unsigned long start_code, end_code, end_data; struct elfhdr elf_ex; struct elfhdr interp_elf_ex; struct exec interp_ex; char passed_fileno[6]; /* Get the exec-header */ elf_ex = *((struct elfhdr *) bprm->buf); retval = -ENOEXEC; /* First of all, some simple consistency checks */ if (elf_ex.e_ident[0] != 0x7f || strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0) goto out; if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) goto out; if (!elf_check_arch(elf_ex.e_machine)) goto out; #ifdef __mips__ /* allow only mips1 if exec is MIPSEB elf, because IRIX binaries handled elsewhere. */ /* borrowed from binutils/include/elf/common.h*/ #define EI_DATA 5 /* Data encoding */ #define ELFDATA2MSB 2 /* 2's complement, big endian */ if ((elf_ex.e_ident[EI_DATA] == ELFDATA2MSB ) && (elf_ex.e_flags & EF_MIPS_ARCH) ) { retval = -ENOEXEC; goto out; } #endif if (!bprm->dentry->d_inode->i_op || !bprm->dentry->d_inode->i_op->default_file_ops || !bprm->dentry->d_inode->i_op->default_file_ops->mmap) goto out; /* Now read in all of the header information */ retval = -ENOMEM; size = elf_ex.e_phentsize * elf_ex.e_phnum; elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); if (!elf_phdata) goto out; retval = read_exec(bprm->dentry, elf_ex.e_phoff, (char *) elf_phdata, size, 1); if (retval < 0) goto out_free_ph; retval = open_dentry(bprm->dentry, O_RDONLY); if (retval < 0) goto out_free_ph; elf_exec_fileno = retval; file = fget(elf_exec_fileno); elf_ppnt = elf_phdata; elf_bss = 0; elf_brk = 0; start_code = ~0UL; end_code = 0; end_data = 0; for (i = 0; i < elf_ex.e_phnum; i++) { if (elf_ppnt->p_type == PT_INTERP) { retval = -EINVAL; if (elf_interpreter) goto out_free_interp; /* This is the program interpreter used for * shared libraries - for now assume that this * is an a.out format binary */ retval = -ENOMEM; elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, GFP_KERNEL); if (!elf_interpreter) goto out_free_file; retval = read_exec(bprm->dentry, elf_ppnt->p_offset, elf_interpreter, elf_ppnt->p_filesz, 1); if (retval < 0) goto out_free_interp; /* If the program interpreter is one of these two, * then assume an iBCS2 image. Otherwise assume * a native linux image. */ if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) ibcs2_interpreter = 1; #if 0 printk("Using ELF interpreter %s\n", elf_interpreter); #endif old_fs = get_fs(); /* This could probably be optimized */ set_fs(get_ds()); #ifdef __sparc__ if (ibcs2_interpreter) { unsigned long old_pers = current->personality; current->personality = PER_SVR4; interpreter_dentry = open_namei(elf_interpreter, 0, 0); current->personality = old_pers; } else #endif interpreter_dentry = open_namei(elf_interpreter, 0, 0); set_fs(old_fs); retval = PTR_ERR(interpreter_dentry); if (IS_ERR(interpreter_dentry)) goto out_free_interp; retval = permission(interpreter_dentry->d_inode, MAY_EXEC); if (retval < 0) goto out_free_dentry; retval = read_exec(interpreter_dentry, 0, bprm->buf, 128, 1); if (retval < 0) goto out_free_dentry; /* Get the exec headers */ interp_ex = *((struct exec *) bprm->buf); interp_elf_ex = *((struct elfhdr *) bprm->buf); } elf_ppnt++; } /* Some simple consistency checks for the interpreter */ if (elf_interpreter) { interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; /* Now figure out which format our binary is */ if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && (N_MAGIC(interp_ex) != QMAGIC)) interpreter_type = INTERPRETER_ELF; if (interp_elf_ex.e_ident[0] != 0x7f || strncmp(&interp_elf_ex.e_ident[1], "ELF", 3) != 0) interpreter_type &= ~INTERPRETER_ELF; retval = -ELIBBAD; if (!interpreter_type) goto out_free_dentry; /* Make sure only one type was selected */ if ((interpreter_type & INTERPRETER_ELF) && interpreter_type != INTERPRETER_ELF) { printk(KERN_WARNING "ELF: Ambiguous type, using ELF\n"); interpreter_type = INTERPRETER_ELF; } } /* OK, we are done with that, now set up the arg stuff, and then start this sucker up */ if (!bprm->sh_bang) { char * passed_p; if (interpreter_type == INTERPRETER_AOUT) { sprintf(passed_fileno, "%d", elf_exec_fileno); passed_p = passed_fileno; if (elf_interpreter) { bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2); bprm->argc++; } } retval = -E2BIG; if (!bprm->p) goto out_free_dentry; } /* 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 long) elf_ex.e_entry; /* Do this immediately, since STACK_TOP as used in setup_arg_pages may depend on the personality. */ SET_PERSONALITY(elf_ex, ibcs2_interpreter); /* Do this so that we can load the interpreter, if need be. We will change some of these later */ current->mm->rss = 0; bprm->p = setup_arg_pages(bprm->p, bprm); current->mm->start_stack = bprm->p; /* Try and get dynamic programs out of the way of the default mmap base, as well as whatever program they might try to exec. This is because the brk will follow the loader, and is not movable. */ load_bias = ELF_PAGESTART(elf_ex.e_type==ET_DYN ? ELF_ET_DYN_BASE : 0); /* Now we do a little grungy work by mmaping the ELF image into the correct location in memory. 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()); for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { int elf_prot = 0, elf_flags; unsigned long vaddr; if (elf_ppnt->p_type != PT_LOAD) continue; if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE; vaddr = elf_ppnt->p_vaddr; if (elf_ex.e_type == ET_EXEC || load_addr_set) { elf_flags |= MAP_FIXED; } error = do_mmap(file, ELF_PAGESTART(load_bias + vaddr), (elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), elf_prot, elf_flags, (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); if (!load_addr_set) { load_addr_set = 1; load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset); if (elf_ex.e_type == ET_DYN) { load_bias += error - ELF_PAGESTART(load_bias + vaddr); load_addr += error; } } k = elf_ppnt->p_vaddr; if (k < start_code) start_code = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; if (k > elf_bss) elf_bss = k; if ((elf_ppnt->p_flags & PF_X) && end_code < k) end_code = k; if (end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; if (k > elf_brk) elf_brk = k; } set_fs(old_fs); fput(file); /* all done with the file */ elf_entry += load_bias; elf_bss += load_bias; elf_brk += load_bias; start_code += load_bias; end_code += load_bias; end_data += load_bias; if (elf_interpreter) { if (interpreter_type == INTERPRETER_AOUT) elf_entry = load_aout_interp(&interp_ex, interpreter_dentry); else elf_entry = load_elf_interp(&interp_elf_ex, interpreter_dentry, &interp_load_addr); dput(interpreter_dentry); kfree(elf_interpreter); if (elf_entry == ~0UL) { printk(KERN_ERR "Unable to load interpreter\n"); kfree(elf_phdata); send_sig(SIGSEGV, current, 0); return 0; } } kfree(elf_phdata); if (interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno); if (current->exec_domain && current->exec_domain->module) __MOD_DEC_USE_COUNT(current->exec_domain->module); if (current->binfmt && current->binfmt->module) __MOD_DEC_USE_COUNT(current->binfmt->module); current->exec_domain = lookup_exec_domain(current->personality); current->binfmt = &elf_format; if (current->exec_domain && current->exec_domain->module) __MOD_INC_USE_COUNT(current->exec_domain->module); if (current->binfmt && current->binfmt->module) __MOD_INC_USE_COUNT(current->binfmt->module); #ifndef VM_STACK_FLAGS current->executable = dget(bprm->dentry); #endif compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; bprm->p = (unsigned long) create_elf_tables((char *)bprm->p, bprm->argc, bprm->envc, (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL), load_addr, load_bias, interp_load_addr, (interpreter_type == INTERPRETER_AOUT ? 0 : 1)); /* N.B. passed_fileno might not be initialized? */ if (interpreter_type == INTERPRETER_AOUT) current->mm->arg_start += strlen(passed_fileno) + 1; 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); padzero(elf_bss); #if 0 printk("(start_brk) %x\n" , current->mm->start_brk); printk("(end_code) %x\n" , current->mm->end_code); printk("(start_code) %x\n" , current->mm->start_code); printk("(end_data) %x\n" , current->mm->end_data); printk("(start_stack) %x\n" , current->mm->start_stack); printk("(brk) %x\n" , current->mm->brk); #endif if ( current->personality == PER_SVR4 ) { /* 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. */ /* N.B. Shouldn't the size here be PAGE_SIZE?? */ error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); } #ifdef ELF_PLAT_INIT /* * The ABI may specify that certain registers be set up in special * ways (on i386 %edx is the address of a DT_FINI function, for * example. This macro performs whatever initialization to * the regs structure is required. */ ELF_PLAT_INIT(regs); #endif start_thread(regs, elf_entry, bprm->p); if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); retval = 0; out: return retval; /* error cleanup */ out_free_dentry: dput(interpreter_dentry); out_free_interp: if (elf_interpreter) kfree(elf_interpreter); out_free_file: fput(file); sys_close(elf_exec_fileno); out_free_ph: kfree(elf_phdata); goto out; }