Beispiel #1
0
/* Currently supported flags (see sched.h):
 o CLONE_VM
 o CLONE_FS
 o CLONE_SIGHAND
 o CLONE_PTRACE
 o CLONE_VFORK
 o CLONE_PARENT
 o CLONE_THREAD
 o CLONE_NEWNS
 o CLONE_SYSVSEM
 o CLONE_SETTLS
 o CLONE_PARENT_SETTID
 o CLONE_CHILD_CLEARTID
 o CLONE_DETACHED
 o CLONE_UNTRACED
 * CLONE_CHILD_SETTID
 o CLONE_NEWUTS
 o CLONE_NEWIPC
 o CLONE_NEWUSER
 o CLONE_NEWPID
 o CLONE_NEWNET
 o CLONE_IO
*/
static pid_t fork_process(struct syscall_context *context, unsigned long flags, void *ptid, void *ctid)
{
    wchar_t filename[MAX_PATH];
    GetModuleFileNameW(NULL, filename, sizeof(filename) / sizeof(filename[0]));

    tls_beforefork();

    PROCESS_INFORMATION info;
    STARTUPINFOW si = { 0 };
    si.cb = sizeof(si);
    if (!CreateProcessW(filename, L"/?/fork", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, &info))
    {
        log_warning("fork(): CreateProcessW() failed.\n");
        return -1;
    }

    if (!mm_fork(info.hProcess))
        goto fail;

    if (!vfs_fork(info.hProcess))
        goto fail;

    /* Set up fork_info in child process */
    void *stack_base = process_get_stack_base();
    VirtualAllocEx(info.hProcess, FORK_INFO_BASE, BLOCK_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(info.hProcess, &fork->context, context, sizeof(struct syscall_context), NULL);
    WriteProcessMemory(info.hProcess, &fork->stack_base, &stack_base, sizeof(stack_base), NULL);
    if (flags & CLONE_CHILD_SETTID)
        WriteProcessMemory(info.hProcess, &fork->ctid, &ctid, sizeof(void*), NULL);

    /* Copy stack */
    VirtualAllocEx(info.hProcess, stack_base, STACK_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(info.hProcess, context->esp, context->esp, (char *)stack_base + STACK_SIZE - context->esp, NULL);

    ResumeThread(info.hThread);

    CloseHandle(info.hThread);
    /* Process handled will be used for wait() */
    log_info("Child pid: %d\n", info.dwProcessId);
    process_add_child(info.dwProcessId, info.hProcess);
    return info.dwProcessId;

fail:
    TerminateProcess(info.hProcess, 0);
    CloseHandle(info.hThread);
    CloseHandle(info.hProcess);
    return -1;
}
Beispiel #2
0
gfarm_error_t
gfm_server_process_alloc_child(struct peer *peer, int from_client, int skip)
{
	gfarm_int32_t e;
	struct user *user;
	gfarm_int32_t parent_keytype, keytype;
	size_t parent_keylen, keylen;
	char parent_sharedkey[GFM_PROTO_PROCESS_KEY_LEN_SHAREDSECRET];
	char sharedkey[GFM_PROTO_PROCESS_KEY_LEN_SHAREDSECRET];
	struct process *parent_process, *process;
	gfarm_pid_t parent_pid, pid;

	e = gfm_server_get_request(peer, "process_alloc_child", "iblib",
	    &parent_keytype,
	    sizeof(parent_sharedkey), &parent_keylen, parent_sharedkey,
	    &parent_pid,
	    &keytype, sizeof(sharedkey), &keylen, sharedkey);
	if (e != GFARM_ERR_NO_ERROR)
		return (e);
	if (skip)
		return (GFARM_ERR_NO_ERROR);

	giant_lock();
	if (peer_get_process(peer) != NULL) {
		e = GFARM_ERR_ALREADY_EXISTS;
	} else if (!from_client || (user = peer_get_user(peer)) == NULL) {
		e = GFARM_ERR_OPERATION_NOT_PERMITTED;
	} else if (parent_keytype != GFM_PROTO_PROCESS_KEY_TYPE_SHAREDSECRET ||
	    parent_keylen != GFM_PROTO_PROCESS_KEY_LEN_SHAREDSECRET) {
		e = GFARM_ERR_INVALID_ARGUMENT;
	} else if ((e = process_does_match(parent_pid,
	    parent_keytype, parent_keylen, parent_sharedkey,
	    &parent_process)) != GFARM_ERR_NO_ERROR) {
		/* error */
	} else if ((e = process_alloc(user, keytype, keylen, sharedkey,
	    &process, &pid)) == GFARM_ERR_NO_ERROR) {
		peer_set_process(peer, process);
		process_add_child(parent_process, process);
	}
	giant_unlock();
	return (gfm_server_put_reply(peer, "process_alloc_child", e, "l",
	    pid));
}