示例#1
0
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(&current->mm->mmap_sem);
	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->mm->mmap_sem);
	if (file)
		fput(file);

out:
	return error;
}
示例#2
0
文件: ring.c 项目: relip/blktap-dkms
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;
}
示例#3
0
文件: map.c 项目: virthub/virthub
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;
}
示例#4
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(&current->mm->mmap_sem);
	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->mm->mmap_sem);

	if (file)
		fput(file);
out:
	return error;
}
示例#5
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 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(&current->mm->mmap_sem);
	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->mm->mmap_sem);

	if (file)
		fput(file);
out:
	return error;
}
示例#6
0
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(&current->mm->mmap_sem);
	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->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(&current->mm->mmap_sem);
	addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->mm->mmap_sem);

out:	if (file)
		fput(file);
	return addr;
}
示例#8
0
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;
	
}
示例#9
0
/**
 * \<\<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(&current->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(&current->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;
}
示例#10
0
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(&current->mm->mmap_sem);
	addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->mm->mmap_sem);

out:	if (file)
		fput(file);
	return addr;
}
示例#11
0
文件: sys_i386.c 项目: ut-osa/txos
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;
}
示例#12
0
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(&current->mm->mmap_sem);    //写者获取当前进程空间的mmap_sem信号量   
	addr =do_mmap_pgoff( NULL, 100, len , PROT_WRITE | PROT_READ , MAP_ANONYMOUS | MAP_SHARED , 0 );
	up_write(&current->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;
}
示例#13
0
文件: util.c 项目: 3null/fastsocket
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(&current->mm->mmap_sem);
	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->mm->mmap_sem);

	if (file)
		fput(file);
out:
	return retval;
}
示例#14
0
/*
 * 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;
}
示例#15
0
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(&current->mm->mmap_sem);
	ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->mm->mmap_sem);
	if (file)
		fput(file);
out:
	return ret;
}
示例#16
0
/* 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;
}
示例#17
0
/* 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(&current->mm->mmap_sem);
	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->mm->mmap_sem);

out_putf:
	if (file)
		fput(file);
out:
	return retval;
}
示例#18
0
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;
}