int start_userspace()

in os-Linux/skas/process.c [312:380]


int start_userspace(unsigned long stub_stack)
{
	void *stack;
	unsigned long sp;
	int pid, status, n, flags, err;

	/* setup a temporary stack page */
	stack = mmap(NULL, UM_KERN_PAGE_SIZE,
		     PROT_READ | PROT_WRITE | PROT_EXEC,
		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	if (stack == MAP_FAILED) {
		err = -errno;
		printk(UM_KERN_ERR "start_userspace : mmap failed, "
		       "errno = %d\n", errno);
		return err;
	}

	/* set stack pointer to the end of the stack page, so it can grow downwards */
	sp = (unsigned long)stack + UM_KERN_PAGE_SIZE;

	flags = CLONE_FILES | SIGCHLD;

	/* clone into new userspace process */
	pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
	if (pid < 0) {
		err = -errno;
		printk(UM_KERN_ERR "start_userspace : clone failed, "
		       "errno = %d\n", errno);
		return err;
	}

	do {
		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
		if (n < 0) {
			err = -errno;
			printk(UM_KERN_ERR "start_userspace : wait failed, "
			       "errno = %d\n", errno);
			goto out_kill;
		}
	} while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGALRM));

	if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
		err = -EINVAL;
		printk(UM_KERN_ERR "start_userspace : expected SIGSTOP, got "
		       "status = %d\n", status);
		goto out_kill;
	}

	if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
		   (void *) PTRACE_O_TRACESYSGOOD) < 0) {
		err = -errno;
		printk(UM_KERN_ERR "start_userspace : PTRACE_OLDSETOPTIONS "
		       "failed, errno = %d\n", errno);
		goto out_kill;
	}

	if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {
		err = -errno;
		printk(UM_KERN_ERR "start_userspace : munmap failed, "
		       "errno = %d\n", errno);
		goto out_kill;
	}

	return pid;

 out_kill:
	os_kill_ptraced_process(pid, 1);
	return err;
}