]> granicus.if.org Git - strace/commitdiff
Implement PTRACE_GET_SYSCALL_INFO decoder
authorDmitry V. Levin <ldv@altlinux.org>
Thu, 13 Dec 2018 22:07:26 +0000 (22:07 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 13 Dec 2018 22:07:26 +0000 (22:07 +0000)
* defs.h (audit_arch): New prototype.
* process.c: Include "ptrace_syscall_info.h".
(SYS_FUNC(ptrace)) <PTRACE_GET_SYSCALL_INFO>: Call
print_ptrace_syscall_info on exiting syscall.
* ptrace_syscall_info.h (print_ptrace_syscall_info): New prototype.
* ptrace_syscall_info.c: Include "print_fields.h" and
"xlat/ptrace_syscall_info_op.h".
(print_ptrace_syscall_info): New function.
* xlat/ptrace_syscall_info_op.in: New file.
* tests/ptrace_syscall_info.c: New file.
* tests/gen_tests.in (ptrace_syscall_info): New test.
* tests/pure_executables.list: Add ptrace_syscall_info.
* tests/.gitignore: Likewise.

defs.h
process.c
ptrace_syscall_info.c
ptrace_syscall_info.h
tests/.gitignore
tests/gen_tests.in
tests/ptrace_syscall_info.c [new file with mode: 0644]
tests/pure_executables.list
xlat/ptrace_syscall_info_op.in [new file with mode: 0644]

diff --git a/defs.h b/defs.h
index 389e4486746967833b760db9f502425849632e36..15f84991b48e7e63d6803a0e996916e2b4c5c25d 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -312,6 +312,7 @@ extern const struct xlat evdev_abs[];
 /** Number of elements in evdev_abs array without the terminating record. */
 extern const size_t evdev_abs_size;
 
+extern const struct xlat audit_arch[];
 extern const struct xlat evdev_ev[];
 extern const struct xlat iffflags[];
 extern const struct xlat ip_type_of_services[];
index 04b2a11427fa23ac01ca4845dda2e37933215a38..3e57295d54d487874d651d7a32620030f82120bc 100644 (file)
--- a/process.c
+++ b/process.c
@@ -22,6 +22,7 @@
 #endif
 
 #include "ptrace.h"
+#include "ptrace_syscall_info.h"
 #include "regs.h"
 
 #include "xlat/nt_descriptor_types.h"
@@ -220,6 +221,7 @@ SYS_FUNC(ptrace)
                case PTRACE_GETSIGMASK:
                case PTRACE_PEEKSIGINFO:
                case PTRACE_SECCOMP_GET_FILTER:
+               case PTRACE_GET_SYSCALL_INFO:
                        if (verbose(tcp)) {
                                /* print data on exiting syscall */
                                return 0;
@@ -283,7 +285,11 @@ SYS_FUNC(ptrace)
                                tprints(", ...");
 
                        tprints("}");
+                       break;
                }
+               case PTRACE_GET_SYSCALL_INFO:
+                       print_ptrace_syscall_info(tcp, data, addr);
+                       break;
                }
        }
        return 0;
index 9f884e4ae9dcdf56b3075bd004586983482eea71..55eafddf7f71587b30c816e754cd0c9ba5900959 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "defs.h"
 #include "kill_save_errno.h"
+#include "print_fields.h"
 #include "ptrace.h"
 #include "ptrace_syscall_info.h"
 #include "scno.h"
@@ -14,6 +15,8 @@
 #include <signal.h>
 #include <sys/wait.h>
 
+#include "xlat/ptrace_syscall_info_op.h"
+
 bool ptrace_get_syscall_info_supported;
 
 static int
@@ -30,6 +33,8 @@ static const unsigned int expected_entry_size =
        offsetofend(struct ptrace_syscall_info, entry.args);
 static const unsigned int expected_exit_size =
        offsetofend(struct ptrace_syscall_info, exit.is_error);
