Module Name: src Committed By: kamil Date: Wed May 23 01:29:43 UTC 2018
Modified Files: src/tests/lib/libc/sys: t_ptrace_wait.c Log Message: Refactor the attach[1-8] and race1 ATF t_ptrace_wait* tests Share code in: attach1, attach2 and race1 in the same function body. Rename thsee tests to more verbose names: - tracer_sees_terminaton_before_the_parent - tracer_sysctl_lookup_without_duplicates - unrelated_tracer_sees_terminaton_before_the_parent Rename attach3 to parent_attach_to_its_child. Rename attach4 to child_attach_to_its_parent. Share code in attach5, attach6 and attach7 in the same function body and reanem the tests to: - tracee_sees_its_original_parent_getppid - tracee_sees_its_original_parent_sysctl_kinfo_proc2 - tracee_sees_its_original_parent_procfs_status Reduce the code by around 50%. No functional change intended. All tests pass. Sponsored by <The NetBSD Foundation> To generate a diff of this commit: cvs rdiff -u -r1.50 -r1.51 src/tests/lib/libc/sys/t_ptrace_wait.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/lib/libc/sys/t_ptrace_wait.c diff -u src/tests/lib/libc/sys/t_ptrace_wait.c:1.50 src/tests/lib/libc/sys/t_ptrace_wait.c:1.51 --- src/tests/lib/libc/sys/t_ptrace_wait.c:1.50 Tue May 22 10:48:06 2018 +++ src/tests/lib/libc/sys/t_ptrace_wait.c Wed May 23 01:29:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: t_ptrace_wait.c,v 1.50 2018/05/22 10:48:06 kamil Exp $ */ +/* $NetBSD: t_ptrace_wait.c,v 1.51 2018/05/23 01:29:43 kamil Exp $ */ /*- * Copyright (c) 2016 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: t_ptrace_wait.c,v 1.50 2018/05/22 10:48:06 kamil Exp $"); +__RCSID("$NetBSD: t_ptrace_wait.c,v 1.51 2018/05/23 01:29:43 kamil Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -852,16 +852,14 @@ ATF_TC_BODY(traceme_vfork_exec, tc) /// ---------------------------------------------------------------------------- #if defined(TWAIT_HAVE_PID) -ATF_TC(attach1); -ATF_TC_HEAD(attach1, tc) -{ - atf_tc_set_md_var(tc, "descr", - "Assert that tracer sees process termination before the parent"); -} - static void -attach1_raw(bool raw) +tracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated) { + /* + * notimeout - disable timeout in await zombie function + * unrelated - attach from unrelated tracer reparented to initproc + */ + struct msg_fds parent_tracee, parent_tracer; const int exitval_tracee = 5; const int exitval_tracer = 10; @@ -884,6 +882,13 @@ attach1_raw(bool raw) SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); tracer = atf_utils_fork(); if (tracer == 0) { + if(unrelated) { + /* Fork again and drop parent to reattach to PID 1 */ + tracer = atf_utils_fork(); + if (tracer != 0) + _exit(exitval_tracer); + } + DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); @@ -910,7 +915,21 @@ attach1_raw(bool raw) DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); DPRINTF("Before exiting of the tracer process\n"); - _exit(exitval_tracer); + _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); + } + + if (unrelated) { + DPRINTF("Wait for the tracer process (direct child) to exit " + "calling %s()\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS( + wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); + + validate_status_exited(status, exitval_tracer); + + DPRINTF("Wait for the non-exited tracee process with %s()\n", + TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS( + wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); } DPRINTF("Wait for the tracer to attach to the tracee\n"); @@ -920,7 +939,7 @@ attach1_raw(bool raw) PARENT_TO_CHILD("exit tracee", parent_tracee, msg); DPRINTF("Detect that tracee is zombie\n"); - if (raw) + if (notimeout) await_zombie_raw(tracee, 0); else await_zombie(tracee); @@ -931,21 +950,26 @@ attach1_raw(bool raw) TWAIT_REQUIRE_SUCCESS( wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); - DPRINTF("Tell the tracer child should have exited\n"); - PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); - DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", - TWAIT_FNAME); - - DPRINTF("Wait from tracer child to complete waiting for tracee\n"); - TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), - tracer); + if (unrelated) { + DPRINTF("Resume the tracer and let it detect exited tracee\n"); + PARENT_TO_CHILD("Message 2", parent_tracer, msg); + } else { + DPRINTF("Tell the tracer child should have exited\n"); + PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); + DPRINTF("Wait for tracer to finish its job and exit - calling " + "%s()\n", TWAIT_FNAME); + + DPRINTF("Wait from tracer child to complete waiting for " + "tracee\n"); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), + tracer); - validate_status_exited(status, exitval_tracer); + validate_status_exited(status, exitval_tracer); + } DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), - tracee); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); validate_status_exited(status, exitval_tracee); @@ -953,126 +977,76 @@ attach1_raw(bool raw) msg_close(&parent_tracee); } -ATF_TC_BODY(attach1, tc) +ATF_TC(tracer_sees_terminaton_before_the_parent); +ATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) { - - /* Reuse this test with race1 */ - attach1_raw(false); + atf_tc_set_md_var(tc, "descr", + "Assert that tracer sees process termination before the parent"); } -#endif +ATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) +{ -#if defined(TWAIT_HAVE_PID) -ATF_TC(attach2); -ATF_TC_HEAD(attach2, tc) + tracer_sees_terminaton_before_the_parent_raw(false, false); +} + +ATF_TC(tracer_sysctl_lookup_without_duplicates); +ATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) { atf_tc_set_md_var(tc, "descr", - "Assert that any tracer sees process termination before its " - "parent"); + "Assert that await_zombie() in attach1 always finds a single " + "process and no other error is reported"); } -ATF_TC_BODY(attach2, tc) +ATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) { - struct msg_fds parent_tracer, parent_tracee; - const int exitval_tracee = 5; - const int exitval_tracer1 = 10, exitval_tracer2 = 20; - pid_t tracee, tracer, wpid; - uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ -#if defined(TWAIT_HAVE_STATUS) - int status; -#endif - - DPRINTF("Spawn tracee\n"); - SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); - tracee = atf_utils_fork(); - if (tracee == 0) { - /* Wait for message from the parent */ - CHILD_FROM_PARENT("Message 1", parent_tracee, msg); - _exit(exitval_tracee); - } - - DPRINTF("Spawn debugger\n"); - SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); - tracer = atf_utils_fork(); - if (tracer == 0) { - /* Fork again and drop parent to reattach to PID 1 */ - tracer = atf_utils_fork(); - if (tracer != 0) - _exit(exitval_tracer1); - - DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); - FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); - - /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ - FORKEE_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); - - forkee_status_stopped(status, SIGSTOP); - - /* Resume tracee with PT_CONTINUE */ - FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); - - /* Inform parent that tracer has attached to tracee */ - CHILD_TO_PARENT("Message 1", parent_tracer, msg); - CHILD_FROM_PARENT("Message 2", parent_tracer, msg); - - /* Wait for tracee and assert that it exited */ - FORKEE_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); + time_t start, end; + double diff; + unsigned long N = 0; - forkee_status_exited(status, exitval_tracee); + /* + * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). + * This test body isn't specific to this race, however it's just good + * enough for this purposes, no need to invent a dedicated code flow. + */ - DPRINTF("Before exiting of the tracer process\n"); - _exit(exitval_tracer2); + start = time(NULL); + while (true) { + DPRINTF("Step: %lu\n", N); + tracer_sees_terminaton_before_the_parent_raw(true, false); + end = time(NULL); + diff = difftime(end, start); + if (diff >= 5.0) + break; + ++N; } - DPRINTF("Wait for the tracer process (direct child) to exit calling " - "%s()\n", TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); - - validate_status_exited(status, exitval_tracer1); - - DPRINTF("Wait for the non-exited tracee process with %s()\n", - TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); - - DPRINTF("Wait for the tracer to attach to the tracee\n"); - PARENT_FROM_CHILD("Message 1", parent_tracer, msg); - DPRINTF("Resume the tracee and let it exit\n"); - PARENT_TO_CHILD("Message 1", parent_tracee, msg); - - DPRINTF("Detect that tracee is zombie\n"); - await_zombie(tracee); - - DPRINTF("Assert that there is no status about tracee - " - "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); - - DPRINTF("Resume the tracer and let it detect exited tracee\n"); - PARENT_TO_CHILD("Message 2", parent_tracer, msg); + DPRINTF("Iterations: %lu\n", N); +} - DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", - TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), - tracee); +ATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); +ATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Assert that tracer sees process termination before the parent"); +} - validate_status_exited(status, exitval_tracee); +ATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) +{ - msg_close(&parent_tracer); - msg_close(&parent_tracee); + tracer_sees_terminaton_before_the_parent_raw(false, true); } #endif -ATF_TC(attach3); -ATF_TC_HEAD(attach3, tc) +/// ---------------------------------------------------------------------------- + +ATF_TC(parent_attach_to_its_child); +ATF_TC_HEAD(parent_attach_to_its_child, tc) { atf_tc_set_md_var(tc, "descr", "Assert that tracer parent can PT_ATTACH to its child"); } -ATF_TC_BODY(attach3, tc) +ATF_TC_BODY(parent_attach_to_its_child, tc) { struct msg_fds parent_tracee; const int exitval_tracee = 5; @@ -1124,14 +1098,16 @@ ATF_TC_BODY(attach3, tc) msg_close(&parent_tracee); } -ATF_TC(attach4); -ATF_TC_HEAD(attach4, tc) +/// ---------------------------------------------------------------------------- + +ATF_TC(child_attach_to_its_parent); +ATF_TC_HEAD(child_attach_to_its_parent, tc) { atf_tc_set_md_var(tc, "descr", "Assert that tracer child can PT_ATTACH to its parent"); } -ATF_TC_BODY(attach4, tc) +ATF_TC_BODY(child_attach_to_its_parent, tc) { struct msg_fds parent_tracee; const int exitval_tracer = 5; @@ -1188,16 +1164,18 @@ ATF_TC_BODY(attach4, tc) msg_close(&parent_tracee); } +/// ---------------------------------------------------------------------------- + #if defined(TWAIT_HAVE_PID) -ATF_TC(attach5); -ATF_TC_HEAD(attach5, tc) -{ - atf_tc_set_md_var(tc, "descr", - "Assert that tracer sees its parent when attached to tracer " - "(check getppid(2))"); -} -ATF_TC_BODY(attach5, tc) +enum tracee_sees_its_original_parent_type { + TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, + TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, + TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS +}; + +static void +tracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) { struct msg_fds parent_tracer, parent_tracee; const int exitval_tracee = 5; @@ -1207,6 +1185,27 @@ ATF_TC_BODY(attach5, tc) #if defined(TWAIT_HAVE_STATUS) int status; #endif + /* sysctl(3) - kinfo_proc2 */ + int name[CTL_MAXNAME]; + struct kinfo_proc2 kp; + size_t len = sizeof(kp); + unsigned int namelen; + + /* procfs - status */ + FILE *fp; + struct stat st; + const char *fname = "/proc/curproc/status"; + char s_executable[MAXPATHLEN]; + int s_pid, s_ppid; + int rv; + + if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { + SYSCALL_REQUIRE((rv = stat(fname, &st)) == 0 || + (errno == ENOENT)); + if (rv != 0) { + atf_tc_skip("/proc/curproc/status not found"); + } + } DPRINTF("Spawn tracee\n"); SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); @@ -1219,7 +1218,35 @@ ATF_TC_BODY(attach5, tc) CHILD_TO_PARENT("tracee ready", parent_tracee, msg); CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); - FORKEE_ASSERT_EQ(parent, getppid()); + switch (type) { + case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: + FORKEE_ASSERT_EQ(parent, getppid()); + break; + case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: + namelen = 0; + name[namelen++] = CTL_KERN; + name[namelen++] = KERN_PROC2; + name[namelen++] = KERN_PROC_PID; + name[namelen++] = getpid(); + name[namelen++] = len; + name[namelen++] = 1; + + FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, + 0), + 0); + FORKEE_ASSERT_EQ(parent, kp.p_ppid); + break; + case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: + /* + * Format: + * EXECUTABLE PID PPID ... + */ + FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); + fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); + FORKEE_ASSERT_EQ(fclose(fp), 0); + FORKEE_ASSERT_EQ(parent, s_ppid); + break; + } _exit(exitval_tracee); } @@ -1291,248 +1318,37 @@ ATF_TC_BODY(attach5, tc) msg_close(&parent_tracer); msg_close(&parent_tracee); } -#endif - -#if defined(TWAIT_HAVE_PID) -ATF_TC(attach6); -ATF_TC_HEAD(attach6, tc) -{ - atf_tc_set_md_var(tc, "descr", - "Assert that tracer sees its parent when attached to tracer " - "(check sysctl(7) and struct kinfo_proc2)"); -} - -ATF_TC_BODY(attach6, tc) -{ - struct msg_fds parent_tracee, parent_tracer; - const int exitval_tracee = 5; - const int exitval_tracer = 10; - pid_t parent, tracee, tracer, wpid; - uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ -#if defined(TWAIT_HAVE_STATUS) - int status; -#endif - int name[CTL_MAXNAME]; - struct kinfo_proc2 kp; - size_t len = sizeof(kp); - unsigned int namelen; - - DPRINTF("Spawn tracee\n"); - SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); - SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); - tracee = atf_utils_fork(); - if (tracee == 0) { - parent = getppid(); - - /* Emit message to the parent */ - CHILD_TO_PARENT("Message 1", parent_tracee, msg); - CHILD_FROM_PARENT("Message 2", parent_tracee, msg); - - namelen = 0; - name[namelen++] = CTL_KERN; - name[namelen++] = KERN_PROC2; - name[namelen++] = KERN_PROC_PID; - name[namelen++] = getpid(); - name[namelen++] = len; - name[namelen++] = 1; - - FORKEE_ASSERT(sysctl(name, namelen, &kp, &len, NULL, 0) == 0); - FORKEE_ASSERT_EQ(parent, kp.p_ppid); - - _exit(exitval_tracee); - } - - DPRINTF("Wait for child to record its parent identifier (pid)\n"); - PARENT_FROM_CHILD("Message 1", parent_tracee, msg); - - DPRINTF("Spawn debugger\n"); - tracer = atf_utils_fork(); - if (tracer == 0) { - /* No IPC to communicate with the child */ - DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); - FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); - - /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ - FORKEE_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); - - forkee_status_stopped(status, SIGSTOP); - - /* Resume tracee with PT_CONTINUE */ - FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); - - /* Inform parent that tracer has attached to tracee */ - CHILD_TO_PARENT("Message 1", parent_tracer, msg); - - CHILD_FROM_PARENT("Message 2", parent_tracer, msg); - - /* Wait for tracee and assert that it exited */ - FORKEE_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); - - forkee_status_exited(status, exitval_tracee); - - DPRINTF("Before exiting of the tracer process\n"); - _exit(exitval_tracer); - } - - DPRINTF("Wait for the tracer to attach to the tracee\n"); - PARENT_FROM_CHILD("Message 1", parent_tracer, msg); - - DPRINTF("Resume the tracee and let it exit\n"); - PARENT_TO_CHILD("Message 1", parent_tracee, msg); - - DPRINTF("Detect that tracee is zombie\n"); - await_zombie(tracee); - - DPRINTF("Assert that there is no status about tracee - " - "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); - - DPRINTF("Resume the tracer and let it detect exited tracee\n"); - PARENT_TO_CHILD("Message 2", parent_tracer, msg); - - DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", - TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), - tracer); - - validate_status_exited(status, exitval_tracer); - - DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", - TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), - tracee); - - validate_status_exited(status, exitval_tracee); - - msg_close(&parent_tracee); - msg_close(&parent_tracer); -} -#endif -#if defined(TWAIT_HAVE_PID) -ATF_TC(attach7); -ATF_TC_HEAD(attach7, tc) -{ - atf_tc_set_md_var(tc, "descr", - "Assert that tracer sees its parent when attached to tracer " - "(check /proc/curproc/status 3rd column)"); +#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ +ATF_TC(test); \ +ATF_TC_HEAD(test, tc) \ +{ \ + atf_tc_set_md_var(tc, "descr", \ + "Assert that tracee sees its original parent when being traced " \ + "(check " descr ")"); \ +} \ + \ +ATF_TC_BODY(test, tc) \ +{ \ + \ + tracee_sees_its_original_parent(type); \ } -ATF_TC_BODY(attach7, tc) -{ - struct msg_fds parent_tracee, parent_tracer; - int rv; - const int exitval_tracee = 5; - const int exitval_tracer = 10; - pid_t parent, tracee, tracer, wpid; - uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ -#if defined(TWAIT_HAVE_STATUS) - int status; +TRACEE_SEES_ITS_ORIGINAL_PARENT( + tracee_sees_its_original_parent_getppid, + TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, + "getppid(2)"); +TRACEE_SEES_ITS_ORIGINAL_PARENT( + tracee_sees_its_original_parent_sysctl_kinfo_proc2, + TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, + "sysctl(3) and kinfo_proc2"); +TRACEE_SEES_ITS_ORIGINAL_PARENT( + tracee_sees_its_original_parent_procfs_status, + TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, + "the status file in procfs"); #endif - FILE *fp; - struct stat st; - const char *fname = "/proc/curproc/status"; - char s_executable[MAXPATHLEN]; - int s_pid, s_ppid; - /* - * Format: - * EXECUTABLE PID PPID ... - */ - - SYSCALL_REQUIRE((rv = stat(fname, &st)) == 0 || (errno == ENOENT)); - if (rv != 0) { - atf_tc_skip("/proc/curproc/status not found"); - } - - DPRINTF("Spawn tracee\n"); - SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); - SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); - tracee = atf_utils_fork(); - if (tracee == 0) { - parent = getppid(); - - // Wait for parent to let us exit - CHILD_TO_PARENT("tracee ready", parent_tracee, msg); - CHILD_FROM_PARENT("tracee exit", parent_tracee, msg); - FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); - fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); - FORKEE_ASSERT(fclose(fp) == 0); - FORKEE_ASSERT_EQ(parent, s_ppid); - - _exit(exitval_tracee); - } - - DPRINTF("Wait for child to record its parent identifier (pid)\n"); - PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); - - DPRINTF("Spawn debugger\n"); - tracer = atf_utils_fork(); - if (tracer == 0) { - DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); - FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); - - /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ - FORKEE_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); - - forkee_status_stopped(status, SIGSTOP); - - /* Resume tracee with PT_CONTINUE */ - FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); - - /* Inform parent that tracer has attached to tracee */ - CHILD_TO_PARENT("tracer ready", parent_tracer, msg); - - /* Wait for parent to tell use that tracee should have exited */ - CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); - - /* Wait for tracee and assert that it exited */ - FORKEE_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); - - forkee_status_exited(status, exitval_tracee); - - DPRINTF("Before exiting of the tracer process\n"); - _exit(exitval_tracer); - } - DPRINTF("Wait for the tracer to attach to the tracee\n"); - PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); - DPRINTF("Resume the tracee and let it exit\n"); - PARENT_TO_CHILD("tracee exit", parent_tracee, msg); - - DPRINTF("Detect that tracee is zombie\n"); - await_zombie(tracee); - - DPRINTF("Assert that there is no status about tracee - " - "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS( - wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); - - DPRINTF("Resume the tracer and let it detect exited tracee\n"); - PARENT_TO_CHILD("Message 2", parent_tracer, msg); - - DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", - TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), - tracer); - - validate_status_exited(status, exitval_tracer); - - DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", - TWAIT_FNAME); - TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), - tracee); - - validate_status_exited(status, exitval_tracee); - - msg_close(&parent_tracee); - msg_close(&parent_tracer); -} -#endif +/// ---------------------------------------------------------------------------- ATF_TC(eventmask1); ATF_TC_HEAD(eventmask1, tc) @@ -7242,37 +7058,6 @@ ATF_TC_BODY(syscallemu1, tc) TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } -#if defined(TWAIT_HAVE_PID) -ATF_TC(race1); -ATF_TC_HEAD(race1, tc) -{ - atf_tc_set_md_var(tc, "descr", - "Assert that await_zombie() in attach1 always finds a single " - "process and no other error is reported"); -} - -ATF_TC_BODY(race1, tc) -{ - time_t start, end; - double diff; - unsigned long N = 0; - - /* Reuse this test with attach1 */ - - start = time(NULL); - while (true) { - DPRINTF("Step: %lu\n", N); - attach1_raw(true); - end = time(NULL); - diff = difftime(end, start); - if (diff >= 5.0) - break; - ++N; - } - DPRINTF("Iterations: %lu\n", N); -} -#endif - #include "t_ptrace_amd64_wait.h" #include "t_ptrace_i386_wait.h" #include "t_ptrace_x86_wait.h" @@ -7321,13 +7106,20 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, traceme_vfork_exec); - ATF_TP_ADD_TC_HAVE_PID(tp, attach1); - ATF_TP_ADD_TC_HAVE_PID(tp, attach2); - ATF_TP_ADD_TC(tp, attach3); - ATF_TP_ADD_TC(tp, attach4); - ATF_TP_ADD_TC_HAVE_PID(tp, attach5); - ATF_TP_ADD_TC_HAVE_PID(tp, attach6); - ATF_TP_ADD_TC_HAVE_PID(tp, attach7); + ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); + ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); + ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_terminaton_before_the_parent); + + ATF_TP_ADD_TC(tp, parent_attach_to_its_child); + + ATF_TP_ADD_TC(tp, child_attach_to_its_parent); + + ATF_TP_ADD_TC_HAVE_PID(tp, + tracee_sees_its_original_parent_getppid); + ATF_TP_ADD_TC_HAVE_PID(tp, + tracee_sees_its_original_parent_sysctl_kinfo_proc2); + ATF_TP_ADD_TC_HAVE_PID(tp, + tracee_sees_its_original_parent_procfs_status); ATF_TP_ADD_TC(tp, eventmask1); ATF_TP_ADD_TC(tp, eventmask2); @@ -7448,8 +7240,6 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, syscallemu1); - ATF_TP_ADD_TC_HAVE_PID(tp, race1); - ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); ATF_TP_ADD_TCS_PTRACE_WAIT_X86();