Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/tests/kernel Add {, io_}read_i[1234] in t_ptrace_wait{, 3, 4, 6, ...



details:   https://anonhg.NetBSD.org/src/rev/e1f0876caaef
branches:  trunk
changeset: 819235:e1f0876caaef
user:      kamil <kamil%NetBSD.org@localhost>
date:      Wed Nov 23 23:30:50 2016 +0000

description:
Add {,io_}read_i[1234] in t_ptrace_wait{,3,4,6,id,pid}

New tests are direct counterparts to the existing ones {,io_}read_d[1234].

PT_READ_D and PIOD_READ_D (from PT_IO) are traditionally used to transfer
data segment. New tests make use of PT_READ_I and PIOD_READ_I (from PT_IO)
in order to copy text segment from traced process.

    Traditionally, ptrace() has
    allowed for machines with distinct address spaces for
    instruction and data, which is why there are two requests:
    conceptually, PT_READ_I reads from the instruction space
    and PT_READ_D reads from the data space.  In the current
    NetBSD implementation, these two requests are completely
    identical.

    --- ptrace(2)

New tests follow the traditional convention and copy only instructions from
dummy functions.

There are no new tests copying data to .text regions from the traced
process, as this is violating mprotect restrictions. This limitation may be
addressed in future, as there are dedicated sysctl(7) handlers for
debuggers (currently mainly gdb(1)).

Tests verifying identical behavior of PT_READ_I and PT_READ_D are not
planned.

Sponsored by <The NetBSD Foundation>

diffstat:

 tests/kernel/t_ptrace_wait.c |  631 ++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 629 insertions(+), 2 deletions(-)

diffs (truncated from 658 to 300 lines):

diff -r c96cbb31e6d4 -r e1f0876caaef tests/kernel/t_ptrace_wait.c
--- a/tests/kernel/t_ptrace_wait.c      Wed Nov 23 21:18:12 2016 +0000
+++ b/tests/kernel/t_ptrace_wait.c      Wed Nov 23 23:30:50 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: t_ptrace_wait.c,v 1.26 2016/11/23 21:14:23 kamil Exp $ */
+/*     $NetBSD: t_ptrace_wait.c,v 1.27 2016/11/23 23:30:50 kamil Exp $ */
 
 /*-
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: t_ptrace_wait.c,v 1.26 2016/11/23 21:14:23 kamil Exp $");
+__RCSID("$NetBSD: t_ptrace_wait.c,v 1.27 2016/11/23 23:30:50 kamil Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -3425,6 +3425,623 @@
        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());
+       child = atf_utils_fork();
+       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());
+       child = atf_utils_fork();
+       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());
+       child = atf_utils_fork();
+       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());
+       child = atf_utils_fork();
+       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);
+       }



Home | Main Index | Thread Index | Old Index