+static const unsigned int expected_seccomp_size =
+       offsetofend(struct ptrace_syscall_info, seccomp.ret_data);
 
 /*
  * Test that PTRACE_GET_SYSCALL_INFO API is supported by the kernel, and
@@ -250,3 +255,84 @@ done:
 
        return ptrace_get_syscall_info_supported;
 }
+
+void
+print_ptrace_syscall_info(struct tcb *tcp, kernel_ulong_t addr,
+                         kernel_ulong_t user_len)
+{
+       struct ptrace_syscall_info info;
+       kernel_ulong_t kernel_len = tcp->u_rval;
+       kernel_ulong_t ret_len = MIN(user_len, kernel_len);
+       kernel_ulong_t fetch_size = MIN(ret_len, expected_seccomp_size);
+
+       if (!fetch_size || !tfetch_mem(tcp, addr, fetch_size, &info)) {
+               printaddr(addr);
+               return;
+       }
+
+       PRINT_FIELD_XVAL_INDEX("{", info, op, ptrace_syscall_info_op,
+                              "PTRACE_SYSCALL_INFO_???");
+       if (fetch_size < offsetofend(struct ptrace_syscall_info, arch))
+               goto printed;
+       PRINT_FIELD_XVAL(", ", info, arch, audit_arch, "AUDIT_ARCH_???");
+
+       if (fetch_size < offsetofend(struct ptrace_syscall_info,
+                                    instruction_pointer))
+               goto printed;
+       PRINT_FIELD_ADDR64(", ", info, instruction_pointer);
+
+       if (fetch_size < offsetofend(struct ptrace_syscall_info, stack_pointer))
+               goto printed;
+       PRINT_FIELD_ADDR64(", ", info, stack_pointer);
+
+       if (fetch_size < offsetofend(struct ptrace_syscall_info, entry.nr))
+               goto printed;
+
+       switch(info.op) {
+               case PTRACE_SYSCALL_INFO_ENTRY:
+               case PTRACE_SYSCALL_INFO_SECCOMP:
+                       PRINT_FIELD_U((info.op == PTRACE_SYSCALL_INFO_ENTRY
+                                      ? ", entry={" : ", seccomp={"),
+                                     info.entry, nr);
+                       for (unsigned int i = 0;
+                            i < ARRAY_SIZE(info.entry.args); ++i) {
+                               const unsigned int i_size =
+                                       offsetofend(struct ptrace_syscall_info,
+                                                   entry.args[i]);
+                               if (fetch_size < i_size) {
+                                       if (i)
+                                               break;
+                                       goto entry_printed;
+                               }
+                               tprintf(", %s%#" PRIx64,
+                                       (i ? "" : "arg=["),
+                                       (uint64_t) info.entry.args[i]);
+                       }
+                       tprints("]");
+                       if (info.op == PTRACE_SYSCALL_INFO_SECCOMP
+                           && fetch_size >= expected_seccomp_size)
+                               PRINT_FIELD_U(", ", info.seccomp, ret_data);
+entry_printed:
+                       tprints("}");
+                       break;
+               case PTRACE_SYSCALL_INFO_EXIT:
+                       tprints(", exit={");
+                       if (fetch_size >= expected_exit_size
+                           && info.exit.is_error) {
+                               uint64_t err = -info.exit.rval;
+
+                               tprints("rval=-");
+                               print_xlat_ex(err, err_name(err),
+                                             XLAT_STYLE_FMT_U);
+                       } else {
+                               PRINT_FIELD_D("", info.exit, rval);
+                       }
+                       if (fetch_size >= expected_exit_size)
+                               PRINT_FIELD_U(", ", info.exit, is_error);
+                       tprints("}");
+                       break;
+       }
+
+printed:
+       tprints("}");
+}
index 25850f8a815ff3152efb5a3f7998bc668c3e5033..3bbafc28fe554188e9f45407df0aff28f20743ef 100644 (file)
@@ -10,5 +10,7 @@
 
 extern bool ptrace_get_syscall_info_supported;
 extern bool test_ptrace_get_syscall_info(void);
+extern void print_ptrace_syscall_info(struct tcb *, kernel_ulong_t addr,
+                                     kernel_ulong_t len);
 
 #endif /* !STRACE_PTRACE_SYSCALL_INFO_H */
index c9dbabb81e736b707529652ab4da15e7ac59f87b..e25d4f920c3caf48cc582483bb0c98dc0e9e7cc2 100644 (file)
@@ -400,6 +400,7 @@ process_vm_readv
 process_vm_writev
 pselect6
 ptrace
+ptrace_syscall_info
 pure_executables.am
 pwritev
 qual_fault
index 31a06274f4b2936433c06c93c77b33c66a7f584f..31443ffdf28188206e0958024f80266ea4db4f04 100644 (file)
@@ -332,6 +332,7 @@ process_vm_readv    -s5 -a37
 process_vm_writev      -s5 -a38
 pselect6
 ptrace -a23 -e signal=none
