示例#1
0
ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
{
    pid_t children[2], fpid, wpid;
    int cpipe[2], status;

    ATF_REQUIRE(pipe(cpipe) == 0);
    ATF_REQUIRE((fpid = fork()) != -1);
    if (fpid == 0) {
        attach_fork_parent(cpipe);
        follow_fork_parent();
    }

    /* Parent process. */
    close(cpipe[1]);

    /* Wait for the direct child to exit. */
    wpid = waitpid(fpid, &status, 0);
    ATF_REQUIRE(wpid == fpid);
    ATF_REQUIRE(WIFEXITED(status));
    ATF_REQUIRE(WEXITSTATUS(status) == 3);

    /* Read the pid of the fork parent. */
    ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
                sizeof(children[0]));

    /* Attach to the fork parent. */
    attach_child(children[0]);

    ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);

    /* Continue the fork parent ignoring the SIGSTOP. */
    ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);

    /* Signal the fork parent to continue. */
    close(cpipe[0]);

    children[1] = handle_fork_events(children[0]);
    ATF_REQUIRE(children[1] > 0);

    ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
    ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);

    /*
     * The fork parent can't exit until the child reports status,
     * so the child should report its exit first to the debugger.
     */
    wpid = wait(&status);
    ATF_REQUIRE(wpid == children[1]);
    ATF_REQUIRE(WIFEXITED(status));
    ATF_REQUIRE(WEXITSTATUS(status) == 2);

    wpid = wait(&status);
    ATF_REQUIRE(wpid == children[0]);
    ATF_REQUIRE(WIFEXITED(status));
    ATF_REQUIRE(WEXITSTATUS(status) == 1);

    wpid = wait(&status);
    ATF_REQUIRE(wpid == -1);
    ATF_REQUIRE(errno == ECHILD);
}
ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
{
	struct ptrace_lwpinfo pl[2];
	pid_t children[2], fpid, wpid;
	int status;

	ATF_REQUIRE((fpid = fork()) != -1);
	if (fpid == 0) {
		trace_me();
		follow_fork_parent(false);
	}

	/* Parent process. */
	children[0] = fpid;

	/* The first wait() should report the stop from SIGSTOP. */
	wpid = waitpid(children[0], &status, 0);
	ATF_REQUIRE(wpid == children[0]);
	ATF_REQUIRE(WIFSTOPPED(status));
	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);

	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);

	/* Continue the child ignoring the SIGSTOP. */
	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);

	/* Wait for both halves of the fork event to get reported. */
	children[1] = handle_fork_events(children[0], pl);
	ATF_REQUIRE(children[1] > 0);

	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_fork);
	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);

	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);

	/*
	 * The child can't exit until the grandchild reports status, so the
	 * grandchild should report its exit first to the debugger.
	 */
	wpid = wait(&status);
	ATF_REQUIRE(wpid == children[1]);
	ATF_REQUIRE(WIFEXITED(status));
	ATF_REQUIRE(WEXITSTATUS(status) == 2);

	wpid = wait(&status);
	ATF_REQUIRE(wpid == children[0]);
	ATF_REQUIRE(WIFEXITED(status));
	ATF_REQUIRE(WEXITSTATUS(status) == 1);

	wpid = wait(&status);
	ATF_REQUIRE(wpid == -1);
	ATF_REQUIRE(errno == ECHILD);
}
示例#3
0
ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
{
    pid_t children[2], fpid, wpid;
    int status;

    ATF_REQUIRE((fpid = fork()) != -1);
    if (fpid == 0) {
        trace_me();
        follow_fork_parent();
    }

    /* Parent process. */
    children[0] = fpid;

    /* The first wait() should report the stop from SIGSTOP. */
    wpid = waitpid(children[0], &status, 0);
    ATF_REQUIRE(wpid == children[0]);
    ATF_REQUIRE(WIFSTOPPED(status));
    ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);

    ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);

    /* Continue the child ignoring the SIGSTOP. */
    ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);

    children[1] = handle_fork_events(children[0]);
    ATF_REQUIRE(children[1] > 0);

    ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
    ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);

    /*
     * The child can't exit until the grandchild reports status, so the
     * grandchild should report its exit first to the debugger.
     *
     * Even though the child process is detached, it is still a
     * child of the debugger, so it will still report it's exit
     * after the grandchild.
     */
    wpid = wait(&status);
    ATF_REQUIRE(wpid == children[1]);
    ATF_REQUIRE(WIFEXITED(status));
    ATF_REQUIRE(WEXITSTATUS(status) == 2);

    wpid = wait(&status);
    ATF_REQUIRE(wpid == children[0]);
    ATF_REQUIRE(WIFEXITED(status));
    ATF_REQUIRE(WEXITSTATUS(status) == 1);

    wpid = wait(&status);
    ATF_REQUIRE(wpid == -1);
    ATF_REQUIRE(errno == ECHILD);
}
示例#4
0
ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
{
    pid_t children[2], fpid, wpid;
    int status;

    ATF_REQUIRE((fpid = fork()) != -1);
    if (fpid == 0) {
        trace_me();
        follow_fork_parent();
    }

    /* Parent process. */
    children[0] = fpid;

    /* The first wait() should report the stop from SIGSTOP. */
    wpid = waitpid(children[0], &status, 0);
    ATF_REQUIRE(wpid == children[0]);
    ATF_REQUIRE(WIFSTOPPED(status));
    ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);

    ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);

    /* Continue the child ignoring the SIGSTOP. */
    ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);

    children[1] = handle_fork_events(children[0]);
    ATF_REQUIRE(children[1] > 0);

    ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
    ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);

    /*
     * Should not see any status from the grandchild now, only the
     * child.
     */
    wpid = wait(&status);
    ATF_REQUIRE(wpid == children[0]);
    ATF_REQUIRE(WIFEXITED(status));
    ATF_REQUIRE(WEXITSTATUS(status) == 1);

    wpid = wait(&status);
    ATF_REQUIRE(wpid == -1);
    ATF_REQUIRE(errno == ECHILD);
}