asmlinkage unsigned long sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { struct file * file = NULL; unsigned long error; error = -EINVAL; if (!(flags & MAP_ANONYMOUS)) { error = -EBADF; file = fget(fd); if (!file) goto out; } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); if (file) fput(file); out: return error; }
int blktap_ring_map_request(struct blktap *tap, struct file *filp, struct blktap_request *request) { struct blktap_ring *ring = &tap->ring; unsigned long addr, len, pgoff; int read, write, prot, flags; write = request->operation == BLKTAP_OP_WRITE; read = request->operation == BLKTAP_OP_READ; if (write) blktap_request_bounce(tap, request, write); prot = PROT_READ; prot |= read ? PROT_WRITE : 0; flags = MAP_FIXED|MAP_SHARED; addr = MMAP_VADDR(ring->user_vstart, request->usr_idx, 0); len = request->nr_pages << PAGE_SHIFT; pgoff = 1 + request->usr_idx * BLKTAP_SEGMENT_MAX; addr = do_mmap_pgoff(filp, addr, len, prot, flags, pgoff); return IS_ERR_VALUE(addr) ? addr : 0; }
int ckpt_map_attach(char *node, pid_t gpid, unsigned long area, size_t size, int prot, int flags) { struct file *file; unsigned long ret; unsigned long populate; char path[MAP_PATH_MAX]; ret = ckpt_map_get_path(node, gpid, area, path); if (ret) { log_err("failed to get path"); return ret; } file = filp_open(path, MAP_FLAG, MAP_MODE); if (IS_ERR(file)) { log_err("failed to open, path=%s", path); return PTR_ERR(file); } ret = do_mmap_pgoff(file, area, size, prot, flags, 0, &populate); if (populate) mm_populate(ret, populate); if (ret != area) { log_err("failed to attach, ret=%d", (int)ret); return -EINVAL; } log_map_attach(path); return 0; }
/* common code for old and new mmaps */ inline long do_mmap2( unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { int error = -EINVAL; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (flags & MAP_FIXED && addr < MIN_MAP_ADDR) goto out; error = -EBADF; if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); if (file) fput(file); out: return error; }
/* common code for old and new mmaps */ inline long do_mmap2( unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { int error = -EINVAL; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); /* * If we are doing a fixed mapping, and address < PAGE_SIZE, * then deny it. */ if (flags & MAP_FIXED && addr < PAGE_SIZE && vectors_base() == 0) goto out; error = -EBADF; if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); if (file) fput(file); out: return error; }
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { int error = -EBADF; struct file * file = NULL; /* As with sparc32, make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE we have.... */ /* But unlike sparc32, don't just silently break if we're trying to map something we can't */ if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1)) return -EINVAL; pgoff >>= PAGE_SHIFT - 12; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); if (file) fput(file); out: return error; }
static inline unsigned long do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff) { struct file *file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) return -EBADF; if (!file->f_op || !file->f_op->mmap) { addr = -ENODEV; goto out; } } /* Careful about overflows.. */ len = PAGE_ALIGN(len); if (!len || len > TASK_SIZE) { addr = -EINVAL; goto out; } down_write(¤t->mm->mmap_sem); addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); out: if (file) fput(file); return addr; }
static int tcmi_ckpt_vm_area_read_l(struct tcmi_ckpt *ckpt, struct tcmi_ckpt_vm_area_hdr *hdr) { /* page for the filepathname */ unsigned long page; char *pathname = NULL; struct file *file; /* file object for the vm_file */ unsigned long mmap_flags; unsigned long addr; /* finish the header */ hdr->type = TCMI_CKPT_VM_AREA_LIGHT; /* resolve the path name. */ if (!(page = __get_free_page(GFP_KERNEL))) { mdbg(ERR3, "Can't allocate page for file pathname!"); goto exit0; } pathname = (char*) page; /* read the header and the pathname from the checkpoint */ if (tcmi_ckpt_read(ckpt, pathname, hdr->pathname_size) < 0) { mdbg(ERR3, "Error reading pathname"); goto exit1; } /* convert the VM flags to MMAP flags */ mmap_flags = tcmi_ckpt_vm_area_to_mmap_flags(hdr->vm_flags); file = filp_open(pathname, O_RDONLY, 0); if (IS_ERR(file)) { mdbg(ERR3, "Error opening file '%s'", pathname); goto exit1; } /* prot flags are just the lower bits extracted from vm_flags - see mman.h, mm.h */ addr = do_mmap_pgoff(file, hdr->vm_start, hdr->vm_end - hdr->vm_start, hdr->vm_flags & (PROT_READ | PROT_EXEC| PROT_WRITE), mmap_flags, hdr->vm_pgoff); if (addr != hdr->vm_start) { mdbg(ERR3, "Error mapping file '%s' at: %lx", pathname, addr); goto exit2; } /* or shall we perform filp_close??? */ fput(file); free_page(page); mdbg(INFO4, "Mapped at: 08%lx, VM_flags = %08llx, mmap flags = %08lx", addr, (unsigned long long)hdr->vm_flags, mmap_flags); return 0; /* error handling */ exit2: fput(file); exit1: free_page(page); exit0: return -EINVAL; }
/** * \<\<private\>\> This method is responsible for fixing a the stack * in the area just read from the checkpoint file. The idea is the * split the supplied VM area into two: * * - one containing the top of the stack * - the other will be created by the standard mechanism. * * What needs to be done is to: * * - create an anonymous mapping with the MAP_GROWSDOWN flag, with start * address the same as the VM area in the checkpoint and size of one page. * - read the first page of the stack area from the checkpoint file * and copy it into the newly created mapping. The current top of the * stack is somewhere in this page. * - adjust the VM area header read from the checkpoint file: * increment vm_start address and reset the VM_GROWSDOWN flag. * * Why is it so complex? Stack expansion is possible only for areas * marked by VM_GROWSDOWN flag. However, it is not possible to create * a file memory mapping using MAP_GROWSDOWN. The memory mapping * framework simply denies this as a regular user doesn't need it. To * change the size of a memory mapping, all processes are encouraged * to use mremap(). Further, we would have a problem when the current * stack pointer leaves the memory region by the allowed limit(max * 32bytes). Where would the expansion get the page? It might end up * asking the file to supply the missing page. This is obviously not * possible. * * * @param *ckpt - checkpoint file where the current stack area resides. * @param *hdr - VM area header * @return 0 upon success. */ static int tcmi_ckpt_vm_area_stack_fixup(struct tcmi_ckpt *ckpt, struct tcmi_ckpt_vm_area_hdr *hdr) { /* temporary page allocated for the top of the stack */ unsigned long page; /* address of the target mapping - must match hdr->vm_start */ unsigned long addr; unsigned long mmap_flags; /* convert the VM flags to MMAP flags */ mmap_flags = tcmi_ckpt_vm_area_to_mmap_flags(hdr->vm_flags); /* prot flags are just the lower bits extracted from vm_flags - see mman.h, mm.h */ down_write(¤t->mm->mmap_sem); addr = do_mmap_pgoff(NULL, hdr->vm_start, PAGE_SIZE, hdr->vm_flags & (PROT_READ | PROT_EXEC| PROT_WRITE), mmap_flags, 0); //Replaced function do_mmap to do_mmap_pgoff for kernel 3.7.x by Jiri Rakosnik up_write(¤t->mm->mmap_sem); if (addr != hdr->vm_start) { mdbg(ERR3, "Error creating an anonymous mapping for stack page %d", (int)addr); goto exit0; } if (!(page = __get_free_page(GFP_KERNEL))) { mdbg(ERR3, "Can't allocate page for stack!"); goto exit0; } /* read the first page of the stack */ if (tcmi_ckpt_read(ckpt, (void*)page, PAGE_SIZE) < 0) { mdbg(ERR3, "Error stack page!"); goto exit1; } mdbg(INFO4, "Copying stack page to %08lx from %08lx", addr, page); if (tcmi_ckpt_vm_area_copy_page(addr, page) < 0) { mdbg(ERR3, "Failed to copy stack page!!!"); goto exit1; } /* memcpy((void*)addr, (void*)page, PAGE_SIZE); */ mdbg(INFO4, "Copying done"); /* adjust the attributes */ hdr->vm_start += PAGE_SIZE; hdr->vm_flags &= ~VM_GROWSDOWN; /* FIXME: make this unified for all archs!!!*/ free_page(page); mdbg(INFO4, "Created anonymous mapping for stack at: %08lx", addr); return 0; /* error handling */ exit1: free_page(page); exit0: return -EINVAL; }
static inline unsigned long do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff) { unsigned long roff; struct file *file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) return -EBADF; if (!file->f_op || !file->f_op->mmap) { addr = -ENODEV; goto out; } } /* * A zero mmap always succeeds in Linux, independent of whether or not the * remaining arguments are valid. */ if (len == 0) goto out; /* Careful about overflows.. */ len = PAGE_ALIGN(len); if (!len || len > TASK_SIZE) { addr = -EINVAL; goto out; } /* * Don't permit mappings into unmapped space, the virtual page table of a region, * or across a region boundary. Note: RGN_MAP_LIMIT is equal to 2^n-PAGE_SIZE * (for some integer n <= 61) and len > 0. */ roff = REGION_OFFSET(addr); if ((len > RGN_MAP_LIMIT) || (roff > (RGN_MAP_LIMIT - len))) { addr = -EINVAL; goto out; } down_write(¤t->mm->mmap_sem); addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); out: if (file) fput(file); return addr; }
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { int error = -EBADF; struct file *file = NULL; struct mm_struct *mm = current->mm; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { /*if(live_transaction()){ if(current->transaction->unsupported_operation_action == UNSUPPORTED_ABORT){ printk(KERN_ERR "Aborting on unsupported mmap in tx\n"); abort_self(NULL, 0); } else if(current->transaction->unsupported_operation_action == UNSUPPORTED_ERROR_CODE){ printk(KERN_ERR "Warning: Stopped unsupported mmap in tx\n"); return -ENOTXSUPPORT; } else { #ifdef CONFIG_TX_KSTM_WARNINGS printk(KERN_ERR "Warning: Attempt to do a non-anon mmap in a transaction. addr %lx, len %lu, prot %lx, flags %lx, fd %lu, pgoff %lu\n", addr, len, prot, flags, fd, pgoff); #endif } }*/ file = fget(fd); if (!file) goto out; } down_write(&mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(&mm->mmap_sem); if (file) fput(file); out: return error; }
int __init do_mmap_pgoff_init(void) { /*调用do_mmap_pgoff( )之前,当前用户空间所包含的线性空间数目*/ printk("<0>before do_mmap_pgoff( ),map_count = %d\n", current->mm->map_count); down_write(¤t->mm->mmap_sem); //写者获取当前进程空间的mmap_sem信号量 addr =do_mmap_pgoff( NULL, 100, len , PROT_WRITE | PROT_READ , MAP_ANONYMOUS | MAP_SHARED , 0 ); up_write(¤t->mm->mmap_sem); //释放当前进程空间的mmap_sem信号量 if ( addr > 0xc0000000 ) //分配不成功或是运行结果错误 { printk("<0>do_mmap_pgoff ( ) failed\n"); } else //如果返回的是有效的地址 { /*调用do_mmap_pgoff( )之后,当前用户空间所包含的线性空间数目*/ printk("<0>after do_mmap_pgoff( ),map_count = %d\n", current->mm->map_count); printk("<0>The addr = 0x%lx\n", addr); } return 0; }
SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, pgoff) { struct file * file = NULL; unsigned long retval = -EBADF; if (!(flags & MAP_ANONYMOUS)) { if (unlikely(flags & MAP_HUGETLB)) return -EINVAL; audit_mmap_fd(fd, flags); file = fget(fd); if (!file) goto out; } else if (flags & MAP_HUGETLB) { struct user_struct *user = NULL; /* * VM_NORESERVE is used because the reservations will be * taken when vm_ops->mmap() is called * A dummy user value is used because we are not locking * memory so no accounting is necessary */ len = ALIGN(len, huge_page_size(&default_hstate)); file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, &user, HUGETLB_ANONHUGE_INODE); if (IS_ERR(file)) return PTR_ERR(file); } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(¤t->mm->mmap_sem); retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); if (file) fput(file); out: return retval; }
/* * Like cr_sendfile_buffered(), but for HUGETLBFS destination file. * Uses temporary mmap()s of a chunk of len HPAGE_SIZE at a time. * * Note: Caller is responsible for checking count==0 or {dst,src}_ppos==NULL. */ static loff_t cr_sendfile_hugedst(cr_errbuf_t *eb, struct file *dst_filp, struct file *src_filp, loff_t *src_ppos, loff_t count) { loff_t bytes_left = count; loff_t retval; struct mm_struct *mm = current->mm; unsigned long map_addr = 0; unsigned long map_pgoff = 0; unsigned long map_flags = MAP_SHARED; CRI_ASSERT((count & (HPAGE_SIZE-1)) == 0); CRI_ASSERT(dst_filp->f_pos == 0); CRI_ASSERT(src_ppos = &src_filp->f_pos); for (bytes_left = count; bytes_left; bytes_left -= HPAGE_SIZE) { unsigned long tmp; down_write(&mm->mmap_sem); tmp = do_mmap_pgoff(dst_filp, map_addr, HPAGE_SIZE, PROT_READ|PROT_WRITE, map_flags, map_pgoff); up_write(&mm->mmap_sem); if (IS_ERR((void*)tmp)) { CR_ERR_EB(eb, "do_mmap(HUGE dst file) returned %ld", (long)tmp); retval = tmp; goto out_err; } map_addr = tmp; map_pgoff += (HPAGE_SIZE >> PAGE_SHIFT); map_flags |= MAP_FIXED; retval = cr_uread(eb, src_filp, (void *)map_addr, HPAGE_SIZE); if (retval < 0) goto out_unmap; } retval = count; dst_filp->f_pos = count; out_unmap: if (map_addr) { (void)sys_munmap(map_addr, HPAGE_SIZE); // XXX: check for error (unless on error path already)? } out_err: return retval; }
static inline unsigned long do_mmap2(unsigned long addr, size_t len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { struct file * file = NULL; int ret = -EBADF; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { if (!(file = fget(fd))) goto out; } down_write(¤t->mm->mmap_sem); ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); if (file) fput(file); out: return ret; }
/* common code for old and new mmaps */ long do_mmap2(struct mm_struct *mm, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { int error = -EBADF; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } down_write(&mm->mmap_sem); error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff); up_write(&mm->mmap_sem); if (file) fput(file); out: return error; }
/* Linux version of mmap */ static unsigned long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { struct file * file = NULL; unsigned long retval = -EBADF; if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } retval = -EINVAL; len = PAGE_ALIGN(len); if (ARCH_SUN4C_SUN4 && (len > 0x20000000 || ((flags & MAP_FIXED) && addr < 0xe0000000 && addr + len > 0x20000000))) goto out_putf; /* See asm-sparc/uaccess.h */ if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) goto out_putf; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(¤t->mm->mmap_sem); retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); out_putf: if (file) fput(file); out: return retval; }
static int load_exeso_binary(struct linux_binprm *bprm, struct pt_regs *regs) { struct elfhdr *elf_ex; struct elf_phdr *elf_phdata = NULL; struct mm_struct *mm; unsigned long load_addr = 0; unsigned long error; int retval = 0; unsigned long pe_entry, ntdll_load_addr = 0; unsigned long start_code, end_code, start_data, end_data; unsigned long ntdll_entry; int executable_stack = EXSTACK_DEFAULT; unsigned long def_flags = 0; unsigned long stack_top; #ifdef NTDLL_SO unsigned long interp_load_addr; unsigned long interp_entry; #endif struct eprocess *process; struct ethread *thread; PRTL_USER_PROCESS_PARAMETERS ppb; OBJECT_ATTRIBUTES ObjectAttributes; INITIAL_TEB init_teb; BOOLEAN is_win32=FALSE; struct startup_info *info=NULL; struct eprocess *parent_eprocess=NULL; struct ethread *parent_ethread=NULL; struct w32process* child_w32process =NULL; struct w32process* parent_w32process =NULL; 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; 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; if(!check_exeso(bprm)) goto out; start_code = ~0UL; end_code = 0; start_data = 0; end_data = 0; if(current->parent->ethread) { is_win32 = TRUE; parent_ethread = current->parent->ethread; parent_eprocess = parent_ethread->threads_process; } /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) { goto out; } /* OK, This is the point of no return */ mm = current->mm; current->flags &= ~PF_FORKNOEXEC; mm->def_flags = def_flags; current->signal->rlim[RLIMIT_STACK].rlim_cur = WIN32_STACK_LIMIT; current->signal->rlim[RLIMIT_STACK].rlim_max = WIN32_STACK_LIMIT; current->personality |= ADDR_COMPAT_LAYOUT; arch_pick_mmap_layout(mm); /* Do this so that we can load the ntdll, if need be. We will change some of these later */ mm->free_area_cache = mm->mmap_base = WIN32_UNMAPPED_BASE; mm->cached_hole_size = 0; stack_top = WIN32_STACK_LIMIT + WIN32_LOWEST_ADDR; retval = setup_arg_pages(bprm, stack_top, executable_stack); if (retval < 0) goto out_free_file; down_write(&mm->mmap_sem); /* reserve first 0x100000 */ do_mmap_pgoff(NULL, 0, WIN32_LOWEST_ADDR, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0); /* reserve first 0x7fff0000 - 0x80000000 */ do_mmap_pgoff(NULL, WIN32_TASK_SIZE - 0x10000, 0x10000, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0); /* reserve first 0x81000000 - 0xc0000000 * 0x80000000 - 0x81000000 used for wine SYSTEM_HEAP */ do_mmap_pgoff(NULL, WIN32_TASK_SIZE + WIN32_SYSTEM_HEAP_SIZE, TASK_SIZE - WIN32_TASK_SIZE - WIN32_SYSTEM_HEAP_SIZE, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0); up_write(&mm->mmap_sem); #ifdef NTDLL_SO /* search ntdll.dll.so in $PATH, default is /usr/local/lib/wine/ntdll.dll.so */ if (!*ntdll_name) search_ntdll(); /* map ntdll.dll.so */ map_system_dll(current, ntdll_name, &ntdll_load_addr, &interp_load_addr); pe_entry = get_pe_entry(); ntdll_entry = get_ntdll_entry(); interp_entry = get_interp_entry(); #endif set_binfmt(&exeso_format); #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES retval = arch_setup_additional_pages(bprm, executable_stack); if (retval < 0) { goto out_free_file; } #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ install_exec_creds(bprm); current->flags &= ~PF_FORKNOEXEC; #ifdef NTDLL_SO /* copy argv, env, and auxvec to stack, all for interpreter */ create_elf_tables_aux(bprm, ntdll_load_addr, ntdll_phoff, ntdll_phnum, get_ntdll_start_thunk(), load_addr, elf_ex->e_phoff, elf_ex->e_phnum, 0, interp_load_addr, interp_entry, 0); #endif mm->end_code = end_code; mm->start_code = start_code; mm->start_data = start_data; mm->end_data = end_data; mm->start_stack = bprm->p; 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(&mm->mmap_sem); error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); up_write(&mm->mmap_sem); } /* create win-related structure */ INIT_OBJECT_ATTR(&ObjectAttributes, NULL, 0, NULL, NULL); /* Create EPROCESS */ retval = create_object(KernelMode, process_object_type, &ObjectAttributes, KernelMode, NULL, sizeof(struct eprocess), 0, 0, (PVOID *)&process); if (retval != STATUS_SUCCESS) { goto out_free_file; } /* init eprocess */ eprocess_init(NULL, FALSE, process); process->unique_processid = create_cid_handle(process, process_object_type); if (!process->unique_processid) goto out_free_eproc; /* initialize EProcess and KProcess */ process->section_base_address = (void *)load_addr; /* FIXME: PsCreateCidHandle */ /* Create PEB */ if ((retval = create_peb(process))) goto out_free_process_cid; /* Create PPB */ if(is_win32 == FALSE) { create_ppb(&ppb, process, bprm, bprm->filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL); ((PEB *)process->peb)->ProcessParameters = ppb; } /* allocate a Win32 thread object */ retval = create_object(KernelMode, thread_object_type, &ObjectAttributes, KernelMode, NULL, sizeof(struct ethread), 0, 0, (PVOID *)&thread); if (retval) { goto out_free_process_cid; } thread->cid.unique_thread = create_cid_handle(thread, thread_object_type); thread->cid.unique_process = process->unique_processid; if (!thread->cid.unique_thread) goto out_free_ethread; /* set the teb */ init_teb.StackBase = (PVOID)(bprm->p); init_teb.StackLimit = (PVOID)WIN32_LOWEST_ADDR + PAGE_SIZE; thread->tcb.teb = create_teb(process, (PCLIENT_ID)&thread->cid, &init_teb); if (IS_ERR(thread->tcb.teb)) { retval = PTR_ERR(thread->tcb.teb); goto out_free_thread_cid; } /* Init KThreaad */ ethread_init(thread, process, current); sema_init(&thread->exec_semaphore,0); if (is_win32 == TRUE) //parent is a windows process { down(&thread->exec_semaphore); //wait for the parent child_w32process = process->win32process; parent_w32process = parent_eprocess->win32process; info = child_w32process->startup_info; //now parent has finished its work if(thread->inherit_all) { create_handle_table(parent_eprocess, TRUE, process); child_w32process = create_w32process(parent_w32process, TRUE, process); } } deref_object(process); deref_object(thread); set_teb_selector(current, (long)thread->tcb.teb); thread->start_address = (void *)pe_entry; /* FIXME */ /* save current trap frame */ thread->tcb.trap_frame = (struct ktrap_frame *)regs; /* init apc, to call LdrInitializeThunk */ #if 0 thread_apc = kmalloc(sizeof(KAPC), GFP_KERNEL); if (!thread_apc) { retval = -ENOMEM; goto out_free_thread_cid; } apc_init(thread_apc, &thread->tcb, OriginalApcEnvironment, thread_special_apc, NULL, (PKNORMAL_ROUTINE)ntdll_entry, UserMode, (void *)(bprm->p + 12)); insert_queue_apc(thread_apc, (void *)interp_entry, (void *)extra_page, IO_NO_INCREMENT); #ifndef TIF_APC #define TIF_APC 13 #endif set_tsk_thread_flag(current, TIF_APC); #endif #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, interp_entry, bprm->p); if (unlikely(current->ptrace & PT_PTRACED)) { if (current->ptrace & PT_TRACE_EXEC) ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP); else send_sig(SIGTRAP, current, 0); } retval = 0; try_module_get(THIS_MODULE); /* return from w32syscall_exit, not syscall_exit */ ((unsigned long *)regs)[-1] = (unsigned long)w32syscall_exit; regs->fs = TEB_SELECTOR; out: if(elf_phdata) kfree(elf_phdata); return retval; /* error cleanup */ out_free_thread_cid: delete_cid_handle(thread->cid.unique_thread, thread_object_type); out_free_ethread: deref_object(thread); out_free_process_cid: delete_cid_handle(process->unique_processid, process_object_type); out_free_eproc: deref_object(process); out_free_file: send_sig(SIGKILL, current, 0); goto out; }