Index: vendor/NetBSD/tests/dist/kernel/t_mqueue.c =================================================================== --- vendor/NetBSD/tests/dist/kernel/t_mqueue.c (revision 312218) +++ vendor/NetBSD/tests/dist/kernel/t_mqueue.c (revision 312219) @@ -1,138 +1,138 @@ -/* $NetBSD: t_mqueue.c,v 1.5 2017/01/10 22:10:22 christos Exp $ */ +/* $NetBSD: t_mqueue.c,v 1.6 2017/01/14 20:57:24 christos Exp $ */ /* * Test for POSIX message queue priority handling. * * This file is in the Public Domain. */ -#include #include +#include +#include +#include +#include #include #include #include -#include #include - -#include #define MQ_PRIO_BASE 24 static void send_msgs(mqd_t mqfd) { char msg[2]; msg[1] = '\0'; msg[0] = 'a'; ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), MQ_PRIO_BASE) != -1, "mq_send 1 failed: %d", errno); msg[0] = 'b'; ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), MQ_PRIO_BASE + 1) != -1, "mq_send 2 failed: %d", errno); msg[0] = 'c'; ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), MQ_PRIO_BASE) != -1, "mq_send 3 failed: %d", errno); msg[0] = 'd'; ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), MQ_PRIO_BASE - 1) != -1, "mq_send 4 failed: %d", errno); msg[0] = 'e'; ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), 0) != -1, "mq_send 5 failed: %d", errno); msg[0] = 'f'; ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), MQ_PRIO_BASE + 1) != -1, "mq_send 6 failed: %d", errno); } static void receive_msgs(mqd_t mqfd) { struct mq_attr mqa; char *m; unsigned p; int len; ATF_REQUIRE_MSG(mq_getattr(mqfd, &mqa) != -1, "mq_getattr failed %d", errno); len = mqa.mq_msgsize; m = calloc(1, len); ATF_REQUIRE_MSG(m != NULL, "calloc failed"); ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1, "mq_receive 1 failed: %d", errno); ATF_REQUIRE_MSG(p == (MQ_PRIO_BASE + 1) && m[0] == 'b', "mq_receive 1 prio/data mismatch"); ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1, "mq_receive 2 failed: %d", errno); ATF_REQUIRE_MSG(p == (MQ_PRIO_BASE + 1) && m[0] == 'f', "mq_receive 2 prio/data mismatch"); ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1, "mq_receive 3 failed: %d", errno); ATF_REQUIRE_MSG(p == MQ_PRIO_BASE && m[0] == 'a', "mq_receive 3 prio/data mismatch"); ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1, "mq_receive 4 failed: %d", errno); ATF_REQUIRE_MSG(p == MQ_PRIO_BASE && m[0] == 'c', "mq_receive 4 prio/data mismatch"); ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1, "mq_receive 5 failed: %d", errno); ATF_REQUIRE_MSG(p == (MQ_PRIO_BASE - 1) && m[0] == 'd', "mq_receive 5 prio/data mismatch"); ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1, "mq_receive 6 failed: %d", errno); ATF_REQUIRE_MSG(p == 0 && m[0] == 'e', "mq_receive 6 prio/data mismatch"); } ATF_TC(mqueue); ATF_TC_HEAD(mqueue, tc) { atf_tc_set_md_var(tc, "timeout", "3"); atf_tc_set_md_var(tc, "descr", "Checks mqueue send/receive"); } ATF_TC_BODY(mqueue, tc) { int status; char *tmpdir; char template[32]; char mq_name[64]; strlcpy(template, "./t_mqueue.XXXXXX", sizeof(template)); tmpdir = mkdtemp(template); ATF_REQUIRE_MSG(tmpdir != NULL, "mkdtemp failed: %d", errno); snprintf(mq_name, sizeof(mq_name), "%s/mq", tmpdir); mqd_t mqfd; mqfd = mq_open(mq_name, O_RDWR | O_CREAT, S_IRUSR | S_IRWXG | S_IROTH, NULL); ATF_REQUIRE_MSG(mqfd != -1, "mq_open failed: %d", errno); send_msgs(mqfd); receive_msgs(mqfd); status = mq_close(mqfd); ATF_REQUIRE_MSG(status == 0, "mq_close failed: %d", errno); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, mqueue); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/kernel/t_ptrace_wait.c =================================================================== --- vendor/NetBSD/tests/dist/kernel/t_ptrace_wait.c (revision 312218) +++ vendor/NetBSD/tests/dist/kernel/t_ptrace_wait.c (revision 312219) @@ -1,5384 +1,5702 @@ -/* $NetBSD: t_ptrace_wait.c,v 1.58 2017/01/14 04:37:55 kamil Exp $ */ +/* $NetBSD: t_ptrace_wait.c,v 1.60 2017/01/14 19:17:10 kamil Exp $ */ /*- * Copyright (c) 2016 The NetBSD Foundation, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_ptrace_wait.c,v 1.58 2017/01/14 04:37:55 kamil Exp $"); +__RCSID("$NetBSD: t_ptrace_wait.c,v 1.60 2017/01/14 19:17:10 kamil Exp $"); #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include "h_macros.h" #include "t_ptrace_wait.h" #include "msg.h" #define PARENT_TO_CHILD(info, fds, msg) \ ATF_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, sizeof(msg)) == 0) #define CHILD_FROM_PARENT(info, fds, msg) \ FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0) #define CHILD_TO_PARENT(info, fds, msg) \ FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, sizeof(msg)) == 0) #define PARENT_FROM_CHILD(info, fds, msg) \ ATF_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0) ATF_TC(traceme1); ATF_TC_HEAD(traceme1, tc) { atf_tc_set_md_var(tc, "descr", "Verify SIGSTOP followed by _exit(2) in a child"); } ATF_TC_BODY(traceme1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(traceme2); ATF_TC_HEAD(traceme2, tc) { atf_tc_set_md_var(tc, "descr", "Verify SIGSTOP followed by _exit(2) in a child"); } static int traceme2_caught = 0; static void traceme2_sighandler(int sig) { FORKEE_ASSERT_EQ(sig, SIGINT); ++traceme2_caught; } ATF_TC_BODY(traceme2, tc) { const int exitval = 5; const int sigval = SIGSTOP, sigsent = SIGINT; pid_t child, wpid; struct sigaction sa; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); sa.sa_handler = traceme2_sighandler; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(traceme2_caught, 1); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before resuming the child process where it left off and with " "signal %s to be sent\n", strsignal(sigsent)); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the exited child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(traceme3); ATF_TC_HEAD(traceme3, tc) { atf_tc_set_md_var(tc, "descr", "Verify SIGSTOP followed by termination by a signal in a child"); } ATF_TC_BODY(traceme3, tc) { const int sigval = SIGSTOP, sigsent = SIGINT /* Without core-dump */; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); /* NOTREACHED */ FORKEE_ASSERTX(0 && "Child should be terminated by a signal from its parent"); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before resuming the child process where it left off and with " "signal %s to be sent\n", strsignal(sigsent)); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_signaled(status, sigsent, 0); printf("Before calling %s() for the exited child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(traceme4); ATF_TC_HEAD(traceme4, tc) { atf_tc_set_md_var(tc, "descr", "Verify SIGSTOP followed by SIGCONT and _exit(2) in a child"); } ATF_TC_BODY(traceme4, tc) { const int exitval = 5; const int sigval = SIGSTOP, sigsent = SIGCONT; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before raising %s from child\n", strsignal(sigsent)); FORKEE_ASSERT(raise(sigsent) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(),child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigsent); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the exited child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #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"); } ATF_TC_BODY(attach1, tc) { struct msg_fds parent_tracee, parent_tracer; const int exitval_tracee = 5; const int exitval_tracer = 10; 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 printf("Spawn tracee\n"); ATF_REQUIRE(msg_open(&parent_tracee) == 0); tracee = atf_utils_fork(); if (tracee == 0) { // Wait for parent to let us exit CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); _exit(exitval_tracee); } printf("Spawn debugger\n"); ATF_REQUIRE(msg_open(&parent_tracer) == 0); tracer = atf_utils_fork(); if (tracer == 0) { printf("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); printf("Tracee %d exited with %d\n", tracee, exitval_tracee); printf("Before exiting of the tracer process\n"); _exit(exitval_tracer); } printf("Wait for the tracer to attach to the tracee\n"); PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); printf("Resume the tracee and let it exit\n"); PARENT_TO_CHILD("exit tracee", parent_tracee, msg); printf("Detect that tracee is zombie\n"); await_zombie(tracee); printf("Assert that there is no status about tracee %d - " "Tracer must detect zombie first - calling %s()\n", tracee, TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS( wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); printf("Tell the tracer child should have exited\n"); PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); printf("Wait for tracer to finish its job and exit - calling %s()\n", TWAIT_FNAME); printf("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); printf("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_tracer); msg_close(&parent_tracee); } #endif #if defined(TWAIT_HAVE_PID) ATF_TC(attach2); ATF_TC_HEAD(attach2, tc) { atf_tc_set_md_var(tc, "descr", "Assert that any tracer sees process termination before its " "parent"); } ATF_TC_BODY(attach2, 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 printf("Spawn tracee\n"); ATF_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); } printf("Spawn debugger\n"); ATF_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); printf("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); printf("Before exiting of the tracer process\n"); _exit(exitval_tracer2); } printf("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); printf("Wait for the non-exited tracee process with %s()\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS( wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); printf("Wait for the tracer to attach to the tracee\n"); PARENT_FROM_CHILD("Message 1", parent_tracer, msg); printf("Resume the tracee and let it exit\n"); PARENT_TO_CHILD("Message 1", parent_tracee, msg); printf("Detect that tracee is zombie\n"); await_zombie(tracee); printf("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); printf("Resume the tracer and let it detect exited tracee\n"); PARENT_TO_CHILD("Message 2", parent_tracer, msg); printf("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_tracer); msg_close(&parent_tracee); } #endif ATF_TC(attach3); ATF_TC_HEAD(attach3, tc) { atf_tc_set_md_var(tc, "descr", "Assert that tracer parent can PT_ATTACH to its child"); } ATF_TC_BODY(attach3, tc) { struct msg_fds parent_tracee; const int exitval_tracee = 5; pid_t tracee, wpid; uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Spawn tracee\n"); ATF_REQUIRE(msg_open(&parent_tracee) == 0); tracee = atf_utils_fork(); if (tracee == 0) { CHILD_FROM_PARENT("Message 1", parent_tracee, msg); printf("Parent should now attach to tracee\n"); CHILD_FROM_PARENT("Message 2", parent_tracee, msg); /* Wait for message from the parent */ _exit(exitval_tracee); } PARENT_TO_CHILD("Message 1", parent_tracee, msg); printf("Before calling PT_ATTACH for tracee %d\n", tracee); ATF_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); printf("Wait for the stopped tracee process with %s()\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS( wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); validate_status_stopped(status, SIGSTOP); printf("Resume tracee with PT_CONTINUE\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); printf("Let the tracee exit now\n"); PARENT_TO_CHILD("Message 2", parent_tracee, msg); printf("Wait for tracee to exit with %s()\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS( wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); validate_status_exited(status, exitval_tracee); printf("Before calling %s() for tracee\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(tracee, &status, 0)); msg_close(&parent_tracee); } ATF_TC(attach4); ATF_TC_HEAD(attach4, tc) { atf_tc_set_md_var(tc, "descr", "Assert that tracer child can PT_ATTACH to its parent"); } ATF_TC_BODY(attach4, tc) { struct msg_fds parent_tracee; const int exitval_tracer = 5; pid_t tracer, wpid; uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Spawn tracer\n"); ATF_REQUIRE(msg_open(&parent_tracee) == 0); tracer = atf_utils_fork(); if (tracer == 0) { /* Wait for message from the parent */ CHILD_FROM_PARENT("Message 1", parent_tracee, msg); printf("Attach to parent PID %d with PT_ATTACH from child\n", getppid()); FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); printf("Wait for the stopped parent process with %s()\n", TWAIT_FNAME); FORKEE_REQUIRE_SUCCESS( wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); forkee_status_stopped(status, SIGSTOP); printf("Resume parent with PT_DETACH\n"); FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) != -1); /* Tell parent we are ready */ CHILD_TO_PARENT("Message 1", parent_tracee, msg); _exit(exitval_tracer); } printf("Wait for the tracer to become ready\n"); PARENT_TO_CHILD("Message 1", parent_tracee, msg); printf("Allow the tracer to exit now\n"); PARENT_FROM_CHILD("Message 1", parent_tracee, msg); printf("Wait for tracer to exit with %s()\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS( wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); validate_status_exited(status, exitval_tracer); printf("Before calling %s() for tracer\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(tracer, &status, 0)); 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) { struct msg_fds parent_tracer, parent_tracee; 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 printf("Spawn tracee\n"); ATF_REQUIRE(msg_open(&parent_tracer) == 0); ATF_REQUIRE(msg_open(&parent_tracee) == 0); tracee = atf_utils_fork(); if (tracee == 0) { parent = getppid(); /* Emit message to the parent */ CHILD_TO_PARENT("tracee ready", parent_tracee, msg); CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); FORKEE_ASSERT_EQ(parent, getppid()); _exit(exitval_tracee); } printf("Wait for child to record its parent identifier (pid)\n"); PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); printf("Spawn debugger\n"); tracer = atf_utils_fork(); if (tracer == 0) { /* No IPC to communicate with the child */ printf("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); printf("Before exiting of the tracer process\n"); _exit(exitval_tracer); } printf("Wait for the tracer to attach to the tracee\n"); PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); printf("Resume the tracee and let it exit\n"); PARENT_TO_CHILD("exit tracee", parent_tracee, msg); printf("Detect that tracee is zombie\n"); await_zombie(tracee); printf("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); printf("Tell the tracer child should have exited\n"); PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); printf("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); printf("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_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; printf("Spawn tracee\n"); ATF_REQUIRE(msg_open(&parent_tracee) == 0); ATF_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); } printf("Wait for child to record its parent identifier (pid)\n"); PARENT_FROM_CHILD("Message 1", parent_tracee, msg); printf("Spawn debugger\n"); tracer = atf_utils_fork(); if (tracer == 0) { /* No IPC to communicate with the child */ printf("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); printf("Before exiting of the tracer process\n"); _exit(exitval_tracer); } printf("Wait for the tracer to attach to the tracee\n"); PARENT_FROM_CHILD("Message 1", parent_tracer, msg); printf("Resume the tracee and let it exit\n"); PARENT_TO_CHILD("Message 1", parent_tracee, msg); printf("Detect that tracee is zombie\n"); await_zombie(tracee); printf("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); printf("Resume the tracer and let it detect exited tracee\n"); PARENT_TO_CHILD("Message 2", parent_tracer, msg); printf("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); printf("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)"); } 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; #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 ... */ ATF_REQUIRE((rv = stat(fname, &st)) == 0 || (errno == ENOENT)); if (rv != 0) { atf_tc_skip("/proc/curproc/status not found"); } printf("Spawn tracee\n"); ATF_REQUIRE(msg_open(&parent_tracee) == 0); ATF_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); } printf("Wait for child to record its parent identifier (pid)\n"); PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); printf("Spawn debugger\n"); tracer = atf_utils_fork(); if (tracer == 0) { printf("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); printf("Before exiting of the tracer process\n"); _exit(exitval_tracer); } printf("Wait for the tracer to attach to the tracee\n"); PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); printf("Resume the tracee and let it exit\n"); PARENT_TO_CHILD("tracee exit", parent_tracee, msg); printf("Detect that tracee is zombie\n"); await_zombie(tracee); printf("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); printf("Resume the tracer and let it detect exited tracee\n"); PARENT_TO_CHILD("Message 2", parent_tracer, msg); printf("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); printf("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) { atf_tc_set_md_var(tc, "descr", "Verify that empty EVENT_MASK is preserved"); } ATF_TC_BODY(eventmask1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_event_t set_event, get_event; const int len = sizeof(ptrace_event_t); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); set_event.pe_set_event = 0; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(eventmask2); ATF_TC_HEAD(eventmask2, tc) { atf_tc_set_md_var(tc, "descr", "Verify that PTRACE_FORK in EVENT_MASK is preserved"); } ATF_TC_BODY(eventmask2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_event_t set_event, get_event; const int len = sizeof(ptrace_event_t); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); set_event.pe_set_event = PTRACE_FORK; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(eventmask3); ATF_TC_HEAD(eventmask3, tc) { atf_tc_set_md_var(tc, "descr", "Verify that PTRACE_VFORK in EVENT_MASK is preserved"); } ATF_TC_BODY(eventmask3, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_event_t set_event, get_event; const int len = sizeof(ptrace_event_t); atf_tc_expect_fail("PR kern/51630"); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); set_event.pe_set_event = PTRACE_VFORK; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(eventmask4); ATF_TC_HEAD(eventmask4, tc) { atf_tc_set_md_var(tc, "descr", "Verify that PTRACE_VFORK_DONE in EVENT_MASK is preserved"); } ATF_TC_BODY(eventmask4, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_event_t set_event, get_event; const int len = sizeof(ptrace_event_t); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); set_event.pe_set_event = PTRACE_VFORK_DONE; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } +ATF_TC(eventmask5); +ATF_TC_HEAD(eventmask5, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that PTRACE_LWP_CREATE in EVENT_MASK is preserved"); +} + +ATF_TC_BODY(eventmask5, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + ptrace_event_t set_event, get_event; + const int len = sizeof(ptrace_event_t); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + set_event.pe_set_event = PTRACE_LWP_CREATE; + ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); + ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); + ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(eventmask6); +ATF_TC_HEAD(eventmask6, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that PTRACE_LWP_EXIT in EVENT_MASK is preserved"); +} + +ATF_TC_BODY(eventmask6, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + ptrace_event_t set_event, get_event; + const int len = sizeof(ptrace_event_t); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + set_event.pe_set_event = PTRACE_LWP_EXIT; + ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); + ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); + ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + #if defined(TWAIT_HAVE_PID) ATF_TC(fork1); ATF_TC_HEAD(fork1, tc) { atf_tc_set_md_var(tc, "descr", "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK " "set to PTRACE_FORK"); } ATF_TC_BODY(fork1, tc) { const int exitval = 5; const int exitval2 = 15; const int sigval = SIGSTOP; pid_t child, child2, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_state_t state; const int slen = sizeof(state); ptrace_event_t event; const int elen = sizeof(event); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT((child2 = fork()) != 1); if (child2 == 0) _exit(exitval2); FORKEE_REQUIRE_SUCCESS (wpid = TWAIT_GENERIC(child2, &status, 0), child2); forkee_status_exited(status, exitval2); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child); event.pe_set_event = PTRACE_FORK; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child %d\n", TWAIT_FNAME, child); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGTRAP); ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK); child2 = state.pe_other_pid; printf("Reported PTRACE_FORK event with forkee %d\n", child2); printf("Before calling %s() for the forkee %d of the child %d\n", TWAIT_FNAME, child2, child); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); validate_status_stopped(status, SIGTRAP); ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK); ATF_REQUIRE_EQ(state.pe_other_pid, child); printf("Before resuming the forkee process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the forkee - expected exited\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); validate_status_exited(status, exitval2); printf("Before calling %s() for the forkee - expected no process\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); printf("Before calling %s() for the child - expected stopped " "SIGCHLD\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGCHLD); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected exited\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child - expected no process\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif ATF_TC(fork2); ATF_TC_HEAD(fork2, tc) { atf_tc_set_md_var(tc, "descr", "Verify that fork(2) is not intercepted by ptrace(2) with empty " "EVENT_MASK"); } ATF_TC_BODY(fork2, tc) { const int exitval = 5; const int exitval2 = 15; const int sigval = SIGSTOP; pid_t child, child2, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_event_t event; const int elen = sizeof(event); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT((child2 = fork()) != 1); if (child2 == 0) _exit(exitval2); FORKEE_REQUIRE_SUCCESS (wpid = TWAIT_GENERIC(child2, &status, 0), child2); forkee_status_exited(status, exitval2); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Set empty EVENT_MASK for the child %d\n", child); event.pe_set_event = 0; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected stopped " "SIGCHLD\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGCHLD); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected exited\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child - expected no process\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #if defined(TWAIT_HAVE_PID) ATF_TC(vfork1); ATF_TC_HEAD(vfork1, tc) { atf_tc_set_md_var(tc, "descr", "Verify that vfork(2) is intercepted by ptrace(2) with EVENT_MASK " "set to PTRACE_VFORK"); } ATF_TC_BODY(vfork1, tc) { const int exitval = 5; const int exitval2 = 15; const int sigval = SIGSTOP; pid_t child, child2, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_state_t state; const int slen = sizeof(state); ptrace_event_t event; const int elen = sizeof(event); atf_tc_expect_fail("PR kern/51630"); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT((child2 = vfork()) != 1); if (child2 == 0) _exit(exitval2); FORKEE_REQUIRE_SUCCESS (wpid = TWAIT_GENERIC(child2, &status, 0), child2); forkee_status_exited(status, exitval2); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child); event.pe_set_event = PTRACE_VFORK; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child %d\n", TWAIT_FNAME, child); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGTRAP); ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK); child2 = state.pe_other_pid; printf("Reported PTRACE_VFORK event with forkee %d\n", child2); printf("Before calling %s() for the forkee %d of the child %d\n", TWAIT_FNAME, child2, child); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); validate_status_stopped(status, SIGTRAP); ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK); ATF_REQUIRE_EQ(state.pe_other_pid, child); printf("Before resuming the forkee process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the forkee - expected exited\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); validate_status_exited(status, exitval2); printf("Before calling %s() for the forkee - expected no process\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); printf("Before calling %s() for the child - expected stopped " "SIGCHLD\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGCHLD); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected exited\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child - expected no process\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif ATF_TC(vfork2); ATF_TC_HEAD(vfork2, tc) { atf_tc_set_md_var(tc, "descr", "Verify that vfork(2) is not intercepted by ptrace(2) with empty " "EVENT_MASK"); } ATF_TC_BODY(vfork2, tc) { const int exitval = 5; const int exitval2 = 15; const int sigval = SIGSTOP; pid_t child, child2, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_event_t event; const int elen = sizeof(event); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT((child2 = vfork()) != 1); if (child2 == 0) _exit(exitval2); FORKEE_REQUIRE_SUCCESS (wpid = TWAIT_GENERIC(child2, &status, 0), child2); forkee_status_exited(status, exitval2); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Set empty EVENT_MASK for the child %d\n", child); event.pe_set_event = 0; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected stopped " "SIGCHLD\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGCHLD); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected exited\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child - expected no process\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(vforkdone1); ATF_TC_HEAD(vforkdone1, tc) { atf_tc_set_md_var(tc, "descr", "Verify that vfork(2) is intercepted by ptrace(2) with EVENT_MASK " "set to PTRACE_VFORK_DONE"); } ATF_TC_BODY(vforkdone1, tc) { const int exitval = 5; const int exitval2 = 15; const int sigval = SIGSTOP; pid_t child, child2, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_state_t state; const int slen = sizeof(state); ptrace_event_t event; const int elen = sizeof(event); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT((child2 = vfork()) != 1); if (child2 == 0) _exit(exitval2); FORKEE_REQUIRE_SUCCESS (wpid = TWAIT_GENERIC(child2, &status, 0), child2); forkee_status_exited(status, exitval2); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child); event.pe_set_event = PTRACE_VFORK_DONE; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child %d\n", TWAIT_FNAME, child); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGTRAP); ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); child2 = state.pe_other_pid; printf("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected stopped " "SIGCHLD\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGCHLD); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected exited\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child - expected no process\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(vforkdone2); ATF_TC_HEAD(vforkdone2, tc) { atf_tc_set_md_var(tc, "descr", "Verify that vfork(2) is intercepted by ptrace(2) with EVENT_MASK " "set to PTRACE_FORK | PTRACE_VFORK_DONE"); } ATF_TC_BODY(vforkdone2, tc) { const int exitval = 5; const int exitval2 = 15; const int sigval = SIGSTOP; pid_t child, child2, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_state_t state; const int slen = sizeof(state); ptrace_event_t event; const int elen = sizeof(event); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT((child2 = vfork()) != 1); if (child2 == 0) _exit(exitval2); FORKEE_REQUIRE_SUCCESS (wpid = TWAIT_GENERIC(child2, &status, 0), child2); forkee_status_exited(status, exitval2); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child); event.pe_set_event = PTRACE_FORK | PTRACE_VFORK_DONE; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child %d\n", TWAIT_FNAME, child); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGTRAP); ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); child2 = state.pe_other_pid; printf("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected stopped " "SIGCHLD\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGCHLD); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected exited\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child - expected no process\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_read_d1); ATF_TC_HEAD(io_read_d1, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_READ_D and len = sizeof(uint8_t)"); } ATF_TC_BODY(io_read_d1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint8_t lookup_me = 0; const uint8_t magic = 0xab; struct ptrace_io_desc io = { .piod_op = PIOD_READ_D, .piod_offs = &lookup_me, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me = magic; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me, magic, "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_read_d2); ATF_TC_HEAD(io_read_d2, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_READ_D and len = sizeof(uint16_t)"); } ATF_TC_BODY(io_read_d2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint16_t lookup_me = 0; const uint16_t magic = 0x1234; struct ptrace_io_desc io = { .piod_op = PIOD_READ_D, .piod_offs = &lookup_me, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me = magic; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me, magic, "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_read_d3); ATF_TC_HEAD(io_read_d3, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_READ_D and len = sizeof(uint32_t)"); } ATF_TC_BODY(io_read_d3, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint32_t lookup_me = 0; const uint32_t magic = 0x1234abcd; struct ptrace_io_desc io = { .piod_op = PIOD_READ_D, .piod_offs = &lookup_me, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me = magic; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me, magic, "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_read_d4); ATF_TC_HEAD(io_read_d4, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_READ_D and len = sizeof(uint64_t)"); } ATF_TC_BODY(io_read_d4, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint64_t lookup_me = 0; const uint64_t magic = 0x1234abcd9876dcfa; struct ptrace_io_desc io = { .piod_op = PIOD_READ_D, .piod_offs = &lookup_me, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me = magic; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me, magic, "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_write_d1); ATF_TC_HEAD(io_write_d1, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint8_t)"); } ATF_TC_BODY(io_write_d1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint8_t lookup_me = 0; const uint8_t magic = 0xab; struct ptrace_io_desc io = { .piod_op = PIOD_WRITE_D, .piod_offs = &lookup_me, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me, magic); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); lookup_me = magic; printf("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_write_d2); ATF_TC_HEAD(io_write_d2, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint16_t)"); } ATF_TC_BODY(io_write_d2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint16_t lookup_me = 0; const uint16_t magic = 0xab12; struct ptrace_io_desc io = { .piod_op = PIOD_WRITE_D, .piod_offs = &lookup_me, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me, magic); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); lookup_me = magic; printf("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_write_d3); ATF_TC_HEAD(io_write_d3, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint32_t)"); } ATF_TC_BODY(io_write_d3, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint32_t lookup_me = 0; const uint32_t magic = 0xab127643; struct ptrace_io_desc io = { .piod_op = PIOD_WRITE_D, .piod_offs = &lookup_me, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me, magic); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); lookup_me = magic; printf("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_write_d4); ATF_TC_HEAD(io_write_d4, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint64_t)"); } ATF_TC_BODY(io_write_d4, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint64_t lookup_me = 0; const uint64_t magic = 0xab12764376490123; struct ptrace_io_desc io = { .piod_op = PIOD_WRITE_D, .piod_offs = &lookup_me, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me, magic); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); lookup_me = magic; printf("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(read_d1); ATF_TC_HEAD(read_d1, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_READ_D called once"); } ATF_TC_BODY(read_d1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me = 0; const int magic = (int)random(); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me = magic; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me = ptrace(PT_READ_D, child, &lookup_me, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me, magic, "got value %#x != expected %#x", lookup_me, magic); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(read_d2); ATF_TC_HEAD(read_d2, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_READ_D called twice"); } ATF_TC_BODY(read_d2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me1 = 0; int lookup_me2 = 0; const int magic1 = (int)random(); const int magic2 = (int)random(); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me1 = magic1; lookup_me2 = magic2; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me1, magic1, "got value %#x != expected %#x", lookup_me1, magic1); printf("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me2, magic2, "got value %#x != expected %#x", lookup_me2, magic2); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(read_d3); ATF_TC_HEAD(read_d3, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_READ_D called three times"); } ATF_TC_BODY(read_d3, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me1 = 0; int lookup_me2 = 0; int lookup_me3 = 0; const int magic1 = (int)random(); const int magic2 = (int)random(); const int magic3 = (int)random(); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me1 = magic1; lookup_me2 = magic2; lookup_me3 = magic3; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me1, magic1, "got value %#x != expected %#x", lookup_me1, magic1); printf("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me2, magic2, "got value %#x != expected %#x", lookup_me2, magic2); printf("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me3, magic3, "got value %#x != expected %#x", lookup_me3, magic3); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(read_d4); ATF_TC_HEAD(read_d4, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_READ_D called four times"); } ATF_TC_BODY(read_d4, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me1 = 0; int lookup_me2 = 0; int lookup_me3 = 0; int lookup_me4 = 0; const int magic1 = (int)random(); const int magic2 = (int)random(); const int magic3 = (int)random(); const int magic4 = (int)random(); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me1 = magic1; lookup_me2 = magic2; lookup_me3 = magic3; lookup_me4 = magic4; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me1, magic1, "got value %#x != expected %#x", lookup_me1, magic1); printf("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me2, magic2, "got value %#x != expected %#x", lookup_me2, magic2); printf("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me3, magic3, "got value %#x != expected %#x", lookup_me3, magic3); printf("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me4 = ptrace(PT_READ_D, child, &lookup_me4, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me4, magic4, "got value %#x != expected %#x", lookup_me4, magic4); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(write_d1); ATF_TC_HEAD(write_d1, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_WRITE_D called once"); } ATF_TC_BODY(write_d1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me = 0; const int magic = (int)random(); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me, magic); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me, magic) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(write_d2); ATF_TC_HEAD(write_d2, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_WRITE_D called twice"); } ATF_TC_BODY(write_d2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me1 = 0; int lookup_me2 = 0; const int magic1 = (int)random(); const int magic2 = (int)random(); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me1, magic1); FORKEE_ASSERT_EQ(lookup_me2, magic2); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1); printf("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(write_d3); ATF_TC_HEAD(write_d3, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_WRITE_D called three times"); } ATF_TC_BODY(write_d3, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me1 = 0; int lookup_me2 = 0; int lookup_me3 = 0; const int magic1 = (int)random(); const int magic2 = (int)random(); const int magic3 = (int)random(); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me1, magic1); FORKEE_ASSERT_EQ(lookup_me2, magic2); FORKEE_ASSERT_EQ(lookup_me3, magic3); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1); printf("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1); printf("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(write_d4); ATF_TC_HEAD(write_d4, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_WRITE_D called four times"); } ATF_TC_BODY(write_d4, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me1 = 0; int lookup_me2 = 0; int lookup_me3 = 0; int lookup_me4 = 0; const int magic1 = (int)random(); const int magic2 = (int)random(); const int magic3 = (int)random(); const int magic4 = (int)random(); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me1, magic1); FORKEE_ASSERT_EQ(lookup_me2, magic2); FORKEE_ASSERT_EQ(lookup_me3, magic3); FORKEE_ASSERT_EQ(lookup_me4, magic4); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1); printf("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1); printf("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1); printf("Write new lookup_me4 to tracee (PID=%d) from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me4, magic4) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_read_d_write_d_handshake1); ATF_TC_HEAD(io_read_d_write_d_handshake1, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_READ_D and PIOD_WRITE_D handshake"); } ATF_TC_BODY(io_read_d_write_d_handshake1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint8_t lookup_me_fromtracee = 0; const uint8_t magic_fromtracee = (uint8_t)random(); uint8_t lookup_me_totracee = 0; const uint8_t magic_totracee = (uint8_t)random(); struct ptrace_io_desc io_fromtracee = { .piod_op = PIOD_READ_D, .piod_offs = &lookup_me_fromtracee, .piod_addr = &lookup_me_fromtracee, .piod_len = sizeof(lookup_me_fromtracee) }; struct ptrace_io_desc io_totracee = { .piod_op = PIOD_WRITE_D, .piod_offs = &lookup_me_totracee, .piod_addr = &lookup_me_totracee, .piod_len = sizeof(lookup_me_totracee) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me_fromtracee = magic_fromtracee; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee, "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee, magic_fromtracee); lookup_me_totracee = magic_totracee; printf("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee, "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee, magic_totracee); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_read_d_write_d_handshake2); ATF_TC_HEAD(io_read_d_write_d_handshake2, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_WRITE_D and PIOD_READ_D handshake"); } ATF_TC_BODY(io_read_d_write_d_handshake2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint8_t lookup_me_fromtracee = 0; const uint8_t magic_fromtracee = (uint8_t)random(); uint8_t lookup_me_totracee = 0; const uint8_t magic_totracee = (uint8_t)random(); struct ptrace_io_desc io_fromtracee = { .piod_op = PIOD_READ_D, .piod_offs = &lookup_me_fromtracee, .piod_addr = &lookup_me_fromtracee, .piod_len = sizeof(lookup_me_fromtracee) }; struct ptrace_io_desc io_totracee = { .piod_op = PIOD_WRITE_D, .piod_offs = &lookup_me_totracee, .piod_addr = &lookup_me_totracee, .piod_len = sizeof(lookup_me_totracee) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me_fromtracee = magic_fromtracee; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); lookup_me_totracee = magic_totracee; printf("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee, "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee, magic_totracee); printf("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee, "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee, magic_fromtracee); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(read_d_write_d_handshake1); ATF_TC_HEAD(read_d_write_d_handshake1, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_READ_D with PT_WRITE_D handshake"); } ATF_TC_BODY(read_d_write_d_handshake1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me_fromtracee = 0; const int magic_fromtracee = (int)random(); int lookup_me_totracee = 0; const int magic_totracee = (int)random(); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me_fromtracee = magic_fromtracee; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me_fromtracee = ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee, "got value %#x != expected %#x", lookup_me_fromtracee, magic_fromtracee); printf("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(read_d_write_d_handshake2); ATF_TC_HEAD(read_d_write_d_handshake2, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_WRITE_D with PT_READ_D handshake"); } ATF_TC_BODY(read_d_write_d_handshake2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me_fromtracee = 0; const int magic_fromtracee = (int)random(); int lookup_me_totracee = 0; const int magic_totracee = (int)random(); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); lookup_me_fromtracee = magic_fromtracee; printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee) != -1); printf("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me_fromtracee = ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee, "got value %#x != expected %#x", lookup_me_fromtracee, magic_fromtracee); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } /* These dummy functions are used to be copied with ptrace(2) calls */ static int __used dummy_fn1(int a, int b, int c, int d) { a *= 1; b += 2; c -= 3; d /= 4; return a + b * c - d; } static int __used dummy_fn2(int a, int b, int c, int d) { a *= 4; b += 3; c -= 2; d /= 1; return a + b * c - d; } static int __used dummy_fn3(int a, int b, int c, int d) { a *= 10; b += 20; c -= 30; d /= 40; return a + b * c - d; } static int __used dummy_fn4(int a, int b, int c, int d) { a *= 40; b += 30; c -= 20; d /= 10; return a + b * c - d; } ATF_TC(io_read_i1); ATF_TC_HEAD(io_read_i1, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_READ_I and len = sizeof(uint8_t)"); } ATF_TC_BODY(io_read_i1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint8_t lookup_me = 0; uint8_t magic; memcpy(&magic, dummy_fn1, sizeof(magic)); struct ptrace_io_desc io = { .piod_op = PIOD_READ_I, .piod_offs = dummy_fn1, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me, magic, "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_read_i2); ATF_TC_HEAD(io_read_i2, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_READ_I and len = sizeof(uint16_t)"); } ATF_TC_BODY(io_read_i2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint16_t lookup_me = 0; uint16_t magic; memcpy(&magic, dummy_fn1, sizeof(magic)); struct ptrace_io_desc io = { .piod_op = PIOD_READ_I, .piod_offs = dummy_fn1, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me, magic, "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_read_i3); ATF_TC_HEAD(io_read_i3, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_READ_I and len = sizeof(uint32_t)"); } ATF_TC_BODY(io_read_i3, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint32_t lookup_me = 0; uint32_t magic; memcpy(&magic, dummy_fn1, sizeof(magic)); struct ptrace_io_desc io = { .piod_op = PIOD_READ_I, .piod_offs = dummy_fn1, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me, magic, "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(io_read_i4); ATF_TC_HEAD(io_read_i4, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_IO with PIOD_READ_I and len = sizeof(uint64_t)"); } ATF_TC_BODY(io_read_i4, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; uint64_t lookup_me = 0; uint64_t magic; memcpy(&magic, dummy_fn1, sizeof(magic)); struct ptrace_io_desc io = { .piod_op = PIOD_READ_I, .piod_offs = dummy_fn1, .piod_addr = &lookup_me, .piod_len = sizeof(lookup_me) }; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); ATF_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); ATF_REQUIRE_EQ_MSG(lookup_me, magic, "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(read_i1); ATF_TC_HEAD(read_i1, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_READ_I called once"); } ATF_TC_BODY(read_i1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me = 0; int magic; memcpy(&magic, dummy_fn1, sizeof(magic)); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me = ptrace(PT_READ_I, child, dummy_fn1, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me, magic, "got value %#x != expected %#x", lookup_me, magic); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(read_i2); ATF_TC_HEAD(read_i2, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_READ_I called twice"); } ATF_TC_BODY(read_i2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me1 = 0; int lookup_me2 = 0; int magic1; int magic2; memcpy(&magic1, dummy_fn1, sizeof(magic1)); memcpy(&magic2, dummy_fn2, sizeof(magic2)); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me1, magic1, "got value %#x != expected %#x", lookup_me1, magic1); printf("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me2, magic2, "got value %#x != expected %#x", lookup_me2, magic2); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(read_i3); ATF_TC_HEAD(read_i3, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_READ_I called three times"); } ATF_TC_BODY(read_i3, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me1 = 0; int lookup_me2 = 0; int lookup_me3 = 0; int magic1; int magic2; int magic3; memcpy(&magic1, dummy_fn1, sizeof(magic1)); memcpy(&magic2, dummy_fn2, sizeof(magic2)); memcpy(&magic3, dummy_fn3, sizeof(magic3)); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me1, magic1, "got value %#x != expected %#x", lookup_me1, magic1); printf("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me2, magic2, "got value %#x != expected %#x", lookup_me2, magic2); printf("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me3, magic3, "got value %#x != expected %#x", lookup_me3, magic3); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(read_i4); ATF_TC_HEAD(read_i4, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_READ_I called four times"); } ATF_TC_BODY(read_i4, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int lookup_me1 = 0; int lookup_me2 = 0; int lookup_me3 = 0; int lookup_me4 = 0; int magic1; int magic2; int magic3; int magic4; memcpy(&magic1, dummy_fn1, sizeof(magic1)); memcpy(&magic2, dummy_fn2, sizeof(magic2)); memcpy(&magic3, dummy_fn3, sizeof(magic3)); memcpy(&magic4, dummy_fn4, sizeof(magic4)); #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me1, magic1, "got value %#x != expected %#x", lookup_me1, magic1); printf("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me2, magic2, "got value %#x != expected %#x", lookup_me2, magic2); printf("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me3, magic3, "got value %#x != expected %#x", lookup_me3, magic3); printf("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n", child, getpid()); errno = 0; lookup_me4 = ptrace(PT_READ_I, child, dummy_fn4, 0); ATF_REQUIRE_EQ(errno, 0); ATF_REQUIRE_EQ_MSG(lookup_me4, magic4, "got value %#x != expected %#x", lookup_me4, magic4); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #if defined(HAVE_GPREGS) ATF_TC(regs1); ATF_TC_HEAD(regs1, tc) { atf_tc_set_md_var(tc, "descr", "Verify plain PT_GETREGS call without further steps"); } ATF_TC_BODY(regs1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct reg r; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Call GETREGS for the child process\n"); ATF_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(HAVE_GPREGS) ATF_TC(regs2); ATF_TC_HEAD(regs2, tc) { atf_tc_set_md_var(tc, "descr", "Verify plain PT_GETREGS call and retrieve PC"); } ATF_TC_BODY(regs2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct reg r; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Call GETREGS for the child process\n"); ATF_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1); printf("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r)); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(HAVE_GPREGS) ATF_TC(regs3); ATF_TC_HEAD(regs3, tc) { atf_tc_set_md_var(tc, "descr", "Verify plain PT_GETREGS call and retrieve SP"); } ATF_TC_BODY(regs3, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct reg r; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Call GETREGS for the child process\n"); ATF_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1); printf("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r)); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(HAVE_GPREGS) ATF_TC(regs4); ATF_TC_HEAD(regs4, tc) { atf_tc_set_md_var(tc, "descr", "Verify plain PT_GETREGS call and retrieve INTRV"); } ATF_TC_BODY(regs4, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct reg r; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Call GETREGS for the child process\n"); ATF_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1); printf("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r)); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(HAVE_GPREGS) ATF_TC(regs5); ATF_TC_HEAD(regs5, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_GETREGS and PT_SETREGS calls without changing regs"); } ATF_TC_BODY(regs5, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct reg r; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Call GETREGS for the child process\n"); ATF_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1); printf("Call SETREGS for the child process (without changed regs)\n"); ATF_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(HAVE_FPREGS) ATF_TC(fpregs1); ATF_TC_HEAD(fpregs1, tc) { atf_tc_set_md_var(tc, "descr", "Verify plain PT_GETFPREGS call without further steps"); } ATF_TC_BODY(fpregs1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct fpreg r; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Call GETFPREGS for the child process\n"); ATF_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(HAVE_FPREGS) ATF_TC(fpregs2); ATF_TC_HEAD(fpregs2, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing " "regs"); } ATF_TC_BODY(fpregs2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct fpreg r; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Call GETFPREGS for the child process\n"); ATF_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1); printf("Call SETFPREGS for the child (without changed regs)\n"); ATF_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(PT_STEP) ATF_TC(step1); ATF_TC_HEAD(step1, tc) { atf_tc_set_md_var(tc, "descr", "Verify single PT_STEP call"); } ATF_TC_BODY(step1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif int happy; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); happy = check_happy(100); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(happy, check_happy(100)); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before resuming the child process where it left off and " "without signal to be sent (use PT_STEP)\n"); ATF_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGTRAP); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(PT_STEP) ATF_TC(step2); ATF_TC_HEAD(step2, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_STEP called twice"); } ATF_TC_BODY(step2, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif int happy; int N = 2; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); happy = check_happy(999); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(happy, check_happy(999)); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); while (N --> 0) { printf("Before resuming the child process where it left off " "and without signal to be sent (use PT_STEP)\n"); ATF_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGTRAP); } printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(PT_STEP) ATF_TC(step3); ATF_TC_HEAD(step3, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_STEP called three times"); } ATF_TC_BODY(step3, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif int happy; int N = 3; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); happy = check_happy(999); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(happy, check_happy(999)); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); while (N --> 0) { printf("Before resuming the child process where it left off " "and without signal to be sent (use PT_STEP)\n"); ATF_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGTRAP); } printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(PT_STEP) ATF_TC(step4); ATF_TC_HEAD(step4, tc) { atf_tc_set_md_var(tc, "descr", "Verify PT_STEP called four times"); } ATF_TC_BODY(step4, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif int happy; int N = 4; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); happy = check_happy(999); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(happy, check_happy(999)); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); while (N --> 0) { printf("Before resuming the child process where it left off " "and without signal to be sent (use PT_STEP)\n"); ATF_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGTRAP); } printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif ATF_TC(kill1); ATF_TC_HEAD(kill1, tc) { atf_tc_set_md_var(tc, "descr", "Verify that PT_CONTINUE with SIGKILL terminates child"); } ATF_TC_BODY(kill1, tc) { const int sigval = SIGSTOP, sigsent = SIGKILL; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); /* NOTREACHED */ FORKEE_ASSERTX(0 && "Child should be terminated by a signal from its parent"); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_signaled(status, sigsent, 0); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(kill2); ATF_TC_HEAD(kill2, tc) { atf_tc_set_md_var(tc, "descr", "Verify that PT_KILL terminates child"); } ATF_TC_BODY(kill2, tc) { const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); /* NOTREACHED */ FORKEE_ASSERTX(0 && "Child should be terminated by a signal from its parent"); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_signaled(status, SIGKILL, 0); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(lwpinfo1); ATF_TC_HEAD(lwpinfo1, tc) { atf_tc_set_md_var(tc, "descr", "Verify basic LWPINFO call for single thread (PT_TRACE_ME)"); } ATF_TC_BODY(lwpinfo1, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct ptrace_lwpinfo info = {0, 0}; printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before calling ptrace(2) with PT_LWPINFO for child\n"); ATF_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1); printf("Assert that there exists a thread\n"); ATF_REQUIRE(info.pl_lwpid > 0); printf("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", info.pl_lwpid); ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL, "Received event %d != expected event %d", info.pl_event, PL_EVENT_SIGNAL); printf("Before calling ptrace(2) with PT_LWPINFO for child\n"); ATF_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1); printf("Assert that there are no more lwp threads in child\n"); ATF_REQUIRE_EQ(info.pl_lwpid, 0); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #if defined(TWAIT_HAVE_PID) ATF_TC(lwpinfo2); ATF_TC_HEAD(lwpinfo2, tc) { atf_tc_set_md_var(tc, "descr", "Verify basic LWPINFO call for single thread (PT_ATTACH from " "tracer)"); } ATF_TC_BODY(lwpinfo2, tc) { struct msg_fds parent_tracee, parent_tracer; const int exitval_tracee = 5; const int exitval_tracer = 10; 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 struct ptrace_lwpinfo info = {0, 0}; printf("Spawn tracee\n"); ATF_REQUIRE(msg_open(&parent_tracee) == 0); ATF_REQUIRE(msg_open(&parent_tracer) == 0); tracee = atf_utils_fork(); if (tracee == 0) { /* Wait for message from the parent */ CHILD_TO_PARENT("tracee ready", parent_tracee, msg); CHILD_FROM_PARENT("tracee exit", parent_tracee, msg); _exit(exitval_tracee); } PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); printf("Spawn debugger\n"); tracer = atf_utils_fork(); if (tracer == 0) { /* No IPC to communicate with the child */ printf("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); printf("Before calling ptrace(2) with PT_LWPINFO for child\n"); FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info)) != -1); printf("Assert that there exists a thread\n"); FORKEE_ASSERTX(info.pl_lwpid > 0); printf("Assert that lwp thread %d received event " "PL_EVENT_SIGNAL\n", info.pl_lwpid); FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL); printf("Before calling ptrace(2) with PT_LWPINFO for child\n"); FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info)) != -1); printf("Assert that there are no more lwp threads in child\n"); FORKEE_ASSERTX(info.pl_lwpid == 0); /* 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 */ CHILD_FROM_PARENT("tracer wait", 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); printf("Before exiting of the tracer process\n"); _exit(exitval_tracer); } printf("Wait for the tracer to attach to the tracee\n"); PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); printf("Resume the tracee and let it exit\n"); PARENT_TO_CHILD("tracee exit", parent_tracee, msg); printf("Detect that tracee is zombie\n"); await_zombie(tracee); printf("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); printf("Resume the tracer and let it detect exited tracee\n"); PARENT_TO_CHILD("tracer wait", parent_tracer, msg); printf("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); printf("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_tracer); msg_close(&parent_tracee); } #endif ATF_TC(siginfo1); ATF_TC_HEAD(siginfo1, tc) { atf_tc_set_md_var(tc, "descr", "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee"); } ATF_TC_BODY(siginfo1, tc) { const int exitval = 5; const int sigval = SIGTRAP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct ptrace_siginfo info; memset(&info, 0, sizeof(info)); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Signal traced to lwpid=%d\n", info.psi_lwpid); printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", info.psi_siginfo.si_signo, info.psi_siginfo.si_code, info.psi_siginfo.si_errno); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(siginfo2); ATF_TC_HEAD(siginfo2, tc) { atf_tc_set_md_var(tc, "descr", "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without " "modification of SIGINT from tracee"); } static int siginfo2_caught = 0; static void siginfo2_sighandler(int sig) { FORKEE_ASSERT_EQ(sig, SIGINT); ++siginfo2_caught; } ATF_TC_BODY(siginfo2, tc) { const int exitval = 5; const int sigval = SIGINT; pid_t child, wpid; struct sigaction sa; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct ptrace_siginfo info; memset(&info, 0, sizeof(info)); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); sa.sa_handler = siginfo2_sighandler; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(siginfo2_caught, 1); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Signal traced to lwpid=%d\n", info.psi_lwpid); printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", info.psi_siginfo.si_signo, info.psi_siginfo.si_code, info.psi_siginfo.si_errno); printf("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(siginfo3); ATF_TC_HEAD(siginfo3, tc) { atf_tc_set_md_var(tc, "descr", "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with " "setting signal to new value"); } static int siginfo3_caught = 0; static void siginfo3_sigaction(int sig, siginfo_t *info, void *ctx) { FORKEE_ASSERT_EQ(sig, SIGTRAP); FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); ++siginfo3_caught; } ATF_TC_BODY(siginfo3, tc) { const int exitval = 5; const int sigval = SIGINT; const int sigfaked = SIGTRAP; const int sicodefaked = TRAP_BRKPT; pid_t child, wpid; struct sigaction sa; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct ptrace_siginfo info; memset(&info, 0, sizeof(info)); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); sa.sa_sigaction = siginfo3_sigaction; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(siginfo3_caught, 1); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Signal traced to lwpid=%d\n", info.psi_lwpid); printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", info.psi_siginfo.si_signo, info.psi_siginfo.si_code, info.psi_siginfo.si_errno); printf("Before setting new faked signal to signo=%d si_code=%d\n", sigfaked, sicodefaked); info.psi_siginfo.si_signo = sigfaked; info.psi_siginfo.si_code = sicodefaked; printf("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Before checking siginfo_t\n"); ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } ATF_TC(siginfo4); ATF_TC_HEAD(siginfo4, tc) { atf_tc_set_md_var(tc, "descr", "Detect SIGTRAP TRAP_EXEC from tracee"); } ATF_TC_BODY(siginfo4, tc) { const int sigval = SIGTRAP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif struct ptrace_siginfo info; memset(&info, 0, sizeof(info)); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before calling execve(2) from child\n"); execlp("/bin/echo", "/bin/echo", NULL); FORKEE_ASSERT(0 && "Not reached"); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Signal traced to lwpid=%d\n", info.psi_lwpid); printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", info.psi_siginfo.si_signo, info.psi_siginfo.si_code, info.psi_siginfo.si_errno); ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #if defined(TWAIT_HAVE_PID) ATF_TC(siginfo5); ATF_TC_HEAD(siginfo5, tc) { atf_tc_set_md_var(tc, "descr", "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK " "set to PTRACE_FORK and reports correct signal information"); } ATF_TC_BODY(siginfo5, tc) { const int exitval = 5; const int exitval2 = 15; const int sigval = SIGSTOP; pid_t child, child2, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif ptrace_state_t state; const int slen = sizeof(state); ptrace_event_t event; const int elen = sizeof(event); struct ptrace_siginfo info; memset(&info, 0, sizeof(info)); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT((child2 = fork()) != 1); if (child2 == 0) _exit(exitval2); FORKEE_REQUIRE_SUCCESS (wpid = TWAIT_GENERIC(child2, &status, 0), child2); forkee_status_exited(status, exitval2); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Before checking siginfo_t\n"); ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); printf("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child); event.pe_set_event = PTRACE_FORK; ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child %d\n", TWAIT_FNAME, child); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGTRAP); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Before checking siginfo_t\n"); ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD); ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK); child2 = state.pe_other_pid; printf("Reported PTRACE_FORK event with forkee %d\n", child2); printf("Before calling %s() for the forkee %d of the child %d\n", TWAIT_FNAME, child2, child); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); validate_status_stopped(status, SIGTRAP); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Before checking siginfo_t\n"); ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD); ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK); ATF_REQUIRE_EQ(state.pe_other_pid, child); printf("Before resuming the forkee process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the forkee - expected exited\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); validate_status_exited(status, exitval2); printf("Before calling %s() for the forkee - expected no process\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); printf("Before calling %s() for the child - expected stopped " "SIGCHLD\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGCHLD); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Before checking siginfo_t\n"); ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD); ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child - expected exited\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child - expected no process\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif #if defined(PT_STEP) ATF_TC(siginfo6); ATF_TC_HEAD(siginfo6, tc) { atf_tc_set_md_var(tc, "descr", "Verify single PT_STEP call with signal information check"); } ATF_TC_BODY(siginfo6, tc) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; #if defined(TWAIT_HAVE_STATUS) int status; #endif int happy; struct ptrace_siginfo info; memset(&info, 0, sizeof(info)); printf("Before forking process PID=%d\n", getpid()); ATF_REQUIRE((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); happy = check_happy(100); printf("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); FORKEE_ASSERT_EQ(happy, check_happy(100)); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, sigval); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Before checking siginfo_t\n"); ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); printf("Before resuming the child process where it left off and " "without signal to be sent (use PT_STEP)\n"); ATF_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_stopped(status, SIGTRAP); printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); printf("Before checking siginfo_t\n"); ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); validate_status_exited(status, exitval); printf("Before calling %s() for the child\n", TWAIT_FNAME); TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } #endif +volatile lwpid_t the_lwp_id = 0; + +static void +lwp_main_func(void *arg) +{ + the_lwp_id = _lwp_self(); + _lwp_exit(); +} + +ATF_TC(lwp_create1); +ATF_TC_HEAD(lwp_create1, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that 1 LWP creation is intercepted by ptrace(2) with " + "EVENT_MASK set to PTRACE_LWP_CREATE"); +} + +ATF_TC_BODY(lwp_create1, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + ptrace_state_t state; + const int slen = sizeof(state); + ptrace_event_t event; + const int elen = sizeof(event); + ucontext_t uc; + lwpid_t lid; + static const size_t ssize = 16*1024; + void *stack; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before allocating memory for stack in child\n"); + FORKEE_ASSERT((stack = malloc(ssize)) != NULL); + + printf("Before making context for new lwp in child\n"); + _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); + + printf("Before creating new in child\n"); + FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); + + printf("Before waiting for lwp %d to exit\n", lid); + FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); + + printf("Before verifying that reported %d and running lid %d " + "are the same\n", lid, the_lwp_id); + FORKEE_ASSERT_EQ(lid, the_lwp_id); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Set empty EVENT_MASK for the child %d\n", child); + event.pe_set_event = PTRACE_LWP_CREATE; + ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child - expected stopped " + "SIGTRAP\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, SIGTRAP); + + ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); + + ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); + + lid = state.pe_lwp; + printf("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child - expected exited\n", + TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child - expected no process\n", + TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(lwp_exit1); +ATF_TC_HEAD(lwp_exit1, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that 1 LWP creation is intercepted by ptrace(2) with " + "EVENT_MASK set to PTRACE_LWP_EXIT"); +} + +ATF_TC_BODY(lwp_exit1, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + ptrace_state_t state; + const int slen = sizeof(state); + ptrace_event_t event; + const int elen = sizeof(event); + ucontext_t uc; + lwpid_t lid; + static const size_t ssize = 16*1024; + void *stack; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before allocating memory for stack in child\n"); + FORKEE_ASSERT((stack = malloc(ssize)) != NULL); + + printf("Before making context for new lwp in child\n"); + _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); + + printf("Before creating new in child\n"); + FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); + + printf("Before waiting for lwp %d to exit\n", lid); + FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); + + printf("Before verifying that reported %d and running lid %d " + "are the same\n", lid, the_lwp_id); + FORKEE_ASSERT_EQ(lid, the_lwp_id); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Set empty EVENT_MASK for the child %d\n", child); + event.pe_set_event = PTRACE_LWP_EXIT; + ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child - expected stopped " + "SIGTRAP\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, SIGTRAP); + + ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); + + ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); + + lid = state.pe_lwp; + printf("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child - expected exited\n", + TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child - expected no process\n", + TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + ATF_TP_ADD_TCS(tp) { setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); ATF_TP_ADD_TC(tp, traceme1); ATF_TP_ADD_TC(tp, traceme2); ATF_TP_ADD_TC(tp, traceme3); ATF_TP_ADD_TC(tp, traceme4); 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(tp, eventmask1); ATF_TP_ADD_TC(tp, eventmask2); ATF_TP_ADD_TC(tp, eventmask3); ATF_TP_ADD_TC(tp, eventmask4); + ATF_TP_ADD_TC(tp, eventmask5); + ATF_TP_ADD_TC(tp, eventmask6); ATF_TP_ADD_TC_HAVE_PID(tp, fork1); ATF_TP_ADD_TC(tp, fork2); ATF_TP_ADD_TC_HAVE_PID(tp, vfork1); ATF_TP_ADD_TC(tp, vfork2); ATF_TP_ADD_TC(tp, vforkdone1); ATF_TP_ADD_TC(tp, vforkdone2); ATF_TP_ADD_TC(tp, io_read_d1); ATF_TP_ADD_TC(tp, io_read_d2); ATF_TP_ADD_TC(tp, io_read_d3); ATF_TP_ADD_TC(tp, io_read_d4); ATF_TP_ADD_TC(tp, io_write_d1); ATF_TP_ADD_TC(tp, io_write_d2); ATF_TP_ADD_TC(tp, io_write_d3); ATF_TP_ADD_TC(tp, io_write_d4); ATF_TP_ADD_TC(tp, read_d1); ATF_TP_ADD_TC(tp, read_d2); ATF_TP_ADD_TC(tp, read_d3); ATF_TP_ADD_TC(tp, read_d4); ATF_TP_ADD_TC(tp, write_d1); ATF_TP_ADD_TC(tp, write_d2); ATF_TP_ADD_TC(tp, write_d3); ATF_TP_ADD_TC(tp, write_d4); ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake1); ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake2); ATF_TP_ADD_TC(tp, read_d_write_d_handshake1); ATF_TP_ADD_TC(tp, read_d_write_d_handshake2); ATF_TP_ADD_TC(tp, io_read_i1); ATF_TP_ADD_TC(tp, io_read_i2); ATF_TP_ADD_TC(tp, io_read_i3); ATF_TP_ADD_TC(tp, io_read_i4); ATF_TP_ADD_TC(tp, read_i1); ATF_TP_ADD_TC(tp, read_i2); ATF_TP_ADD_TC(tp, read_i3); ATF_TP_ADD_TC(tp, read_i4); ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1); ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2); ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3); ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4); ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5); ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1); ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2); ATF_TP_ADD_TC_PT_STEP(tp, step1); ATF_TP_ADD_TC_PT_STEP(tp, step2); ATF_TP_ADD_TC_PT_STEP(tp, step3); ATF_TP_ADD_TC_PT_STEP(tp, step4); ATF_TP_ADD_TC(tp, kill1); ATF_TP_ADD_TC(tp, kill2); ATF_TP_ADD_TC(tp, lwpinfo1); ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2); ATF_TP_ADD_TC(tp, siginfo1); ATF_TP_ADD_TC(tp, siginfo2); ATF_TP_ADD_TC(tp, siginfo3); ATF_TP_ADD_TC(tp, siginfo4); ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5); ATF_TP_ADD_TC_PT_STEP(tp, siginfo6); + + ATF_TP_ADD_TC(tp, lwp_create1); + + ATF_TP_ADD_TC(tp, lwp_exit1); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/lib/libc/c063/t_mkfifoat.c =================================================================== --- vendor/NetBSD/tests/dist/lib/libc/c063/t_mkfifoat.c (revision 312218) +++ vendor/NetBSD/tests/dist/lib/libc/c063/t_mkfifoat.c (revision 312219) @@ -1,125 +1,120 @@ -/* $NetBSD: t_mkfifoat.c,v 1.3 2017/01/10 15:15:09 christos Exp $ */ +/* $NetBSD: t_mkfifoat.c,v 1.4 2017/01/14 20:55:26 christos Exp $ */ /*- * Copyright (c) 2012 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Emmanuel Dreyfus. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_mkfifoat.c,v 1.3 2017/01/10 15:15:09 christos Exp $"); +__RCSID("$NetBSD: t_mkfifoat.c,v 1.4 2017/01/14 20:55:26 christos Exp $"); #include #include #include #include #include #include #include #include #include #include #define DIR "dir" #define FIFO "dir/openat" #define BASEFIFO "openat" #define FIFOERR "dir/openaterr" ATF_TC(mkfifoat_fd); ATF_TC_HEAD(mkfifoat_fd, tc) { atf_tc_set_md_var(tc, "descr", "See that mkfifoat works with fd"); } ATF_TC_BODY(mkfifoat_fd, tc) { int dfd; - int fd; mode_t mode = 0600; ATF_REQUIRE(mkdir(DIR, 0755) == 0); ATF_REQUIRE((dfd = open(DIR, O_RDONLY, 0)) != -1); - ATF_REQUIRE((fd = mkfifoat(dfd, BASEFIFO, mode)) != -1); - ATF_REQUIRE(close(fd) == 0); + ATF_REQUIRE(mkfifoat(dfd, BASEFIFO, mode) != -1); ATF_REQUIRE(access(FIFO, F_OK) == 0); (void)close(dfd); } ATF_TC(mkfifoat_fdcwd); ATF_TC_HEAD(mkfifoat_fdcwd, tc) { atf_tc_set_md_var(tc, "descr", "See that mkfifoat works with fd as AT_FDCWD"); } ATF_TC_BODY(mkfifoat_fdcwd, tc) { - int fd; mode_t mode = 0600; ATF_REQUIRE(mkdir(DIR, 0755) == 0); - ATF_REQUIRE((fd = mkfifoat(AT_FDCWD, FIFO, mode)) != -1); - ATF_REQUIRE(close(fd) == 0); + ATF_REQUIRE(mkfifoat(AT_FDCWD, FIFO, mode) != -1); ATF_REQUIRE(access(FIFO, F_OK) == 0); } ATF_TC(mkfifoat_fdcwderr); ATF_TC_HEAD(mkfifoat_fdcwderr, tc) { atf_tc_set_md_var(tc, "descr", "See that mkfifoat fails with fd as AT_FDCWD and bad path"); } ATF_TC_BODY(mkfifoat_fdcwderr, tc) { - int fd; mode_t mode = 0600; - ATF_REQUIRE((fd = mkfifoat(AT_FDCWD, FIFOERR, mode)) == -1); + ATF_REQUIRE(mkfifoat(AT_FDCWD, FIFOERR, mode) == -1); } ATF_TC(mkfifoat_fderr); ATF_TC_HEAD(mkfifoat_fderr, tc) { atf_tc_set_md_var(tc, "descr", "See that mkfifoat fails with fd as -1"); } ATF_TC_BODY(mkfifoat_fderr, tc) { int fd; mode_t mode = 0600; ATF_REQUIRE(mkdir(DIR, 0755) == 0); ATF_REQUIRE((fd = open(FIFO, O_CREAT|O_RDWR, 0644)) != -1); ATF_REQUIRE(close(fd) == 0); - ATF_REQUIRE((fd = mkfifoat(-1, FIFO, mode)) == -1); + ATF_REQUIRE(mkfifoat(-1, FIFO, mode) == -1); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, mkfifoat_fd); ATF_TP_ADD_TC(tp, mkfifoat_fdcwd); ATF_TP_ADD_TC(tp, mkfifoat_fdcwderr); ATF_TP_ADD_TC(tp, mkfifoat_fderr); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/lib/libc/gen/t_glob.c =================================================================== --- vendor/NetBSD/tests/dist/lib/libc/gen/t_glob.c (revision 312218) +++ vendor/NetBSD/tests/dist/lib/libc/gen/t_glob.c (revision 312219) @@ -1,273 +1,273 @@ -/* $NetBSD: t_glob.c,v 1.4 2017/01/13 21:30:41 christos Exp $ */ +/* $NetBSD: t_glob.c,v 1.5 2017/01/14 20:47:41 christos Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Christos Zoulas * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_glob.c,v 1.4 2017/01/13 21:30:41 christos Exp $"); +__RCSID("$NetBSD: t_glob.c,v 1.5 2017/01/14 20:47:41 christos Exp $"); #include #include #include #include #include #include #include #include #include #include "h_macros.h" #ifdef DEBUG #define DPRINTF(a) printf a #else #define DPRINTF(a) #endif struct gl_file { const char *name; int dir; }; static struct gl_file a[] = { { "1", 0 }, { "b", 1 }, { "3", 0 }, { "4", 0 }, }; static struct gl_file b[] = { { "x", 0 }, { "y", 0 }, { "z", 0 }, { "w", 0 }, }; struct gl_dir { const char *name; /* directory name */ const struct gl_file *dir; size_t len, pos; }; static struct gl_dir d[] = { { "a", a, __arraycount(a), 0 }, { "a/b", b, __arraycount(b), 0 }, }; static const char *glob_star[] = { "a/1", "a/3", "a/4", "a/b", "a/b/w", "a/b/x", "a/b/y", "a/b/z", }; static const char *glob_star_not[] = { "a/1", "a/3", "a/4", "a/b", }; static void trim(char *buf, size_t len, const char *name) { char *path = buf, *epath = buf + len; while (path < epath && (*path++ = *name++) != '\0') continue; path--; while (path > buf && *--path == '/') *path = '\0'; } static void * gl_opendir(const char *dir) { size_t i; char buf[MAXPATHLEN]; trim(buf, sizeof(buf), dir); for (i = 0; i < __arraycount(d); i++) if (strcmp(buf, d[i].name) == 0) { DPRINTF(("opendir %s %zu\n", buf, i)); return &d[i]; } errno = ENOENT; return NULL; } static struct dirent * gl_readdir(void *v) { static struct dirent dir; struct gl_dir *dd = v; if (dd->pos < dd->len) { const struct gl_file *f = &dd->dir[dd->pos++]; strcpy(dir.d_name, f->name); dir.d_namlen = strlen(f->name); dir.d_ino = dd->pos; dir.d_type = f->dir ? DT_DIR : DT_REG; DPRINTF(("readdir %s %d\n", dir.d_name, dir.d_type)); dir.d_reclen = _DIRENT_RECLEN(&dir, dir.d_namlen); return &dir; } return NULL; } static int gl_stat(const char *name , __gl_stat_t *st) { char buf[MAXPATHLEN]; trim(buf, sizeof(buf), name); memset(st, 0, sizeof(*st)); if (strcmp(buf, "a") == 0 || strcmp(buf, "a/b") == 0) { - st->st_mode |= _S_IFDIR; + st->st_mode |= S_IFDIR; return 0; } if (buf[0] == 'a' && buf[1] == '/') { struct gl_file *f; size_t offs, count; if (buf[2] == 'b' && buf[3] == '/') { offs = 4; count = __arraycount(b); f = b; } else { offs = 2; count = __arraycount(a); f = a; } for (size_t i = 0; i < count; i++) if (strcmp(f[i].name, buf + offs) == 0) return 0; } DPRINTF(("stat %s %d\n", buf, st->st_mode)); errno = ENOENT; return -1; } static int gl_lstat(const char *name , __gl_stat_t *st) { return gl_stat(name, st); } static void gl_closedir(void *v) { struct gl_dir *dd = v; dd->pos = 0; DPRINTF(("closedir %p\n", dd)); } static void run(const char *p, int flags, const char **res, size_t len) { glob_t gl; size_t i; memset(&gl, 0, sizeof(gl)); gl.gl_opendir = gl_opendir; gl.gl_readdir = gl_readdir; gl.gl_closedir = gl_closedir; gl.gl_stat = gl_stat; gl.gl_lstat = gl_lstat; RZ(glob(p, GLOB_ALTDIRFUNC | flags, NULL, &gl)); for (i = 0; i < gl.gl_pathc; i++) DPRINTF(("%s\n", gl.gl_pathv[i])); ATF_CHECK(len == gl.gl_pathc); for (i = 0; i < gl.gl_pathc; i++) ATF_CHECK_STREQ(gl.gl_pathv[i], res[i]); globfree(&gl); } ATF_TC(glob_star); ATF_TC_HEAD(glob_star, tc) { atf_tc_set_md_var(tc, "descr", "Test glob(3) ** with GLOB_STAR"); } ATF_TC_BODY(glob_star, tc) { run("a/**", GLOB_STAR, glob_star, __arraycount(glob_star)); } ATF_TC(glob_star_not); ATF_TC_HEAD(glob_star_not, tc) { atf_tc_set_md_var(tc, "descr", "Test glob(3) ** without GLOB_STAR"); } ATF_TC_BODY(glob_star_not, tc) { run("a/**", 0, glob_star_not, __arraycount(glob_star_not)); } #if 0 ATF_TC(glob_nocheck); ATF_TC_HEAD(glob_nocheck, tc) { atf_tc_set_md_var(tc, "descr", "Test glob(3) pattern with backslash and GLOB_NOCHECK"); } ATF_TC_BODY(glob_nocheck, tc) { static const char pattern[] = { 'f', 'o', 'o', '\\', ';', 'b', 'a', 'r', '\0' }; static const char *glob_nocheck[] = { pattern }; run(pattern, GLOB_NOCHECK, glob_nocheck, __arraycount(glob_nocheck)); } #endif ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, glob_star); ATF_TP_ADD_TC(tp, glob_star_not); /* * Remove this test for now - the GLOB_NOCHECK return value has been * re-defined to return a modified pattern in revision 1.33 of glob.c * * ATF_TP_ADD_TC(tp, glob_nocheck); */ return atf_no_error(); } Index: vendor/NetBSD/tests/dist/lib/libc/regex/t_regex_att.c =================================================================== --- vendor/NetBSD/tests/dist/lib/libc/regex/t_regex_att.c (revision 312218) +++ vendor/NetBSD/tests/dist/lib/libc/regex/t_regex_att.c (revision 312219) @@ -1,629 +1,630 @@ -/* $NetBSD: t_regex_att.c,v 1.2 2017/01/14 00:50:56 christos Exp $ */ +/* $NetBSD: t_regex_att.c,v 1.3 2017/01/14 20:59:23 christos Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Christos Zoulas. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_regex_att.c,v 1.2 2017/01/14 00:50:56 christos Exp $"); +__RCSID("$NetBSD: t_regex_att.c,v 1.3 2017/01/14 20:59:23 christos Exp $"); #include -#include +#include +#include #include -#include +#include #include +#include +#include #include -#include -#include static const char sep[] = "\r\n\t"; static const char delim[3] = "\\\\\0"; static void fail(const char *pattern, const char *input, size_t lineno) { fprintf(stderr, "skipping failed test at line %zu (pattern=%s, input=%s)\n", lineno, pattern, input); } static int bug(const char *pattern, const char *input, size_t lineno) { static const struct { const char *p; const char *i; } b[] = { #if defined(REGEX_SPENCER) /* * The default libc implementation by Henry Spencer */ { "a[-]?c", "ac" }, // basic.dat { "(a*)*", "a" }, // categorization.dat { "(aba|a*b)*", "ababa" }, // categorization.dat { "\\(a\\(b\\)*\\)*\\2", "abab" }, // categorization.dat { "(a*)*", "aaaaaa" }, // nullsubexpression.dat { "(a*)*", "aaaaaax" }, // nullsubexpression.dat { "(a*)+", "a" }, // nullsubexpression.dat { "(a*)+", "aaaaaa" }, // nullsubexpression.dat { "(a*)+", "aaaaaax" }, // nullsubexpression.dat { "([a]*)*", "a" }, // nullsubexpression.dat { "([a]*)*", "aaaaaa" }, // nullsubexpression.dat { "([a]*)*", "aaaaaax" }, // nullsubexpression.dat { "([a]*)+", "a" }, // nullsubexpression.dat { "([a]*)+", "aaaaaa" }, // nullsubexpression.dat { "([a]*)+", "aaaaaax" }, // nullsubexpression.dat { "([^b]*)*", "a" }, // nullsubexpression.dat { "([^b]*)*", "aaaaaa" }, // nullsubexpression.dat { "([^b]*)*", "aaaaaab" }, // nullsubexpression.dat { "([ab]*)*", "a" }, // nullsubexpression.dat { "([ab]*)*", "aaaaaa" }, // nullsubexpression.dat { "([ab]*)*", "ababab" }, // nullsubexpression.dat { "([ab]*)*", "bababa" }, // nullsubexpression.dat { "([ab]*)*", "b" }, // nullsubexpression.dat { "([ab]*)*", "bbbbbb" }, // nullsubexpression.dat { "([ab]*)*", "aaaabcde" }, // nullsubexpression.dat { "([^a]*)*", "b" }, // nullsubexpression.dat { "([^a]*)*", "bbbbbb" }, // nullsubexpression.dat { "([^ab]*)*", "ccccxx" }, // nullsubexpression.dat { "\\(a*\\)*\\(x\\)", "ax" }, // nullsubexpression.dat { "\\(a*\\)*\\(x\\)", "axa" }, // nullsubexpression.dat { "\\(a*\\)*\\(x\\)\\(\\1\\)", "x" }, // nullsubexpression.dat /* crash! */ { "\\(a*\\)*\\(x\\)\\(\\1\\)", "ax" }, // nullsubexpression.dat /* crash! */ { "\\(a*\\)*\\(x\\)\\(\\1\\)\\(x\\)", "axxa" }, // "" { "(a*)*(x)", "ax" }, // nullsubexpression.dat { "(a*)*(x)", "axa" }, // nullsubexpression.dat { "(a*)+(x)", "ax" }, // nullsubexpression.dat { "(a*)+(x)", "axa" }, // nullsubexpression.dat { "((a|ab)(c|bcd))(d*)", "abcd" }, // forcedassoc.dat { "((a|ab)(bcd|c))(d*)", "abcd" }, // forcedassoc.dat { "((ab|a)(c|bcd))(d*)", "abcd" }, // forcedassoc.dat { "((ab|a)(bcd|c))(d*)", "abcd" }, // forcedassoc.dat { "((a*)(b|abc))(c*)", "abc" }, // forcedassoc.dat { "((a*)(abc|b))(c*)", "abc" }, // forcedassoc.dat { "((..)|(.)){2}", "aaa" }, // repetition.dat { "((..)|(.)){3}", "aaa" }, // repetition.dat { "((..)|(.)){3}", "aaaa" }, // repetition.dat { "((..)|(.)){3}", "aaaaa" }, // repetition.dat { "X(.?){0,}Y", "X1234567Y" }, // repetition.dat { "X(.?){1,}Y", "X1234567Y" }, // repetition.dat { "X(.?){2,}Y", "X1234567Y" }, // repetition.dat { "X(.?){3,}Y", "X1234567Y" }, // repetition.dat { "X(.?){4,}Y", "X1234567Y" }, // repetition.dat { "X(.?){5,}Y", "X1234567Y" }, // repetition.dat { "X(.?){6,}Y", "X1234567Y" }, // repetition.dat { "X(.?){7,}Y", "X1234567Y" }, // repetition.dat { "X(.?){0,8}Y", "X1234567Y" }, // repetition.dat { "X(.?){1,8}Y", "X1234567Y" }, // repetition.dat { "X(.?){2,8}Y", "X1234567Y" }, // repetition.dat { "X(.?){3,8}Y", "X1234567Y" }, // repetition.dat { "X(.?){4,8}Y", "X1234567Y" }, // repetition.dat { "X(.?){5,8}Y", "X1234567Y" }, // repetition.dat { "X(.?){6,8}Y", "X1234567Y" }, // repetition.dat { "X(.?){7,8}Y", "X1234567Y" }, // repetition.dat { "(a|ab|c|bcd){0,}(d*)", "ababcd" }, // repetition.dat { "(a|ab|c|bcd){1,}(d*)", "ababcd" }, // repetition.dat { "(a|ab|c|bcd){2,}(d*)", "ababcd" }, // repetition.dat { "(a|ab|c|bcd){3,}(d*)", "ababcd" }, // repetition.dat { "(a|ab|c|bcd){1,10}(d*)", "ababcd" }, // repetition.dat { "(a|ab|c|bcd){2,10}(d*)", "ababcd" }, // repetition.dat { "(a|ab|c|bcd){3,10}(d*)", "ababcd" }, // repetition.dat { "(a|ab|c|bcd)*(d*)", "ababcd" }, // repetition.dat { "(a|ab|c|bcd)+(d*)", "ababcd" }, // repetition.dat { "(ab|a|c|bcd){0,}(d*)", "ababcd" }, // repetition.dat { "(ab|a|c|bcd){1,}(d*)", "ababcd" }, // repetition.dat { "(ab|a|c|bcd){2,}(d*)", "ababcd" }, // repetition.dat { "(ab|a|c|bcd){3,}(d*)", "ababcd" }, // repetition.dat { "(ab|a|c|bcd){1,10}(d*)", "ababcd" }, // repetition.dat { "(ab|a|c|bcd){2,10}(d*)", "ababcd" }, // repetition.dat { "(ab|a|c|bcd){3,10}(d*)", "ababcd" }, // repetition.dat { "(ab|a|c|bcd)*(d*)", "ababcd" }, // repetition.dat { "(ab|a|c|bcd)+(d*)", "ababcd" }, // repetition.dat #elif defined(REGEX_TRE) { "a[-]?c", "ac" }, // basic.dat { "a\\(b\\)*\\1", "a" }, // categorization.dat { "a\\(b\\)*\\1", "abab" }, // categorization.dat { "\\(a\\(b\\)*\\)*\\2", "abab" }, // categorization.dat { "\\(a*\\)*\\(x\\)\\(\\1\\)", "ax" }, // categorization.dat { "\\(a*\\)*\\(x\\)\\(\\1\\)\\(x\\)", "axxa" }, // "" { "((..)|(.))*", "aa" }, // repetition.dat { "((..)|(.))*", "aaa" }, // repetition.dat { "((..)|(.))*", "aaaaa" }, // repetition.dat { "X(.?){7,}Y", "X1234567Y" }, // repetition.dat #else { "", "" } #endif }; for (size_t i = 0; i < __arraycount(b); i++) { if (strcmp(pattern, b[i].p) == 0 && strcmp(input, b[i].i) == 0) { fail(pattern, input, lineno); return 1; } } return 0; } #ifdef REGEX_SPENCER #define HAVE_BRACES 1 #define HAVE_MINIMAL 0 #endif #ifndef HAVE_BRACES #define HAVE_BRACES 1 #endif #ifndef HAVE_MINIMAL #define HAVE_MINIMAL 1 #endif static int optional(const char *s) { static const struct{ const char *n; int v; } nv[]= { { "[[]] not supported", HAVE_BRACES }, { "no *? +? mimimal match ops", HAVE_MINIMAL }, }; for (size_t i = 0; i < __arraycount(nv); i++) if (strcmp(nv[i].n, s) == 0) { if (nv[i].v) return 0; fprintf(stderr, "skipping unsupported [%s] tests\n", s); return 1; } ATF_REQUIRE_MSG(0, "Unknown feature: %s", s); return 0; } static int unsupported(const char *s) { static const char *we[] = { #if defined(REGEX_SPENCER) "ASSOCIATIVITY=left", // have right associativity "SUBEXPRESSION=precedence", // have grouping subexpression "REPEAT_LONGEST=last", // have first repeat longest "BUG=alternation-order", // don't have it "BUG=first-match", // don't have it "BUG=nomatch-match", // don't have it "BUG=repeat-any", // don't have it "BUG=range-null", // don't have it "BUG=repeat-null-unknown", // don't have it "BUG=repeat-null", // don't have it "BUG=repeat-artifact", // don't have it "BUG=subexpression-first", // don't have it #elif defined(REGEX_TRE) "ASSOCIATIVITY=right", // have left associativity "SUBEXPRESSION=grouping", // have precedence subexpression "REPEAT_LONGEST=first", // have last repeat longest "LENGTH=first", // have last length "BUG=alternation-order", // don't have it "BUG=first-match", // don't have it "BUG=range-null", // don't have it "BUG=repeat-null", // don't have it "BUG=repeat-artifact", // don't have it "BUG=subexpression-first", // don't have it "BUG=repeat-short", // don't have it #endif }; if (s == NULL) return 0; while (*s == '#' || isspace((unsigned char)*s)) s++; for (size_t i = 0; i < __arraycount(we); i++) if (strcmp(we[i], s) == 0) return 1; return 0; } static void geterror(const char *s, int *comp, int *exec) { static const struct { const char *n; int v; int ce; } nv[] = { #define COMP 1 #define EXEC 2 { "OK", 0, COMP|EXEC }, #define _DO(a, b) { # a, REG_ ## a, b }, _DO(NOMATCH, EXEC) _DO(BADPAT, COMP) _DO(ECOLLATE, COMP) _DO(ECTYPE, COMP) _DO(EESCAPE, COMP) _DO(ESUBREG, COMP) _DO(EBRACK, COMP) _DO(EPAREN, COMP) _DO(EBRACE, COMP) _DO(BADBR, COMP) _DO(ERANGE, COMP) _DO(ESPACE, EXEC) _DO(BADRPT, COMP) _DO(EMPTY, COMP) _DO(ASSERT, COMP) _DO(INVARG, COMP) _DO(ENOSYS, COMP) #undef _DO }; *comp = 0; *exec = 0; for (size_t i = 0; i < __arraycount(nv); i++) if (strcmp(s, nv[i].n) == 0) { if (nv[i].ce & COMP) *comp = nv[i].v; if (nv[i].ce & EXEC) *exec = nv[i].v; return; } ATF_REQUIRE_MSG(0, "Unknown error %s", s); return; } static int getflags(char *s) { int flags = 0; for (;; s++) switch (*s) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': *s = '\0'; break; case '\0': return flags; case 'B': case 'E': case 'F': case 'L': break; case 'i': flags |= REG_ICASE; *s = '\0'; break; case '$': *s = '\0'; break; case 'n': *s = '\0'; break; default: ATF_REQUIRE_MSG(0, "Unknown char %c", *s); break; } } static size_t getmatches(const char *s) { size_t i; char *q; for (i = 0; (q = strchr(s, '(')) != NULL; i++, s = q + 1) continue; ATF_REQUIRE_MSG(i != 0, "No parentheses found"); return i; } static void checkcomment(const char *s, size_t lineno) { if (s && strstr(s, "BUG") != NULL) fprintf(stderr, "Expected %s at line %zu\n", s, lineno); } static void checkmatches(const char *matches, size_t nm, const regmatch_t *pm, size_t lineno) { if (nm == 0) return; char *res; size_t len = strlen(matches) + 1, off = 0; ATF_REQUIRE((res = strdup(matches)) != NULL); for (size_t i = 0; i < nm; i++) { int l; if (pm[i].rm_so == -1 && pm[i].rm_eo == -1) l = snprintf(res + off, len - off, "(?,?)"); else l = snprintf(res + off, len - off, "(%lld,%lld)", (long long)pm[i].rm_so, (long long)pm[i].rm_eo); ATF_REQUIRE_MSG((size_t) l < len - off, "String too long %s" " cur=%d, max=%zu", res, l, len - off); off += l; } ATF_CHECK_STREQ_MSG(res, matches, " at line %zu", lineno); free(res); } static void att_test(const struct atf_tc *tc, const char *data_name) { regex_t re; char *line, *lastpattern = NULL, data_path[MAXPATHLEN]; size_t len, lineno = 0; int skipping = 0; FILE *input_file; snprintf(data_path, sizeof(data_path), "%s/data/%s.dat", atf_tc_get_config_var(tc, "srcdir"), data_name); input_file = fopen(data_path, "r"); if (input_file == NULL) atf_tc_fail("Failed to open input file %s", data_path); for (; (line = fparseln(input_file, &len, &lineno, delim, 0)) != NULL; free(line)) { char *name, *pattern, *input, *matches, *comment; regmatch_t *pm; size_t nm; #ifdef DEBUG fprintf(stderr, "[%s]\n", line); #endif if ((name = strtok(line, sep)) == NULL) continue; /* * We check these early so that we skip the lines quickly * in order to do more strict testing on the other arguments * The same characters are also tested in the switch below */ if (*name == '}') { skipping = 0; continue; } if (skipping) continue; if (*name == ';' || *name == '#' || strcmp(name, "NOTE") == 0) continue; if (*name == ':') { /* Skip ":HA#???:" prefix */ while (*++name && *name != ':') continue; if (*name) name++; } ATF_REQUIRE_MSG((pattern = strtok(NULL, sep)) != NULL, "Missing pattern at line %zu", lineno); ATF_REQUIRE_MSG((input = strtok(NULL, sep)) != NULL, "Missing input at line %zu", lineno); if (strchr(name, '$')) { ATF_REQUIRE(strunvis(pattern, pattern) != -1); ATF_REQUIRE(strunvis(input, input) != -1); } if (strcmp(input, "NULL") == 0) *input = '\0'; if (strcmp(pattern, "SAME") == 0) { ATF_REQUIRE(lastpattern != NULL); pattern = lastpattern; } else { free(lastpattern); ATF_REQUIRE((lastpattern = strdup(pattern)) != NULL); } ATF_REQUIRE_MSG((matches = strtok(NULL, sep)) != NULL, "Missing matches at line %zu", lineno); comment = strtok(NULL, sep); switch (*name) { case '{': /* Begin optional implementation */ if (optional(comment)) { skipping++; continue; } name++; /* We have it, so ignore */ break; case '}': /* End optional implementation */ skipping = 0; continue; case '?': /* Optional */ case '|': /* Alternative */ if (unsupported(comment)) continue; name++; /* We have it, so ignore */ break; case '#': /* Comment */ case ';': /* Skip */ continue; default: break; } /* XXX: Our bug */ if (bug(pattern, input, lineno)) continue; int comp, exec; if (*matches != '(') { geterror(matches, &comp, &exec); pm = NULL; nm = 0; } else { comp = exec = 0; nm = getmatches(matches); ATF_REQUIRE((pm = calloc(nm, sizeof(*pm))) != NULL); } int iflags = getflags(name); for (; *name; name++) { int flags; switch (*name) { case 'B': flags = REG_BASIC; break; case 'E': flags = REG_EXTENDED; break; case 'L': flags = REG_NOSPEC; break; default: ATF_REQUIRE_MSG(0, "Bad name %c", *name); continue; } int c = regcomp(&re, pattern, flags | iflags); ATF_REQUIRE_MSG(c == comp, "regcomp returned %d for pattern %s at line %zu", c, pattern, lineno); if (c) continue; int e = regexec(&re, input, nm, pm, 0); ATF_REQUIRE_MSG(e == exec, "Expected error %d," " got %d at line %zu", exec, e, lineno); checkmatches(matches, nm, pm, lineno); checkcomment(comment, lineno); regfree(&re); } free(pm); } fclose(input_file); } ATF_TC(basic); ATF_TC_HEAD(basic, tc) { atf_tc_set_md_var(tc, "descr", "Tests basic functionality"); } ATF_TC_BODY(basic, tc) { att_test(tc, "basic"); } ATF_TC(categorization); ATF_TC_HEAD(categorization, tc) { atf_tc_set_md_var(tc, "descr", "Tests implementation categorization"); } ATF_TC_BODY(categorization, tc) { att_test(tc, "categorization"); } ATF_TC(nullsubexpr); ATF_TC_HEAD(nullsubexpr, tc) { atf_tc_set_md_var(tc, "descr", "Tests (...)*"); } ATF_TC_BODY(nullsubexpr, tc) { att_test(tc, "nullsubexpr"); } ATF_TC(leftassoc); ATF_TC_HEAD(leftassoc, tc) { atf_tc_set_md_var(tc, "descr", "Tests left-associative " "implementations"); } ATF_TC_BODY(leftassoc, tc) { #if SKIP_LEFTASSOC /* jmmv: I converted the original shell-based tests to C and they * disabled this test in a very unconventional way without giving * any explation. Mark as broken here, but I don't know why. */ atf_tc_expect_fail("Reason for breakage unknown"); #endif att_test(tc, "leftassoc"); } ATF_TC(rightassoc); ATF_TC_HEAD(rightassoc, tc) { atf_tc_set_md_var(tc, "descr", "Tests right-associative " "implementations"); } ATF_TC_BODY(rightassoc, tc) { #if SKIP_RIGHTASSOC /* jmmv: I converted the original shell-based tests to C and they * disabled this test in a very unconventional way without giving * any explation. Mark as broken here, but I don't know why. */ atf_tc_expect_fail("Reason for breakage unknown"); #endif att_test(tc, "rightassoc"); } ATF_TC(forcedassoc); ATF_TC_HEAD(forcedassoc, tc) { atf_tc_set_md_var(tc, "descr", "Tests subexpression grouping to " "force association"); } ATF_TC_BODY(forcedassoc, tc) { att_test(tc, "forcedassoc"); } ATF_TC(repetition); ATF_TC_HEAD(repetition, tc) { atf_tc_set_md_var(tc, "descr", "Tests implicit vs. explicit " "repetition"); } ATF_TC_BODY(repetition, tc) { att_test(tc, "repetition"); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, basic); ATF_TP_ADD_TC(tp, categorization); ATF_TP_ADD_TC(tp, nullsubexpr); ATF_TP_ADD_TC(tp, leftassoc); ATF_TP_ADD_TC(tp, rightassoc); ATF_TP_ADD_TC(tp, forcedassoc); ATF_TP_ADD_TC(tp, repetition); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/lib/libc/setjmp/t_setjmp.c =================================================================== --- vendor/NetBSD/tests/dist/lib/libc/setjmp/t_setjmp.c (revision 312218) +++ vendor/NetBSD/tests/dist/lib/libc/setjmp/t_setjmp.c (revision 312219) @@ -1,196 +1,196 @@ -/* $NetBSD: t_setjmp.c,v 1.1 2010/12/27 19:35:31 pgoyette Exp $ */ +/* $NetBSD: t_setjmp.c,v 1.2 2017/01/14 21:08:17 christos Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1994 Christopher G. Demetriou * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the * NetBSD Project. See http://www.NetBSD.org/ for * information about NetBSD. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * <> */ #include __COPYRIGHT("@(#) Copyright (c) 2008\ The NetBSD Foundation, inc. All rights reserved."); -__RCSID("$NetBSD: t_setjmp.c,v 1.1 2010/12/27 19:35:31 pgoyette Exp $"); +__RCSID("$NetBSD: t_setjmp.c,v 1.2 2017/01/14 21:08:17 christos Exp $"); #include #include #include #include #include #include #include #include #include #define REQUIRE_ERRNO(x) ATF_REQUIRE_MSG(x, "%s", strerror(errno)) #define TEST_SETJMP 0 #define TEST_U_SETJMP 1 #define TEST_SIGSETJMP_SAVE 2 #define TEST_SIGSETJMP_NOSAVE 3 static int expectsignal; static void -aborthandler(int signo) +aborthandler(int signo __unused) { ATF_REQUIRE_MSG(expectsignal, "kill(SIGABRT) succeeded"); atf_tc_pass(); } static void h_check(int test) { struct sigaction sa; jmp_buf jb; sigjmp_buf sjb; sigset_t ss; int i, x; i = getpid(); if (test == TEST_SETJMP || test == TEST_SIGSETJMP_SAVE) expectsignal = 0; else if (test == TEST_U_SETJMP || test == TEST_SIGSETJMP_NOSAVE) expectsignal = 1; else atf_tc_fail("unknown test"); sa.sa_handler = aborthandler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; REQUIRE_ERRNO(sigaction(SIGABRT, &sa, NULL) != -1); REQUIRE_ERRNO(sigemptyset(&ss) != -1); REQUIRE_ERRNO(sigaddset(&ss, SIGABRT) != -1); REQUIRE_ERRNO(sigprocmask(SIG_BLOCK, &ss, NULL) != -1); if (test == TEST_SETJMP) x = setjmp(jb); else if (test == TEST_U_SETJMP) x = _setjmp(jb); else x = sigsetjmp(sjb, !expectsignal); if (x != 0) { ATF_REQUIRE_MSG(x == i, "setjmp returned wrong value"); kill(i, SIGABRT); ATF_REQUIRE_MSG(!expectsignal, "kill(SIGABRT) failed"); atf_tc_pass(); } REQUIRE_ERRNO(sigprocmask(SIG_UNBLOCK, &ss, NULL) != -1); if (test == TEST_SETJMP) longjmp(jb, i); else if (test == TEST_U_SETJMP) _longjmp(jb, i); else siglongjmp(sjb, i); atf_tc_fail("jmp failed"); } ATF_TC(setjmp); ATF_TC_HEAD(setjmp, tc) { atf_tc_set_md_var(tc, "descr", "Checks setjmp(3)"); } ATF_TC_BODY(setjmp, tc) { h_check(TEST_SETJMP); } ATF_TC(_setjmp); ATF_TC_HEAD(_setjmp, tc) { atf_tc_set_md_var(tc, "descr", "Checks _setjmp(3)"); } ATF_TC_BODY(_setjmp, tc) { h_check(TEST_U_SETJMP); } ATF_TC(sigsetjmp_save); ATF_TC_HEAD(sigsetjmp_save, tc) { atf_tc_set_md_var(tc, "descr", "Checks sigsetjmp(3) with savemask enabled"); } ATF_TC_BODY(sigsetjmp_save, tc) { h_check(TEST_SIGSETJMP_SAVE); } ATF_TC(sigsetjmp_nosave); ATF_TC_HEAD(sigsetjmp_nosave, tc) { atf_tc_set_md_var(tc, "descr", "Checks sigsetjmp(3) with savemask disabled"); } ATF_TC_BODY(sigsetjmp_nosave, tc) { h_check(TEST_SIGSETJMP_NOSAVE); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, setjmp); ATF_TP_ADD_TC(tp, _setjmp); ATF_TP_ADD_TC(tp, sigsetjmp_save); ATF_TP_ADD_TC(tp, sigsetjmp_nosave); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/lib/libc/setjmp/t_threadjmp.c =================================================================== --- vendor/NetBSD/tests/dist/lib/libc/setjmp/t_threadjmp.c (revision 312218) +++ vendor/NetBSD/tests/dist/lib/libc/setjmp/t_threadjmp.c (revision 312219) @@ -1,218 +1,218 @@ -/* $NetBSD: t_threadjmp.c,v 1.1 2011/04/21 18:58:20 martin Exp $ */ +/* $NetBSD: t_threadjmp.c,v 1.2 2017/01/14 21:08:17 christos Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1994 Christopher G. Demetriou * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the * NetBSD Project. See http://www.NetBSD.org/ for * information about NetBSD. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * <> */ #include __COPYRIGHT("@(#) Copyright (c) 2008\ The NetBSD Foundation, inc. All rights reserved."); -__RCSID("$NetBSD: t_threadjmp.c,v 1.1 2011/04/21 18:58:20 martin Exp $"); +__RCSID("$NetBSD: t_threadjmp.c,v 1.2 2017/01/14 21:08:17 christos Exp $"); #include #include #include #include #include #include #include #include #include #include #define REQUIRE_ERRNO(x) ATF_REQUIRE_MSG(x, "%s", strerror(errno)) #define TEST_SETJMP 0 #define TEST_U_SETJMP 1 #define TEST_SIGSETJMP_SAVE 2 #define TEST_SIGSETJMP_NOSAVE 3 static pthread_t myself = NULL; static int expectsignal; static void -aborthandler(int signo) +aborthandler(int signo __unused) { ATF_REQUIRE(myself == pthread_self()); ATF_REQUIRE_MSG(expectsignal, "kill(SIGABRT) succeeded"); atf_tc_pass(); } static void h_check(int test) { struct sigaction sa; jmp_buf jb; sigjmp_buf sjb; sigset_t ss; int i, x; myself = pthread_self(); i = getpid(); if (test == TEST_SETJMP || test == TEST_SIGSETJMP_SAVE) expectsignal = 0; else if (test == TEST_U_SETJMP || test == TEST_SIGSETJMP_NOSAVE) expectsignal = 1; else atf_tc_fail("unknown test"); sa.sa_handler = aborthandler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; REQUIRE_ERRNO(sigaction(SIGABRT, &sa, NULL) != -1); REQUIRE_ERRNO(sigemptyset(&ss) != -1); REQUIRE_ERRNO(sigaddset(&ss, SIGABRT) != -1); REQUIRE_ERRNO(sigprocmask(SIG_BLOCK, &ss, NULL) != -1); ATF_REQUIRE(myself == pthread_self()); if (test == TEST_SETJMP) x = setjmp(jb); else if (test == TEST_U_SETJMP) x = _setjmp(jb); else x = sigsetjmp(sjb, !expectsignal); if (x != 0) { ATF_REQUIRE(myself == pthread_self()); ATF_REQUIRE_MSG(x == i, "setjmp returned wrong value"); kill(i, SIGABRT); ATF_REQUIRE_MSG(!expectsignal, "kill(SIGABRT) failed"); ATF_REQUIRE(myself == pthread_self()); atf_tc_pass(); } ATF_REQUIRE(myself == pthread_self()); REQUIRE_ERRNO(sigprocmask(SIG_UNBLOCK, &ss, NULL) != -1); if (test == TEST_SETJMP) longjmp(jb, i); else if (test == TEST_U_SETJMP) _longjmp(jb, i); else siglongjmp(sjb, i); atf_tc_fail("jmp failed"); } ATF_TC(setjmp); ATF_TC_HEAD(setjmp, tc) { atf_tc_set_md_var(tc, "descr", "Checks pthread_self() and setjmp(3)"); } ATF_TC_BODY(setjmp, tc) { h_check(TEST_SETJMP); } ATF_TC(_setjmp); ATF_TC_HEAD(_setjmp, tc) { atf_tc_set_md_var(tc, "descr", "Checks pthread_self() and _setjmp(3)"); } ATF_TC_BODY(_setjmp, tc) { h_check(TEST_U_SETJMP); } ATF_TC(sigsetjmp_save); ATF_TC_HEAD(sigsetjmp_save, tc) { atf_tc_set_md_var(tc, "descr", "Checks pthread_self() and sigsetjmp(3) with savemask enabled"); } ATF_TC_BODY(sigsetjmp_save, tc) { h_check(TEST_SIGSETJMP_SAVE); } ATF_TC(sigsetjmp_nosave); ATF_TC_HEAD(sigsetjmp_nosave, tc) { atf_tc_set_md_var(tc, "descr", "Checks pthread_self() and sigsetjmp(3) with savemask disabled"); } ATF_TC_BODY(sigsetjmp_nosave, tc) { h_check(TEST_SIGSETJMP_NOSAVE); } ATF_TP_ADD_TCS(tp) { /* * These test cases try to verify setjmp and friends in a program * linked with pthreads, and verify that pthread_self() stays * consistent throughout the program. A setcontext() call invoked * by *setjmp() might clobber the TLS special register used to * implement pthread_self(). */ ATF_TP_ADD_TC(tp, setjmp); ATF_TP_ADD_TC(tp, _setjmp); ATF_TP_ADD_TC(tp, sigsetjmp_save); ATF_TP_ADD_TC(tp, sigsetjmp_nosave); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/lib/libc/string/t_strlen.c =================================================================== --- vendor/NetBSD/tests/dist/lib/libc/string/t_strlen.c (revision 312218) +++ vendor/NetBSD/tests/dist/lib/libc/string/t_strlen.c (revision 312219) @@ -1,199 +1,202 @@ -/* $NetBSD: t_strlen.c,v 1.5 2011/07/14 07:33:20 jruoho Exp $ */ +/* $NetBSD: t_strlen.c,v 1.6 2017/01/14 20:49:24 christos Exp $ */ /* * Written by J.T. Conklin * Public domain. */ #include #include #include #include #include #include #include static void write_num(int); static void write_num(int val) { char buf[20]; int i; for (i = sizeof buf; --i >= 0;) { buf[i] = '0' + val % 10; val /= 10; if (val == 0) { write(2, buf + i, sizeof buf - i); return; } } write(2, "overflow", 8); } ATF_TC(strlen_basic); ATF_TC_HEAD(strlen_basic, tc) { atf_tc_set_md_var(tc, "descr", "Test strlen(3) results"); } ATF_TC_BODY(strlen_basic, tc) { + void *dl_handle; /* try to trick the compiler */ size_t (*strlen_fn)(const char *); unsigned int a, t; size_t len; char buf[64]; struct tab { const char* val; size_t len; }; const struct tab tab[] = { /* * patterns that check for all combinations of leading and * trailing unaligned characters (on a 64 bit processor) */ { "", 0 }, { "a", 1 }, { "ab", 2 }, { "abc", 3 }, { "abcd", 4 }, { "abcde", 5 }, { "abcdef", 6 }, { "abcdefg", 7 }, { "abcdefgh", 8 }, { "abcdefghi", 9 }, { "abcdefghij", 10 }, { "abcdefghijk", 11 }, { "abcdefghijkl", 12 }, { "abcdefghijklm", 13 }, { "abcdefghijklmn", 14 }, { "abcdefghijklmno", 15 }, { "abcdefghijklmnop", 16 }, { "abcdefghijklmnopq", 17 }, { "abcdefghijklmnopqr", 18 }, { "abcdefghijklmnopqrs", 19 }, { "abcdefghijklmnopqrst", 20 }, { "abcdefghijklmnopqrstu", 21 }, { "abcdefghijklmnopqrstuv", 22 }, { "abcdefghijklmnopqrstuvw", 23 }, /* * patterns that check for the cases where the expression: * * ((word - 0x7f7f..7f) & 0x8080..80) * * returns non-zero even though there are no zero bytes in * the word. */ { "" "\xff\xff\xff\xff\xff\xff\xff\xff" "abcdefgh", 16 }, { "a" "\xff\xff\xff\xff\xff\xff\xff\xff" "bcdefgh", 16 }, { "ab" "\xff\xff\xff\xff\xff\xff\xff\xff" "cdefgh", 16 }, { "abc" "\xff\xff\xff\xff\xff\xff\xff\xff" "defgh", 16 }, { "abcd" "\xff\xff\xff\xff\xff\xff\xff\xff" "efgh", 16 }, { "abcde" "\xff\xff\xff\xff\xff\xff\xff\xff" "fgh", 16 }, { "abcdef" "\xff\xff\xff\xff\xff\xff\xff\xff" "gh", 16 }, { "abcdefg" "\xff\xff\xff\xff\xff\xff\xff\xff" "h", 16 }, { "abcdefgh" "\xff\xff\xff\xff\xff\xff\xff\xff" "", 16 }, }; /* * During testing it is useful have the rest of the program * use a known good version! */ - strlen_fn = dlsym(dlopen(NULL, RTLD_LAZY), "test_strlen"); + dl_handle = dlopen(NULL, RTLD_LAZY); + strlen_fn = dlsym(dl_handle, "test_strlen"); if (!strlen_fn) strlen_fn = strlen; for (a = 0; a < sizeof(long); ++a) { for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) { memcpy(&buf[a], tab[t].val, tab[t].len + 1); len = strlen_fn(&buf[a]); if (len != tab[t].len) { /* Write error without using printf / strlen */ write(2, "alignment ", 10); write_num(a); write(2, ", test ", 7); write_num(t); write(2, ", got len ", 10); write_num(len); write(2, ", not ", 6); write_num(tab[t].len); write(2, ", for '", 7); write(2, tab[t].val, tab[t].len); write(2, "'\n", 2); atf_tc_fail("See stderr for details"); } } } + (void)dlclose(dl_handle); } ATF_TC(strlen_huge); ATF_TC_HEAD(strlen_huge, tc) { atf_tc_set_md_var(tc, "descr", "Test strlen(3) with huge strings"); } ATF_TC_BODY(strlen_huge, tc) { long page; char *str; size_t i; page = sysconf(_SC_PAGESIZE); ATF_REQUIRE(page >= 0); for (i = 1; i < 1000; i = i + 100) { str = malloc(i * page + 1); if (str == NULL) continue; (void)memset(str, 'x', i * page); str[i * page] = '\0'; ATF_REQUIRE(strlen(str) == i * page); free(str); } } ATF_TC(strnlen_basic); ATF_TC_HEAD(strnlen_basic, tc) { atf_tc_set_md_var(tc, "descr", "A naive test of strnlen(3)"); } ATF_TC_BODY(strnlen_basic, tc) { char buf[1]; buf[0] = '\0'; ATF_CHECK(strnlen(buf, 000) == 0); ATF_CHECK(strnlen(buf, 111) == 0); ATF_CHECK(strnlen("xxx", 0) == 0); ATF_CHECK(strnlen("xxx", 1) == 1); ATF_CHECK(strnlen("xxx", 2) == 2); ATF_CHECK(strnlen("xxx", 3) == 3); ATF_CHECK(strnlen("xxx", 9) == 3); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, strlen_basic); ATF_TP_ADD_TC(tp, strlen_huge); ATF_TP_ADD_TC(tp, strnlen_basic); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/lib/libc/sys/t_mincore.c =================================================================== --- vendor/NetBSD/tests/dist/lib/libc/sys/t_mincore.c (revision 312218) +++ vendor/NetBSD/tests/dist/lib/libc/sys/t_mincore.c (revision 312219) @@ -1,319 +1,326 @@ -/* $NetBSD: t_mincore.c,v 1.9 2017/01/10 22:36:29 christos Exp $ */ +/* $NetBSD: t_mincore.c,v 1.10 2017/01/14 20:51:13 christos Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jukka Ruohonen. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, * NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_mincore.c,v 1.9 2017/01/10 22:36:29 christos Exp $"); +__RCSID("$NetBSD: t_mincore.c,v 1.10 2017/01/14 20:51:13 christos Exp $"); #include #include #include #include #include #include #include #include #include #include #include #include static long page = 0; static const char path[] = "mincore"; static size_t check_residency(void *, size_t); static size_t check_residency(void *addr, size_t npgs) { size_t i, resident; char *vec; vec = malloc(npgs); ATF_REQUIRE(vec != NULL); ATF_REQUIRE(mincore(addr, npgs * page, vec) == 0); for (i = resident = 0; i < npgs; i++) { if (vec[i] != 0) resident++; #if 0 (void)fprintf(stderr, "page 0x%p is %sresident\n", (char *)addr + (i * page), vec[i] ? "" : "not "); #endif } free(vec); return resident; } ATF_TC(mincore_err); ATF_TC_HEAD(mincore_err, tc) { atf_tc_set_md_var(tc, "descr", "Test errors from mincore(2)"); } ATF_TC_BODY(mincore_err, tc) { char *map, *vec; map = mmap(NULL, page, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); vec = malloc(page); ATF_REQUIRE(vec != NULL); ATF_REQUIRE(map != MAP_FAILED); errno = 0; ATF_REQUIRE_ERRNO(EINVAL, mincore(map, 0, vec) == -1); errno = 0; ATF_REQUIRE_ERRNO(ENOMEM, mincore(0, page, vec) == -1); errno = 0; ATF_REQUIRE_ERRNO(EFAULT, mincore(map, page, (void *)-1) == -1); free(vec); ATF_REQUIRE(munmap(map, page) == 0); } ATF_TC_WITH_CLEANUP(mincore_resid); ATF_TC_HEAD(mincore_resid, tc) { atf_tc_set_md_var(tc, "descr", "Test page residency with mincore(2)"); + atf_tc_set_md_var(tc, "require.user", "root"); } ATF_TC_BODY(mincore_resid, tc) { void *addr, *addr2, *addr3, *buf; size_t npgs = 0, resident; struct stat st; int fd, rv; struct rlimit rlim; ATF_REQUIRE(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0); + /* + * Bump the mlock limit to unlimited so the rest of the testcase + * passes instead of failing on the mlock call. + */ + rlim.rlim_max = RLIM_INFINITY; rlim.rlim_cur = rlim.rlim_max; ATF_REQUIRE(setrlimit(RLIMIT_MEMLOCK, &rlim) == 0); (void)memset(&st, 0, sizeof(struct stat)); fd = open(path, O_RDWR | O_CREAT, 0700); buf = malloc(page * 5); ATF_REQUIRE(fd >= 0); ATF_REQUIRE(buf != NULL); rv = write(fd, buf, page * 5); ATF_REQUIRE(rv >= 0); ATF_REQUIRE(fd >= 0); ATF_REQUIRE(fstat(fd, &st) == 0); addr = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_FILE | MAP_SHARED, fd, (off_t) 0); ATF_REQUIRE(addr != MAP_FAILED); (void)close(fd); npgs = st.st_size / page; if (st.st_size % page != 0) npgs++; (void)check_residency(addr, npgs); rv = mlock(addr, npgs * page); if (rv == -1 && errno == EAGAIN) atf_tc_skip("hit process resource limits"); ATF_REQUIRE(munmap(addr, st.st_size) == 0); npgs = 128; addr = mmap(NULL, npgs * page, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_WIRED, -1, (off_t)0); if (addr == MAP_FAILED) atf_tc_skip("could not mmap wired anonymous test area, system " "might be low on memory"); ATF_REQUIRE(check_residency(addr, npgs) == npgs); ATF_REQUIRE(munmap(addr, npgs * page) == 0); npgs = 128; addr = mmap(NULL, npgs * page, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, (off_t)0); ATF_REQUIRE(addr != MAP_FAILED); /* * Check that the in-core pages match the locked pages. */ ATF_REQUIRE(check_residency(addr, npgs) == 0); errno = 0; if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0 && errno != ENOMEM) atf_tc_fail("mlockall(2) failed"); if (errno == ENOMEM) atf_tc_skip("mlockall() exceeded process resource limits"); resident = check_residency(addr, npgs); if (resident < npgs) atf_tc_fail("mlockall(MCL_FUTURE) succeeded, still only " "%zu pages of the newly mapped %zu pages are resident", resident, npgs); addr2 = mmap(NULL, npgs * page, PROT_READ, MAP_ANON, -1, (off_t)0); addr3 = mmap(NULL, npgs * page, PROT_NONE, MAP_ANON, -1, (off_t)0); if (addr2 == MAP_FAILED || addr3 == MAP_FAILED) atf_tc_skip("could not mmap more anonymous test pages with " "mlockall(MCL_FUTURE) in effect, system " "might be low on memory"); ATF_REQUIRE(check_residency(addr2, npgs) == npgs); ATF_REQUIRE(check_residency(addr3, npgs) == 0); ATF_REQUIRE(mprotect(addr3, npgs * page, PROT_READ) == 0); ATF_REQUIRE(check_residency(addr, npgs) == npgs); ATF_REQUIRE(check_residency(addr2, npgs) == npgs); (void)munlockall(); ATF_REQUIRE(madvise(addr2, npgs * page, MADV_FREE) == 0); ATF_REQUIRE(check_residency(addr2, npgs) == 0); (void)memset(addr, 0, npgs * page); ATF_REQUIRE(madvise(addr, npgs * page, MADV_FREE) == 0); ATF_REQUIRE(check_residency(addr, npgs) == 0); (void)munmap(addr, npgs * page); (void)munmap(addr2, npgs * page); (void)munmap(addr3, npgs * page); (void)unlink(path); + free(buf); } ATF_TC_CLEANUP(mincore_resid, tc) { (void)unlink(path); } ATF_TC(mincore_shmseg); ATF_TC_HEAD(mincore_shmseg, tc) { atf_tc_set_md_var(tc, "descr", "residency of shared memory"); } ATF_TC_BODY(mincore_shmseg, tc) { size_t npgs = 128; void *addr = NULL; int shmid; shmid = shmget(IPC_PRIVATE, npgs * page, IPC_CREAT | S_IRUSR | S_IWUSR); ATF_REQUIRE(shmid != -1); addr = shmat(shmid, NULL, 0); ATF_REQUIRE(addr != NULL); ATF_REQUIRE(check_residency(addr, npgs) == 0); (void)memset(addr, 0xff, npgs * page); ATF_REQUIRE(check_residency(addr, npgs) == npgs); ATF_REQUIRE(madvise(addr, npgs * page, MADV_FREE) == 0); /* * NOTE! Even though we have MADV_FREE'd the range, * there is another reference (the kernel's) to the * object which owns the pages. In this case, the * kernel does not simply free the pages, as haphazardly * freeing pages when there are still references to * an object can cause data corruption (say, the other * referencer doesn't expect the pages to be freed, * and is surprised by the subsequent ZFOD). * * Because of this, we simply report the number of * pages still resident, for information only. */ npgs = check_residency(addr, npgs); (void)fprintf(stderr, "%zu pages still resident\n", npgs); ATF_REQUIRE(shmdt(addr) == 0); ATF_REQUIRE(shmctl(shmid, IPC_RMID, NULL) == 0); } ATF_TP_ADD_TCS(tp) { page = sysconf(_SC_PAGESIZE); ATF_REQUIRE(page >= 0); ATF_TP_ADD_TC(tp, mincore_err); ATF_TP_ADD_TC(tp, mincore_resid); ATF_TP_ADD_TC(tp, mincore_shmseg); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/lib/libc/sys/t_msync.c =================================================================== --- vendor/NetBSD/tests/dist/lib/libc/sys/t_msync.c (revision 312218) +++ vendor/NetBSD/tests/dist/lib/libc/sys/t_msync.c (revision 312219) @@ -1,237 +1,224 @@ -/* $NetBSD: t_msync.c,v 1.2 2012/03/16 06:15:17 matt Exp $ */ +/* $NetBSD: t_msync.c,v 1.3 2017/01/14 20:52:42 christos Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jukka Ruohonen. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_msync.c,v 1.2 2012/03/16 06:15:17 matt Exp $"); +__RCSID("$NetBSD: t_msync.c,v 1.3 2017/01/14 20:52:42 christos Exp $"); #include #include #include #include #include #include #include #include static long page = 0; static const off_t off = 512; static const char path[] = "msync"; static const char *msync_sync(const char *, int); static const char * msync_sync(const char *garbage, int flags) { char *buf, *map = MAP_FAILED; const char *str = NULL; - size_t i, len; - ssize_t tot; + size_t len; int fd, rv; /* * Create a temporary file, write * one page to it, and map the file. */ buf = malloc(page); if (buf == NULL) return NULL; - for (i = 0; i < (size_t)page; i++) - buf[i] = 'x'; + memset(buf, 'x', page); fd = open(path, O_RDWR | O_CREAT, 0700); if (fd < 0) { - str = "failed to open"; - goto out; + free(buf); + return "failed to open"; } - tot = 0; - - while (tot < page) { - - rv = write(fd, buf, sizeof(buf)); - - if (rv < 0) { - str = "failed to write"; - goto out; - } - - tot += rv; - } + ATF_REQUIRE_MSG(write(fd, buf, page) != -1, "write(2) failed: %s", + strerror(errno)); map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { str = "failed to map"; goto out; } /* * Seek to an arbitrary offset and * write garbage to this position. */ if (lseek(fd, off, SEEK_SET) != off) { str = "failed to seek"; goto out; } len = strlen(garbage); rv = write(fd, garbage, len); if (rv != (ssize_t)len) { str = "failed to write garbage"; goto out; } /* * Synchronize the mapping and verify * that garbage is at the given offset. */ if (msync(map, page, flags) != 0) { str = "failed to msync"; goto out; } if (memcmp(map + off, garbage, len) != 0) { str = "msync did not synchronize"; goto out; } out: free(buf); (void)close(fd); (void)unlink(path); if (map != MAP_FAILED) (void)munmap(map, page); return str; } ATF_TC(msync_async); ATF_TC_HEAD(msync_async, tc) { atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_ASYNC"); } ATF_TC_BODY(msync_async, tc) { const char *str; str = msync_sync("garbage", MS_ASYNC); if (str != NULL) atf_tc_fail("%s", str); } ATF_TC(msync_err); ATF_TC_HEAD(msync_err, tc) { atf_tc_set_md_var(tc, "descr", "Test error conditions in msync(2)"); } ATF_TC_BODY(msync_err, tc) { char *map = MAP_FAILED; /* * Test that invalid flags error out. */ ATF_REQUIRE(msync_sync("error", -1) != NULL); ATF_REQUIRE(msync_sync("error", INT_MAX) != NULL); errno = 0; /* * Map a page and then unmap to get an unmapped address. */ map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); ATF_REQUIRE(map != MAP_FAILED); (void)munmap(map, page); ATF_REQUIRE(msync(map, page, MS_SYNC) != 0); ATF_REQUIRE(errno == EFAULT); } ATF_TC(msync_invalidate); ATF_TC_HEAD(msync_invalidate, tc) { atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_INVALIDATE"); } ATF_TC_BODY(msync_invalidate, tc) { const char *str; str = msync_sync("garbage", MS_INVALIDATE); if (str != NULL) atf_tc_fail("%s", str); } ATF_TC(msync_sync); ATF_TC_HEAD(msync_sync, tc) { atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_SYNC"); } ATF_TC_BODY(msync_sync, tc) { const char *str; str = msync_sync("garbage", MS_SYNC); if (str != NULL) atf_tc_fail("%s", str); } ATF_TP_ADD_TCS(tp) { page = sysconf(_SC_PAGESIZE); ATF_REQUIRE(page >= 0); ATF_REQUIRE(page > off); ATF_TP_ADD_TC(tp, msync_async); ATF_TP_ADD_TC(tp, msync_err); ATF_TP_ADD_TC(tp, msync_invalidate); ATF_TP_ADD_TC(tp, msync_sync); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/lib/libc/sys/t_unlink.c =================================================================== --- vendor/NetBSD/tests/dist/lib/libc/sys/t_unlink.c (revision 312218) +++ vendor/NetBSD/tests/dist/lib/libc/sys/t_unlink.c (revision 312219) @@ -1,161 +1,158 @@ -/* $NetBSD: t_unlink.c,v 1.3 2017/01/13 19:33:03 christos Exp $ */ +/* $NetBSD: t_unlink.c,v 1.4 2017/01/14 20:55:26 christos Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jukka Ruohonen. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_unlink.c,v 1.3 2017/01/13 19:33:03 christos Exp $"); +__RCSID("$NetBSD: t_unlink.c,v 1.4 2017/01/14 20:55:26 christos Exp $"); #include #include #include #include #include #include #include static char path[] = "unlink"; ATF_TC_WITH_CLEANUP(unlink_basic); ATF_TC_HEAD(unlink_basic, tc) { atf_tc_set_md_var(tc, "descr", "A basic test of unlink(2)"); } ATF_TC_BODY(unlink_basic, tc) { const size_t n = 512; size_t i; int fd; for (i = 0; i < n; i++) { fd = open(path, O_RDWR | O_CREAT, 0666); ATF_REQUIRE(fd != -1); ATF_REQUIRE(close(fd) == 0); ATF_REQUIRE(unlink(path) == 0); errno = 0; ATF_REQUIRE_ERRNO(ENOENT, open(path, O_RDONLY) == -1); } } ATF_TC_CLEANUP(unlink_basic, tc) { (void)unlink(path); } ATF_TC_WITH_CLEANUP(unlink_err); ATF_TC_HEAD(unlink_err, tc) { atf_tc_set_md_var(tc, "descr", "Test error conditions of unlink(2)"); } ATF_TC_BODY(unlink_err, tc) { char buf[PATH_MAX + 1]; (void)memset(buf, 'x', sizeof(buf)); errno = 0; ATF_REQUIRE_ERRNO(EBUSY, unlink("/") == -1); errno = 0; ATF_REQUIRE_ERRNO(ENAMETOOLONG, unlink(buf) == -1); errno = 0; ATF_REQUIRE_ERRNO(ENOENT, unlink("/a/b/c/d/e/f/g/h/i/j/k/l/m") == -1); } ATF_TC_CLEANUP(unlink_err, tc) { (void)unlink(path); } ATF_TC_WITH_CLEANUP(unlink_fifo); ATF_TC_HEAD(unlink_fifo, tc) { atf_tc_set_md_var(tc, "descr", "Test unlink(2) for a FIFO"); } ATF_TC_BODY(unlink_fifo, tc) { - int fd; - ATF_REQUIRE_MSG((fd = mkfifo(path, 0666)) == 0, - "mkfifo failed: %s", strerror(errno)); - (void)close(fd); + ATF_REQUIRE(mkfifo(path, 0666) == 0); ATF_REQUIRE(unlink(path) == 0); errno = 0; ATF_REQUIRE_ERRNO(ENOENT, open(path, O_RDONLY) == -1); } ATF_TC_CLEANUP(unlink_fifo, tc) { (void)unlink(path); } ATF_TC_WITH_CLEANUP(unlink_perm); ATF_TC_HEAD(unlink_perm, tc) { atf_tc_set_md_var(tc, "descr", "Test permissions with unlink(2)"); atf_tc_set_md_var(tc, "require.user", "unprivileged"); } ATF_TC_BODY(unlink_perm, tc) { int rv; errno = 0; rv = unlink("/etc"); ATF_REQUIRE_MSG(rv == -1 && (errno == EACCES || errno == EPERM), "unlinking a directory did not fail with EPERM or EACCESS; " "unlink() returned %d, errno %d", rv, errno); errno = 0; ATF_REQUIRE_ERRNO(EACCES, unlink("/root/.profile") == -1); } ATF_TC_CLEANUP(unlink_perm, tc) { (void)unlink(path); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, unlink_basic); ATF_TP_ADD_TC(tp, unlink_err); ATF_TP_ADD_TC(tp, unlink_fifo); ATF_TP_ADD_TC(tp, unlink_perm); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/lib/librt/t_sem.c =================================================================== --- vendor/NetBSD/tests/dist/lib/librt/t_sem.c (revision 312218) +++ vendor/NetBSD/tests/dist/lib/librt/t_sem.c (revision 312219) @@ -1,175 +1,183 @@ -/* $NetBSD: t_sem.c,v 1.2 2010/11/08 13:05:49 njoly Exp $ */ +/* $NetBSD: t_sem.c,v 1.3 2017/01/14 20:58:20 christos Exp $ */ /* * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (C) 2000 Jason Evans . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __COPYRIGHT("@(#) Copyright (c) 2008, 2010\ The NetBSD Foundation, inc. All rights reserved."); -__RCSID("$NetBSD: t_sem.c,v 1.2 2010/11/08 13:05:49 njoly Exp $"); +__RCSID("$NetBSD: t_sem.c,v 1.3 2017/01/14 20:58:20 christos Exp $"); #include #include #include #include #include #include #include #define NCHILDREN 10 -ATF_TC(basic); +ATF_TC_WITH_CLEANUP(basic); ATF_TC_HEAD(basic, tc) { atf_tc_set_md_var(tc, "descr", "Checks basic functionality of POSIX " "semaphores"); } ATF_TC_BODY(basic, tc) { int val; sem_t *sem_b; if (sysconf(_SC_SEMAPHORES) == -1) atf_tc_skip("POSIX semaphores not supported"); sem_b = sem_open("/sem_b", O_CREAT | O_EXCL, 0644, 0); ATF_REQUIRE(sem_b != SEM_FAILED); ATF_REQUIRE_EQ(sem_getvalue(sem_b, &val), 0); ATF_REQUIRE_EQ(val, 0); ATF_REQUIRE_EQ(sem_post(sem_b), 0); ATF_REQUIRE_EQ(sem_getvalue(sem_b, &val), 0); ATF_REQUIRE_EQ(val, 1); ATF_REQUIRE_EQ(sem_wait(sem_b), 0); ATF_REQUIRE_EQ(sem_trywait(sem_b), -1); ATF_REQUIRE_EQ(errno, EAGAIN); ATF_REQUIRE_EQ(sem_post(sem_b), 0); ATF_REQUIRE_EQ(sem_trywait(sem_b), 0); ATF_REQUIRE_EQ(sem_post(sem_b), 0); ATF_REQUIRE_EQ(sem_wait(sem_b), 0); ATF_REQUIRE_EQ(sem_post(sem_b), 0); ATF_REQUIRE_EQ(sem_close(sem_b), 0); ATF_REQUIRE_EQ(sem_unlink("/sem_b"), 0); } +ATF_TC_CLEANUP(basic, tc) +{ + (void)sem_unlink("/sem_b"); +} -ATF_TC(child); +ATF_TC_WITH_CLEANUP(child); ATF_TC_HEAD(child, tc) { atf_tc_set_md_var(tc, "descr", "Checks using semaphores to synchronize " "parent with multiple child processes"); } ATF_TC_BODY(child, tc) { pid_t children[NCHILDREN]; unsigned i, j; sem_t *sem_a; int status; pid_t pid; - if (sysconf(_SC_SEMAPHORES) == -1) + if (sysconf(_SC_SEMAPHORES) == -1) atf_tc_skip("POSIX semaphores not supported"); sem_a = sem_open("/sem_a", O_CREAT | O_EXCL, 0644, 0); ATF_REQUIRE(sem_a != SEM_FAILED); for (j = 1; j <= 2; j++) { for (i = 0; i < NCHILDREN; i++) { switch ((pid = fork())) { case -1: atf_tc_fail("fork() returned -1"); case 0: printf("PID %d waiting for semaphore...\n", getpid()); ATF_REQUIRE_MSG(sem_wait(sem_a) == 0, "sem_wait failed; iteration %d", j); printf("PID %d got semaphore\n", getpid()); _exit(0); default: children[i] = pid; break; } } for (i = 0; i < NCHILDREN; i++) { sleep(1); printf("main loop %d: posting...\n", j); ATF_REQUIRE_EQ(sem_post(sem_a), 0); } for (i = 0; i < NCHILDREN; i++) { ATF_REQUIRE_EQ(waitpid(children[i], &status, 0), children[i]); ATF_REQUIRE(WIFEXITED(status)); ATF_REQUIRE_EQ(WEXITSTATUS(status), 0); } } ATF_REQUIRE_EQ(sem_close(sem_a), 0); ATF_REQUIRE_EQ(sem_unlink("/sem_a"), 0); +} +ATF_TC_CLEANUP(child, tc) +{ + (void)sem_unlink("/sem_a"); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, basic); ATF_TP_ADD_TC(tp, child); return atf_no_error(); } Index: vendor/NetBSD/tests/dist/usr.bin/grep/d_binary.out =================================================================== --- vendor/NetBSD/tests/dist/usr.bin/grep/d_binary.out (revision 312218) +++ vendor/NetBSD/tests/dist/usr.bin/grep/d_binary.out (revision 312219) @@ -1 +1 @@ -Binary file /bin/sh matches +Binary file test.file matches Index: vendor/NetBSD/tests/dist/usr.bin/grep/t_grep.sh =================================================================== --- vendor/NetBSD/tests/dist/usr.bin/grep/t_grep.sh (revision 312218) +++ vendor/NetBSD/tests/dist/usr.bin/grep/t_grep.sh (revision 312219) @@ -1,246 +1,248 @@ -# $NetBSD: t_grep.sh,v 1.2 2013/05/17 15:39:17 christos Exp $ +# $NetBSD: t_grep.sh,v 1.3 2017/01/14 20:43:52 christos Exp $ # # Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # atf_test_case basic basic_head() { atf_set "descr" "Checks basic functionality" } basic_body() { atf_check -o file:"$(atf_get_srcdir)/d_basic.out" -x \ 'jot 10000 | grep 123' } atf_test_case binary binary_head() { atf_set "descr" "Checks handling of binary files" } binary_body() { - atf_check -o file:"$(atf_get_srcdir)/d_binary.out" grep $(uname) /bin/sh + dd if=/dev/zero count=1 of=test.file + echo -n "foobar" >> test.file + atf_check -o file:"$(atf_get_srcdir)/d_binary.out" grep foobar test.file } atf_test_case recurse recurse_head() { atf_set "descr" "Checks recursive searching" } recurse_body() { mkdir -p recurse/a/f recurse/d echo -e "cod\ndover sole\nhaddock\nhalibut\npilchard" > recurse/d/fish echo -e "cod\nhaddock\nplaice" > recurse/a/f/favourite-fish - atf_check -o file:"$(atf_get_srcdir)/d_recurse.out" grep -r haddock recurse + atf_check -o file:"$(atf_get_srcdir)/d_recurse.out" -x "grep -r haddock recurse | sort" } atf_test_case recurse_symlink recurse_symlink_head() { atf_set "descr" "Checks symbolic link recursion" } recurse_symlink_body() { mkdir -p test/c/d (cd test/c/d && ln -s ../d .) echo "Test string" > test/c/match atf_check -o file:"$(atf_get_srcdir)/d_recurse_symlink.out" \ -e file:"$(atf_get_srcdir)/d_recurse_symlink.err" \ grep -r string test } atf_test_case word_regexps word_regexps_head() { atf_set "descr" "Checks word-regexps" } word_regexps_body() { atf_check -o file:"$(atf_get_srcdir)/d_word_regexps.out" \ grep -w separated $(atf_get_srcdir)/d_input } atf_test_case begin_end begin_end_head() { atf_set "descr" "Checks handling of line beginnings and ends" } begin_end_body() { atf_check -o file:"$(atf_get_srcdir)/d_begin_end_a.out" \ grep ^Front "$(atf_get_srcdir)/d_input" atf_check -o file:"$(atf_get_srcdir)/d_begin_end_b.out" \ grep ending$ "$(atf_get_srcdir)/d_input" } atf_test_case ignore_case ignore_case_head() { atf_set "descr" "Checks ignore-case option" } ignore_case_body() { atf_check -o file:"$(atf_get_srcdir)/d_ignore_case.out" \ grep -i Upper "$(atf_get_srcdir)/d_input" } atf_test_case invert invert_head() { atf_set "descr" "Checks selecting non-matching lines with -v option" } invert_body() { atf_check -o file:"$(atf_get_srcdir)/d_invert.out" \ grep -v fish "$(atf_get_srcdir)/d_invert.in" } atf_test_case whole_line whole_line_head() { atf_set "descr" "Checks whole-line matching with -x flag" } whole_line_body() { atf_check -o file:"$(atf_get_srcdir)/d_whole_line.out" \ grep -x matchme "$(atf_get_srcdir)/d_input" } atf_test_case negative negative_head() { atf_set "descr" "Checks handling of files with no matches" } negative_body() { atf_check -s ne:0 grep "not a hope in hell" "$(atf_get_srcdir)/d_input" } atf_test_case context context_head() { atf_set "descr" "Checks displaying context with -A, -B and -C flags" } context_body() { cp $(atf_get_srcdir)/d_context_*.* . atf_check -o file:d_context_a.out grep -C2 bamboo d_context_a.in atf_check -o file:d_context_b.out grep -A3 tilt d_context_a.in atf_check -o file:d_context_c.out grep -B4 Whig d_context_a.in atf_check -o file:d_context_d.out grep -C1 pig d_context_a.in d_context_b.in } atf_test_case file_exp file_exp_head() { atf_set "descr" "Checks reading expressions from file" } file_exp_body() { atf_check -o file:"$(atf_get_srcdir)/d_file_exp.out" -x \ 'jot 21 -1 1.00 | grep -f '"$(atf_get_srcdir)"'/d_file_exp.in' } atf_test_case egrep egrep_head() { atf_set "descr" "Checks matching special characters with egrep" } egrep_body() { atf_check -o file:"$(atf_get_srcdir)/d_egrep.out" \ egrep '\?|\*$$' "$(atf_get_srcdir)/d_input" } atf_test_case zgrep zgrep_head() { atf_set "descr" "Checks handling of gzipped files with zgrep" } zgrep_body() { cp "$(atf_get_srcdir)/d_input" . gzip d_input || atf_fail "gzip failed" atf_check -o file:"$(atf_get_srcdir)/d_zgrep.out" zgrep -h line d_input.gz } atf_test_case nonexistent nonexistent_head() { atf_set "descr" "Checks that -s flag suppresses error" \ "messages about nonexistent files" } nonexistent_body() { atf_check -s ne:0 grep -s foobar nonexistent } atf_test_case context2 context2_head() { atf_set "descr" "Checks displaying context with -z flag" } context2_body() { printf "haddock\000cod\000plaice\000" > test1 printf "mackeral\000cod\000crab\000" > test2 atf_check -o file:"$(atf_get_srcdir)/d_context2_a.out" \ grep -z -A1 cod test1 test2 atf_check -o file:"$(atf_get_srcdir)/d_context2_b.out" \ grep -z -B1 cod test1 test2 atf_check -o file:"$(atf_get_srcdir)/d_context2_c.out" \ grep -z -C1 cod test1 test2 } atf_init_test_cases() { atf_add_test_case basic atf_add_test_case binary atf_add_test_case recurse atf_add_test_case recurse_symlink atf_add_test_case word_regexps atf_add_test_case begin_end atf_add_test_case ignore_case atf_add_test_case invert atf_add_test_case whole_line atf_add_test_case negative atf_add_test_case context atf_add_test_case file_exp atf_add_test_case egrep atf_add_test_case zgrep atf_add_test_case nonexistent atf_add_test_case context2 } Index: vendor/NetBSD/tests/dist/usr.sbin/mtree/t_mtree.sh =================================================================== --- vendor/NetBSD/tests/dist/usr.sbin/mtree/t_mtree.sh (revision 312218) +++ vendor/NetBSD/tests/dist/usr.sbin/mtree/t_mtree.sh (revision 312219) @@ -1,422 +1,436 @@ -# $NetBSD: t_mtree.sh,v 1.6 2013/02/05 16:49:42 christos Exp $ +# $NetBSD: t_mtree.sh,v 1.7 2017/01/14 20:45:16 christos Exp $ # # Copyright (c) 2009, 2012 The NetBSD Foundation, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Postprocess mtree output, canonicalising portions that # are expected to differ from one run to another. # h_postprocess() { sed -e ' /^# user: /s/:.*/: x/ /^# machine: /s/:.*/: x/ /^# tree: /s/:.*/: x/ /^# date: /s/:.*/: x/ ' \ -e '/type=dir/s/ size=[0-9]*//' } h_check() { diff -Nru "$1" "$2" || atf_fail "files $1 and $2 differ" } atf_test_case mtree_create atf_test_case netbsd6_create create_head() { atf_set "descr" "Create a specfile describing a directory tree" } create_setup() { # create some directories rm -fr create mkdir -p create/a/1 create/a/2 create/b # create some files for file in create/top.file.1 \ create/a/a.file.1 \ create/a/a.file.2 \ create/a/1/a1.file.1 \ create/b/b.file.1 \ create/b/b.file.2 do echo "$file" >$file done # hard link to file in same dir ln create/b/b.file.1 create/b/b.hardlink.1 # hard link to file in another dir ln create/b/b.file.2 create/a/a.hardlink.b2 # symlink to file ln -s a.file.1 create/a.symlink.1 # symlink to dir ln -s b create/top.symlink.b # dangling symlink ln -s nonexistent create/top.dangling } create_body() { create_setup # run mtree and check output ( cd create && mtree -F ${FLAVOR} -c -k type,nlink,link,size,sha256 ) >output.raw \ || atf_fail "mtree exit status $?" h_postprocess output h_check "$(atf_get_srcdir)/${FLAVOR}_d_create.out" output } mtree_create_head() { FLAVOR=mtree create_head } netbsd6_create_head() { FLAVOR=netbsd6 create_head } mtree_create_body() { FLAVOR=mtree create_body } netbsd6_create_body() { FLAVOR=netbsd6 create_body } atf_test_case mtree_check atf_test_case netbsd6_check check_head() { atf_set "descr" "Check a directory tree against a specfile" } check_body() { # we use the same directory tree and specfile as in the "create" test create_setup # run mtree and check output ( cd create && mtree -F ${FLAVOR} ) <"$(atf_get_srcdir)/${FLAVOR}_d_create.out" >output \ || atf_fail "mtree exit status $?" h_check /dev/null output } mtree_check_head() { FLAVOR=mtree check_head } netbsd6_check_head() { FLAVOR=netbsd6 check_head } mtree_check_body() { FLAVOR=mtree check_body } netbsd6_check_body() { FLAVOR=netbsd6 check_body } atf_test_case mtree_convert_C atf_test_case netbsd6_convert_C convert_C_head() { atf_set "descr" "Convert a specfile to mtree -C format, unsorted" } convert_C_body() { mtree -F ${FLAVOR} -C -K all <"$(atf_get_srcdir)/d_convert.in" >output h_check "$(atf_get_srcdir)/d_convert_C.out" output } mtree_convert_C_head() { FLAVOR=mtree convert_C_head } netbsd6_convert_C_head() { FLAVOR=netbsd6 convert_C_head } mtree_convert_C_body() { FLAVOR=mtree convert_C_body } netbsd6_convert_C_body() { FLAVOR=netbsd6 convert_C_body } atf_test_case mtree_convert_C_S atf_test_case netbsd6_convert_C_S convert_C_S_head() { atf_set "descr" "Convert a specfile to mtree -C format, sorted" } convert_C_S_body() { mtree -F ${FLAVOR} -C -S -K all <"$(atf_get_srcdir)/d_convert.in" >output h_check "$(atf_get_srcdir)/d_convert_C_S.out" output } mtree_convert_C_S_head() { FLAVOR=mtree convert_C_S_head } netbsd6_convert_C_S_head() { FLAVOR=netbsd6 convert_C_S_head } mtree_convert_C_S_body() { FLAVOR=mtree convert_C_S_body } netbsd6_convert_C_S_body() { FLAVOR=netbsd6 convert_C_S_body } atf_test_case mtree_convert_D atf_test_case netbsd6_convert_D convert_D_head() { atf_set "descr" "Convert a specfile to mtree -D format, unsorted" } convert_D_body() { mtree -F ${FLAVOR} -D -K all <"$(atf_get_srcdir)/d_convert.in" >output h_check "$(atf_get_srcdir)/d_convert_D.out" output } mtree_convert_D_head() { FLAVOR=mtree convert_D_head } netbsd6_convert_D_head() { FLAVOR=netbsd6 convert_D_head } mtree_convert_D_body() { FLAVOR=mtree convert_D_body } netbsd6_convert_D_body() { FLAVOR=netbsd6 convert_D_body } atf_test_case mtree_convert_D_S atf_test_case netbsd6_convert_D_S convert_D_S_head() { atf_set "descr" "Convert a specfile to mtree -D format, sorted" } convert_D_S_body() { mtree -F ${FLAVOR} -D -S -K all <"$(atf_get_srcdir)/d_convert.in" >output h_check "$(atf_get_srcdir)/d_convert_D_S.out" output } mtree_convert_D_S_head() { FLAVOR=mtree convert_D_S_head } netbsd6_convert_D_S_head() { FLAVOR=netbsd6 convert_D_S_head } mtree_convert_D_S_body() { FLAVOR=mtree convert_D_S_body } netbsd6_convert_D_S_body() { FLAVOR=netbsd6 convert_D_S_body } atf_test_case mtree_ignore atf_test_case netbs6_ignore ignore_head() { atf_set "descr" "Test that -d ignores symlinks (PR bin/41061)" } ignore_body() { + # Kyua 0.11 and above point TMPDIR to our work directory and atf-check + # generates a temporary file, which confuses mtree. Put the mtree files + # into a subdirectory. + # + # See https://github.com/jmmv/kyua/issues/133 for details. + mkdir root && cd root + mkdir newdir mtree -F ${FLAVOR} -c | mtree -F ${FLAVOR} -Ck uid,gid,mode > mtree.spec ln -s newdir otherdir # This yields "extra: otherdir" even with -d. # (PR bin/41061) atf_check -s ignore -o empty -e empty -x "mtree -F ${FLAVOR} -d < mtree.spec" # Delete the symlink and re-verify. # rm otherdir atf_check -s ignore -o empty -e empty -x "mtree -F ${FLAVOR} -d < mtree.spec" } mtree_ignore_head() { FLAVOR=mtree ignore_head } netbsd6_ignore_head() { FLAVOR=netbsd6 ignore_head } mtree_ignore_body() { FLAVOR=mtree ignore_body } netbsd6_ignore_body() { + # Kyua 0.11 and above point TMPDIR to our work directory and atf-check + # generates a temporary file, which confuses mtree. Put the mtree files + # into a subdirectory. + # + # See https://github.com/jmmv/kyua/issues/133 for details. + mkdir root && cd root + FLAVOR=netbsd6 ignore_body } atf_test_case mtree_merge atf_test_case netbsd6_merge merge_head() { atf_set "descr" "Merge records of different type" } merge_body() { mtree -F ${FLAVOR} -C -M -K all <"$(atf_get_srcdir)/d_merge.in" >output h_check "$(atf_get_srcdir)/d_merge_C_M.out" output # same again, with sorting mtree -F ${FLAVOR} -C -M -S -K all <"$(atf_get_srcdir)/d_merge.in" >output h_check "$(atf_get_srcdir)/d_merge_C_M_S.out" output } mtree_merge_head() { FLAVOR=mtree merge_head } netbsd6_merge_head() { FLAVOR=netbsd6 merge_head } mtree_merge_body() { FLAVOR=mtree merge_body } netbsd6_merge_body() { FLAVOR=netbsd6 merge_body } atf_test_case mtree_nonemptydir atf_test_case netbsd6_nonemptydir nonemptydir_head() { atf_set "descr" "Test that new non-empty " \ "directories are recorded (PR bin/25693)" } nonemptydir_body() { mkdir testdir cd testdir mtree -F ${FLAVOR} -c > mtree.spec if [ ! -f mtree.spec ]; then atf_fail "mtree failed" fi touch bar atf_check -s ignore -o save:output -x "mtree -F ${FLAVOR} -f mtree.spec" if [ ! -n "$(egrep "extra: bar" output)" ]; then atf_fail "mtree did not record changes (PR bin/25693)" fi } mtree_nonemptydir_head() { FLAVOR=mtree nonemptydir_head } netbsd6_nonemptydir_head() { FLAVOR=netbsd6 nonemptydir_head } mtree_nonemptydir_body() { FLAVOR=mtree nonemptydir_body } netbsd6_nonemptydir_body() { FLAVOR=netbsd6 nonemptydir_body } atf_init_test_cases() { atf_add_test_case mtree_create atf_add_test_case mtree_check atf_add_test_case mtree_convert_C atf_add_test_case mtree_convert_C_S atf_add_test_case mtree_convert_D atf_add_test_case mtree_convert_D_S atf_add_test_case mtree_ignore atf_add_test_case mtree_merge atf_add_test_case mtree_nonemptydir atf_add_test_case netbsd6_create atf_add_test_case netbsd6_check atf_add_test_case netbsd6_convert_C atf_add_test_case netbsd6_convert_C_S atf_add_test_case netbsd6_convert_D atf_add_test_case netbsd6_convert_D_S atf_add_test_case netbsd6_ignore atf_add_test_case netbsd6_merge atf_add_test_case netbsd6_nonemptydir }