+ptrace_syscall_info    -a35 -e signal=none -e trace=ptrace
 pwritev        -a22 -s7
 quotactl
 quotactl-v     -v -e trace=quotactl
diff --git a/tests/ptrace_syscall_info.c b/tests/ptrace_syscall_info.c
new file mode 100644 (file)
index 0000000..ea29d22
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * Check decoding of ptrace PTRACE_GET_SYSCALL_INFO request.
+ *
+ * Copyright (c) 2018 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+
+#include "ptrace.h"
+#include <asm/unistd.h>
+#include "scno.h"
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <linux/audit.h>
+
+#include "xlat.h"
+#include "xlat/audit_arch.h"
+
+static const char *errstr;
+
+static long
+do_ptrace(unsigned long request, unsigned long pid,
+         unsigned long addr, unsigned long data)
+{
+       long rc = syscall(__NR_ptrace, request, pid, addr, data);
+       errstr = sprintrc(rc);
+       return rc;
+}
+
+static pid_t pid;
+
+static void
+kill_tracee(void)
+{
+       if (!pid)
+               return;
+       int saved_errno = errno;
+       kill(pid, SIGKILL);
+       errno = saved_errno;
+}
+
+#define FAIL(fmt_, ...)                                                        \
+       do {                                                            \
+               kill_tracee();                                          \
+               error_msg_and_fail("%s:%d: " fmt_,                      \
+                                  __FILE__, __LINE__, ##__VA_ARGS__);  \
+       } while (0)
+
+#define PFAIL(fmt_, ...)                                               \
+       do {                                                            \
+               kill_tracee();                                          \
+               perror_msg_and_fail("%s:%d: " fmt_,                     \
+                                   __FILE__, __LINE__, ##__VA_ARGS__); \
+       } while (0)
+
+static const unsigned long args[][7] = {
+       /* a sequence of architecture-agnostic syscalls */
+       {
+               __NR_chdir,
+               (unsigned long) "",
+               0xbad1fed1,
+               0xbad2fed2,
+               0xbad3fed3,
+               0xbad4fed4,
+               0xbad5fed5
+       },
+       {
+               __NR_gettid,
+               0xcaf0bea0,
+               0xcaf1bea1,
+               0xcaf2bea2,
+               0xcaf3bea3,
+               0xcaf4bea4,
+               0xcaf5bea5
+       },
+       {
+               __NR_exit_group,
+               0,
+               0xfac1c0d1,
+               0xfac2c0d2,
+               0xfac3c0d3,
+               0xfac4c0d4,
+               0xfac5c0d5
+       }
+};
+
+static const unsigned int expected_none_size =
+       offsetof(struct ptrace_syscall_info, entry);
+static const unsigned int expected_entry_size =
+       offsetofend(struct ptrace_syscall_info, entry.args);
+static const unsigned int expected_exit_size =
+       offsetofend(struct ptrace_syscall_info, exit.is_error);
+
+static unsigned long end_of_page;
+static unsigned int ptrace_stop;
+
+static bool
+test_none(void)
+{
+       do_ptrace(PTRACE_GET_SYSCALL_INFO, pid, 1, 0);
+       printf("ptrace(PTRACE_GET_SYSCALL_INFO, %d, 1, NULL) = %s\n",
+              pid, errstr);
+
+       do_ptrace(PTRACE_GET_SYSCALL_INFO, pid, 1, end_of_page);
+       printf("ptrace(PTRACE_GET_SYSCALL_INFO, %d, 1, %#lx) = %s\n",
+              pid, end_of_page, errstr);
+
+       for (unsigned int size = 0;
+            size <= sizeof(struct ptrace_syscall_info); ++size) {
+               unsigned long buf = end_of_page - size;
+               memset((void *) buf, -1, size);
+
+               long rc = do_ptrace(PTRACE_GET_SYSCALL_INFO, pid, size, buf);
+               if (rc < 0) {
+                       printf("ptrace(PTRACE_GET_SYSCALL_INFO, %d, %u, %#lx)"
+                              " = %s\n",
+                              pid, (unsigned int) size, buf, errstr);
+                       return false;
+               }
+               if (rc < (long) expected_none_size)
+                       FAIL("signal stop mismatch");
+
+               printf("ptrace(PTRACE_GET_SYSCALL_INFO, %d, %u, ",
+                      pid, size);
+               if (!size) {
+                       printf("%#lx) = %s\n", buf, errstr);
+                       continue;
+               }
+
+               /* copy to a local structure to avoid unaligned access */
+               struct ptrace_syscall_info info;
+               memcpy(&info, (void *) buf,  MIN(size, expected_none_size));
+
+               if (info.op != PTRACE_SYSCALL_INFO_NONE)
+                       FAIL("signal stop mismatch");
+               printf("{op=PTRACE_SYSCALL_INFO_NONE");
+
+               if (size < offsetofend(struct ptrace_syscall_info, arch))
+                       goto printed_none;
+               if (!info.arch)
+                       FAIL("signal stop mismatch");
+               printf(", arch=");
+               printxval(audit_arch, info.arch, "AUDIT_ARCH_???");
+
+               if (size < offsetofend(struct ptrace_syscall_info,
+                                      instruction_pointer))
+                       goto printed_none;
+               if (!info.instruction_pointer)
+                       FAIL("signal stop mismatch");
+               printf(", instruction_pointer=%#llx",
+                      (unsigned long long) info.instruction_pointer);
+
+               if (size < offsetofend(struct ptrace_syscall_info,
+                                      stack_pointer))
+                       goto printed_none;
+               if (!info.stack_pointer)
+                       FAIL("signal stop mismatch");
+               printf(", stack_pointer=%#llx",
+                      (unsigned long long) info.stack_pointer);
+
+printed_none:
+               printf("}) = %s\n", errstr);
+       }
+
+       return true;
+}
+
+static void
+test_entry(void)
+{
+       for (unsigned int size = 0;
+            size <= sizeof(struct ptrace_syscall_info); ++size) {
+               unsigned long buf = end_of_page - size;
+               memset((void *) buf, -1, size);
+
+               long rc = do_ptrace(PTRACE_GET_SYSCALL_INFO, pid, size, buf);
+               if (rc < 0)
+                       PFAIL("PTRACE_GET_SYSCALL_INFO");
+
+               if (rc < (long) expected_entry_size)
+                       FAIL("#%d: entry stop mismatch", ptrace_stop);
+
+               printf("ptrace(PTRACE_GET_SYSCALL_INFO, %d, %u, ",
+                      pid, size);
+               if (!size) {
+                       printf("%#lx) = %s\n", buf, errstr);
+                       continue;
+               }
+
+               /* copy to a local structure to avoid unaligned access */
+               struct ptrace_syscall_info info;
+               memcpy(&info, (void *) buf,  MIN(size, expected_entry_size));
+
+               if (info.op != PTRACE_SYSCALL_INFO_ENTRY)
+                       FAIL("#%d: entry stop mismatch", ptrace_stop);
+               printf("{op=PTRACE_SYSCALL_INFO_ENTRY");
+
+               if (size < offsetofend(struct ptrace_syscall_info, arch))
+                       goto printed_entry_common;
+               if (!info.arch)
+                       FAIL("#%d: entry stop mismatch", ptrace_stop);
+               printf(", arch=");
+               printxval(audit_arch, info.arch, "AUDIT_ARCH_???");
+
+               if (size < offsetofend(struct ptrace_syscall_info,
+                                      instruction_pointer))
+                       goto printed_entry_common;
+               if (!info.instruction_pointer)
+                       FAIL("#%d: entry stop mismatch", ptrace_stop);
+               printf(", instruction_pointer=%#llx",
+                      (unsigned long long) info.instruction_pointer);
+
+               if (size < offsetofend(struct ptrace_syscall_info,
+                                      stack_pointer))
+                       goto printed_entry_common;
+               if (!info.stack_pointer)
+                       FAIL("#%d: entry stop mismatch", ptrace_stop);
+               printf(", stack_pointer=%#llx",
+                      (unsigned long long) info.stack_pointer);
+
+               if (size < offsetofend(struct ptrace_syscall_info, entry.nr))
+                       goto printed_entry_common;
+               const unsigned long *exp_args = args[ptrace_stop / 2];
+               if (info.entry.nr != exp_args[0])
+                       FAIL("#%d: entry stop mismatch", ptrace_stop);
+               printf(", entry={nr=%llu", (unsigned long long) info.entry.nr);
+
+               for (unsigned int i = 0; i < ARRAY_SIZE(info.entry.args); ++i) {
+                       const unsigned int i_size =
+                               offsetofend(struct ptrace_syscall_info,
+                                           entry.args[i]);
+                       if (size < i_size) {
+                               if (i)
+                                       break;
+                               goto printed_entry_nr;
+                       }
+                       if (info.entry.args[i] != exp_args[i + 1])
+                               FAIL("#%d: entry stop mismatch", ptrace_stop);
+                       printf("%s%#llx", (i ? ", " : ", arg=["),
+                              (unsigned long long) info.entry.args[i]);
+               }
+               printf("]");
+
+printed_entry_nr:
+               printf("}");
+
+printed_entry_common:
+               printf("}) = %s\n", errstr);
+       }
+}
+
+static void
+test_exit(void)
+{
+       for (unsigned int size = 0;
+            size <= sizeof(struct ptrace_syscall_info); ++size) {
+               unsigned long buf = end_of_page - size;
+               memset((void *) buf, -1, size);
+
+               long rc = do_ptrace(PTRACE_GET_SYSCALL_INFO, pid, size, buf);
+               if (rc < 0)
+                       PFAIL("PTRACE_GET_SYSCALL_INFO");
+
+               if (rc < (long) expected_exit_size)
+                       FAIL("#%d: exit stop mismatch", ptrace_stop);
+
+               printf("ptrace(PTRACE_GET_SYSCALL_INFO, %d, %u, ",
+                      pid, size);
+               if (!size) {
+                       printf("%#lx) = %s\n", buf, errstr);
+                       continue;
+               }
+
+               /* copy to a local structure to avoid unaligned access */
+               struct ptrace_syscall_info info;
+               memcpy(&info, (void *) buf,  MIN(size, expected_exit_size));
+
+               if (info.op != PTRACE_SYSCALL_INFO_EXIT)
+                       FAIL("#%d: exit stop mismatch", ptrace_stop);
+               printf("{op=PTRACE_SYSCALL_INFO_EXIT");
+
+               if (size < offsetofend(struct ptrace_syscall_info, arch))
+                       goto printed_exit_common;
+               if (!info.arch)
+                       FAIL("#%d: exit stop mismatch", ptrace_stop);
+               printf(", arch=");
+               printxval(audit_arch, info.arch, "AUDIT_ARCH_???");
+
+               if (size < offsetofend(struct ptrace_syscall_info,
+                                      instruction_pointer))
+                       goto printed_exit_common;
+               if (!info.instruction_pointer)
+                       FAIL("#%d: exit stop mismatch", ptrace_stop);
+               printf(", instruction_pointer=%#llx",
+                      (unsigned long long) info.instruction_pointer);
+
+               if (size < offsetofend(struct ptrace_syscall_info,
+                                      stack_pointer))
+                       goto printed_exit_common;
+               if (!info.stack_pointer)
+                       FAIL("#%d: exit stop mismatch", ptrace_stop);
+               printf(", stack_pointer=%#llx",
+                      (unsigned long long) info.stack_pointer);
+
+               const struct {
+                       unsigned int is_error;
+                       int rval;
+                       const char *str;
+               } exit_param[] = {
+                       { 1, -ENOENT, "-ENOENT" },      /* chdir */
+                       { 0, pid, NULL }                /* gettid */
+               }, *exp_param = &exit_param[ptrace_stop / 2 - 1];
+
+               if (size < offsetofend(struct ptrace_syscall_info, exit.rval))
+                       goto printed_exit_common;
+               if (info.exit.rval != exp_param->rval)
+                       FAIL("#%d: exit stop mismatch", ptrace_stop);
+               if (size >= expected_exit_size && info.exit.is_error) {
+                       printf(", exit={rval=%s", exp_param->str);
+               } else {
+                       printf(", exit={rval=%lld", (long long) info.exit.rval);
+               }
+
+               if (size >= expected_exit_size) {
+                       if (info.exit.is_error != exp_param->is_error)
+                               FAIL("#%d: exit stop mismatch", ptrace_stop);
+                       printf(", is_error=%u",
+                              (unsigned int) info.exit.is_error);
+               }
+
+               printf("}");
+
+printed_exit_common:
+               printf("}) = %s\n", errstr);
+       }
+}
+
+int
+main(void)
+{
+       end_of_page = (unsigned long) tail_alloc(1) + 1;
+
+       pid = getpid();
+       do_ptrace(PTRACE_GET_SYSCALL_INFO, pid, 0, 0);
+       printf("ptrace(PTRACE_GET_SYSCALL_INFO, %d, 0, NULL) = %s\n",
+              pid, errstr);
+
+       pid = fork();
+       if (pid < 0)
+               PFAIL("fork");
+
+       if (pid == 0) {
+               /* get the pid before PTRACE_TRACEME */
+               pid = getpid();
+               if (do_ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
+                       /* exit with a nonzero exit status */
+                       PFAIL("PTRACE_TRACEME");
+               }
+               kill(pid, SIGSTOP);
+               for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) {
+                       syscall(args[i][0],
+                               args[i][1], args[i][2], args[i][3],
+                               args[i][4], args[i][5], args[i][6]);
+               }
+               /* unreachable */
+               _exit(1);
+       }
+
+       for (ptrace_stop = 0; ; ++ptrace_stop) {
+               int status;
+               long rc = waitpid(pid, &status, 0);
+               if (rc != pid) {
+                       /* cannot happen */
+                       PFAIL("#%d: unexpected wait result %ld",
+                                           ptrace_stop, rc);
+               }
+               if (WIFEXITED(status)) {
+                       /* tracee is no more */
+                       pid = 0;
+                       if (WEXITSTATUS(status) == 0)
+                               break;
+                       FAIL("#%d: unexpected exit status %u",
+                            ptrace_stop, WEXITSTATUS(status));
+               }
+               if (WIFSIGNALED(status)) {
+                       /* tracee is no more */
+                       pid = 0;
+                       FAIL("#%d: unexpected signal %u",
+                            ptrace_stop, WTERMSIG(status));
+               }
+               if (!WIFSTOPPED(status)) {
+                       /* cannot happen */
+                       FAIL("#%d: unexpected wait status %#x",
+                            ptrace_stop, status);
+               }
+
+               switch (WSTOPSIG(status)) {
+               case SIGSTOP:
+                       if (ptrace_stop)
+                               FAIL("#%d: unexpected signal stop",
+                                              ptrace_stop);
+                       if (do_ptrace(PTRACE_SETOPTIONS, pid, 0,
+                                  PTRACE_O_TRACESYSGOOD) < 0) {
+                               /* cannot happen */
+                               PFAIL("PTRACE_SETOPTIONS");
+                       }
+                       printf("ptrace(PTRACE_SETOPTIONS, %d, NULL"
+                              ", PTRACE_O_TRACESYSGOOD) = 0\n", pid);
+
+                       if (!test_none())
+                               goto done;
+                       break;
+
+               case SIGTRAP | 0x80:
+                       switch (ptrace_stop) {
+                       case 1: /* entering chdir */
+                       case 3: /* entering gettid */
+                       case 5: /* entering exit_group */
+                               test_entry();
+                               break;
+                       case 2: /* exiting chdir */
+                       case 4: /* exiting gettid */
+                               test_exit();
+                               break;
+                       default:
+                               FAIL("#%d: unexpected syscall stop",
+                                    ptrace_stop);
+                       }
+                       break;
+
+               default:
+                       FAIL("#%d: unexpected stop signal %#x",
+                            ptrace_stop, WSTOPSIG(status));
+               }
+
+               if (do_ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
+                       /* cannot happen */
+                       PFAIL("PTRACE_SYSCALL");
+               }
+               printf("ptrace(PTRACE_SYSCALL, %d, NULL, 0) = 0\n", pid);
+       }
+
+done:
+       if (pid) {
+               kill_tracee();
+               waitpid(pid, NULL, 0);
+       }
+
+       puts("+++ exited with 0 +++");
+       return 0;
+}
index c1ac75ed52bae8b31f3542e6e02c7a5b27fc2301..2c6eabd74fe63dab9a02a0ffbd2b76f6d845000b 100755 (executable)
@@ -336,6 +336,7 @@ process_vm_readv
 process_vm_writev
 pselect6
 ptrace
+ptrace_syscall_info
 pwritev
 quotactl
 quotactl-xfs
diff --git a/xlat/ptrace_syscall_info_op.in b/xlat/ptrace_syscall_info_op.in
new file mode 100644 (file)
index 0000000..96e7620
--- /dev/null
@@ -0,0 +1,5 @@
+#value_indexed
+PTRACE_SYSCALL_INFO_NONE
+PTRACE_SYSCALL_INFO_ENTRY
+PTRACE_SYSCALL_INFO_EXIT
+PTRACE_SYSCALL_INFO_SECCOMP