From: "Dmitry V. Levin" <ldv@altlinux.org>
To: Oleg Nesterov <oleg@redhat.com>,
Andy Lutomirski <luto@kernel.org>, Shuah Khan <shuah@kernel.org>
Cc: Elvira Khabirova <lineprinter@altlinux.org>,
Eugene Syromyatnikov <esyr@redhat.com>,
Michael Ellerman <mpe@ellerman.id.au>,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v5 25/25] selftests/ptrace: add a test case for PTRACE_GET_SYSCALL_INFO
Date: Mon, 10 Dec 2018 07:31:33 +0300 [thread overview]
Message-ID: <20181210043133.GY6131@altlinux.org> (raw)
In-Reply-To: <20181210042352.GA6092@altlinux.org>
Check whether PTRACE_GET_SYSCALL_INFO semantics implemented in the kernel
matches userspace expectations.
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Elvira Khabirova <lineprinter@altlinux.org>
Cc: Eugene Syromyatnikov <esyr@redhat.com>
Cc: linux-kselftest@vger.kernel.org
Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
---
tools/testing/selftests/ptrace/.gitignore | 1 +
tools/testing/selftests/ptrace/Makefile | 2 +-
.../selftests/ptrace/get_syscall_info.c | 272 ++++++++++++++++++
3 files changed, 274 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/ptrace/get_syscall_info.c
diff --git a/tools/testing/selftests/ptrace/.gitignore b/tools/testing/selftests/ptrace/.gitignore
index b3e59d41fd82..cfcc49a7def7 100644
--- a/tools/testing/selftests/ptrace/.gitignore
+++ b/tools/testing/selftests/ptrace/.gitignore
@@ -1 +1,2 @@
+get_syscall_info
peeksiginfo
diff --git a/tools/testing/selftests/ptrace/Makefile b/tools/testing/selftests/ptrace/Makefile
index 8a2bc5562179..4bc550b6b845 100644
--- a/tools/testing/selftests/ptrace/Makefile
+++ b/tools/testing/selftests/ptrace/Makefile
@@ -1,5 +1,5 @@
CFLAGS += -iquote../../../../include/uapi -Wall
-TEST_GEN_PROGS := peeksiginfo
+TEST_GEN_PROGS := get_syscall_info peeksiginfo
include ../lib.mk
diff --git a/tools/testing/selftests/ptrace/get_syscall_info.c b/tools/testing/selftests/ptrace/get_syscall_info.c
new file mode 100644
index 000000000000..21d1180d117e
--- /dev/null
+++ b/tools/testing/selftests/ptrace/get_syscall_info.c
@@ -0,0 +1,272 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright (c) 2018 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Check whether PTRACE_GET_SYSCALL_INFO semantics implemented in the kernel
+ * matches userspace expectations.
+ */
+
+#include "../kselftest_harness.h"
+#include <err.h>
+#include <signal.h>
+#include <asm/unistd.h>
+#include "linux/ptrace.h"
+
+static int
+kill_tracee(pid_t pid)
+{
+ if (!pid)
+ return 0;
+
+ int saved_errno = errno;
+
+ int rc = kill(pid, SIGKILL);
+
+ errno = saved_errno;
+ return rc;
+}
+
+static long
+sys_ptrace(int request, pid_t pid, unsigned long addr, unsigned long data)
+{
+ return syscall(__NR_ptrace, request, pid, addr, data);
+}
+
+#define LOG_KILL_TRACEE(fmt, ...) \
+ do { \
+ kill_tracee(pid); \
+ TH_LOG("wait #%d: " fmt, \
+ ptrace_stop, ##__VA_ARGS__); \
+ } while (0)
+
+TEST(get_syscall_info)
+{
+ 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
+ }
+ };
+ const unsigned long *exp_args;
+
+ pid_t pid = fork();
+
+ ASSERT_LE(0, pid) {
+ TH_LOG("fork: %m");
+ }
+
+ if (pid == 0) {
+ /* get the pid before PTRACE_TRACEME */
+ pid = getpid();
+ ASSERT_EQ(0, sys_ptrace(PTRACE_TRACEME, 0, 0, 0)) {
+ TH_LOG("PTRACE_TRACEME: %m");
+ }
+ ASSERT_EQ(0, kill(pid, SIGSTOP)) {
+ /* cannot happen */
+ TH_LOG("kill SIGSTOP: %m");
+ }
+ 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);
+ }
+
+ const struct {
+ unsigned int is_error;
+ int rval;
+ } *exp_param, exit_param[] = {
+ { 1, -ENOENT }, /* chdir */
+ { 0, pid } /* gettid */
+ };
+
+ unsigned int ptrace_stop;
+
+ for (ptrace_stop = 0; ; ++ptrace_stop) {
+ struct ptrace_syscall_info info = {
+ .op = 0xff /* invalid PTRACE_SYSCALL_INFO_* op */
+ };
+ const size_t size = sizeof(info);
+ const int expected_none_size =
+ (void *) &info.entry - (void *) &info;
+ const int expected_entry_size =
+ (void *) &info.entry.args[6] - (void *) &info;
+ const int expected_exit_size =
+ (void *) (&info.exit.is_error + 1) -
+ (void *) &info;
+ int status;
+ long rc;
+
+ ASSERT_EQ(pid, wait(&status)) {
+ /* cannot happen */
+ LOG_KILL_TRACEE("wait: %m");
+ }
+ if (WIFEXITED(status)) {
+ pid = 0; /* the tracee is no more */
+ ASSERT_EQ(0, WEXITSTATUS(status));
+ break;
+ }
+ ASSERT_FALSE(WIFSIGNALED(status)) {
+ pid = 0; /* the tracee is no more */
+ LOG_KILL_TRACEE("unexpected signal %u",
+ WTERMSIG(status));
+ }
+ ASSERT_TRUE(WIFSTOPPED(status)) {
+ /* cannot happen */
+ LOG_KILL_TRACEE("unexpected wait status %#x", status);
+ }
+
+ switch (WSTOPSIG(status)) {
+ case SIGSTOP:
+ ASSERT_EQ(0, ptrace_stop) {
+ LOG_KILL_TRACEE("unexpected signal stop");
+ }
+ ASSERT_EQ(0, sys_ptrace(PTRACE_SETOPTIONS, pid, 0,
+ PTRACE_O_TRACESYSGOOD)) {
+ LOG_KILL_TRACEE("PTRACE_SETOPTIONS: %m");
+ }
+ ASSERT_LT(0, (rc = sys_ptrace(PTRACE_GET_SYSCALL_INFO,
+ pid, size,
+ (unsigned long) &info))) {
+ LOG_KILL_TRACEE("PTRACE_GET_SYSCALL_INFO: %m");
+ }
+ ASSERT_LE(expected_none_size, rc) {
+ LOG_KILL_TRACEE("signal stop mismatch");
+ }
+ ASSERT_EQ(PTRACE_SYSCALL_INFO_NONE, info.op) {
+ LOG_KILL_TRACEE("signal stop mismatch");
+ }
+ ASSERT_TRUE(info.arch) {
+ LOG_KILL_TRACEE("signal stop mismatch");
+ }
+ ASSERT_TRUE(info.instruction_pointer) {
+ LOG_KILL_TRACEE("signal stop mismatch");
+ }
+ ASSERT_TRUE(info.stack_pointer) {
+ LOG_KILL_TRACEE("signal stop mismatch");
+ }
+ break;
+
+ case SIGTRAP | 0x80:
+ ASSERT_LT(0, (rc = sys_ptrace(PTRACE_GET_SYSCALL_INFO,
+ pid, size,
+ (unsigned long) &info))) {
+ LOG_KILL_TRACEE("PTRACE_GET_SYSCALL_INFO: %m");
+ }
+ switch (ptrace_stop) {
+ case 1: /* entering chdir */
+ case 3: /* entering gettid */
+ case 5: /* entering exit_group */
+ exp_args = args[ptrace_stop / 2];
+ ASSERT_LE(expected_entry_size, rc) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_EQ(PTRACE_SYSCALL_INFO_ENTRY, info.op) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_TRUE(info.arch) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_TRUE(info.instruction_pointer) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_TRUE(info.stack_pointer) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_EQ(exp_args[0], info.entry.nr) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_EQ(exp_args[1], info.entry.args[0]) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_EQ(exp_args[2], info.entry.args[1]) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_EQ(exp_args[3], info.entry.args[2]) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_EQ(exp_args[4], info.entry.args[3]) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_EQ(exp_args[5], info.entry.args[4]) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ ASSERT_EQ(exp_args[6], info.entry.args[5]) {
+ LOG_KILL_TRACEE("entry stop mismatch");
+ }
+ break;
+ case 2: /* exiting chdir */
+ case 4: /* exiting gettid */
+ exp_param = &exit_param[ptrace_stop / 2 - 1];
+ ASSERT_LE(expected_exit_size, rc) {
+ LOG_KILL_TRACEE("exit stop mismatch");
+ }
+ ASSERT_EQ(PTRACE_SYSCALL_INFO_EXIT, info.op) {
+ LOG_KILL_TRACEE("exit stop mismatch");
+ }
+ ASSERT_TRUE(info.arch) {
+ LOG_KILL_TRACEE("exit stop mismatch");
+ }
+ ASSERT_TRUE(info.instruction_pointer) {
+ LOG_KILL_TRACEE("exit stop mismatch");
+ }
+ ASSERT_TRUE(info.stack_pointer) {
+ LOG_KILL_TRACEE("exit stop mismatch");
+ }
+ ASSERT_EQ(exp_param->is_error,
+ info.exit.is_error) {
+ LOG_KILL_TRACEE("exit stop mismatch");
+ }
+ ASSERT_EQ(exp_param->rval, info.exit.rval) {
+ LOG_KILL_TRACEE("exit stop mismatch");
+ }
+ break;
+ default:
+ LOG_KILL_TRACEE("unexpected syscall stop");
+ abort();
+ }
+ break;
+
+ default:
+ LOG_KILL_TRACEE("unexpected stop signal %#x",
+ WSTOPSIG(status));
+ abort();
+ }
+
+ ASSERT_EQ(0, sys_ptrace(PTRACE_SYSCALL, pid, 0, 0)) {
+ LOG_KILL_TRACEE("PTRACE_SYSCALL: %m");
+ }
+ }
+
+ ASSERT_EQ(ARRAY_SIZE(args) * 2, ptrace_stop);
+}
+
+TEST_HARNESS_MAIN
--
ldv
prev parent reply other threads:[~2018-12-10 4:31 UTC|newest]
Thread overview: 65+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20181210042352.GA6092@altlinux.org>
2018-12-10 4:27 ` [PATCH v5 01/25] alpha: define remaining syscall_get_* functions Dmitry V. Levin
2018-12-10 4:28 ` [PATCH v5 02/25] Move EM_ARCOMPACT and EM_ARCV2 to uapi/linux/elf-em.h Dmitry V. Levin
2018-12-10 4:29 ` [PATCH v5 03/25] arc: define syscall_get_arch() Dmitry V. Levin
2018-12-10 4:29 ` [PATCH v5 04/25] c6x: " Dmitry V. Levin
2018-12-11 22:40 ` Mark Salter
2018-12-10 4:29 ` [PATCH v5 05/25] elf-em.h: add EM_CSKY Dmitry V. Levin
2018-12-10 4:29 ` [PATCH v5 06/25] csky: define syscall_get_arch() Dmitry V. Levin
2018-12-10 4:29 ` [PATCH v5 07/25] h8300: define remaining syscall_get_* functions Dmitry V. Levin
2018-12-10 4:29 ` [PATCH v5 08/25] Move EM_HEXAGON to uapi/linux/elf-em.h Dmitry V. Levin
2018-12-10 4:29 ` [PATCH v5 09/25] hexagon: define remaining syscall_get_* functions Dmitry V. Levin
2018-12-10 4:29 ` [PATCH v5 10/25] Move EM_NDS32 to uapi/linux/elf-em.h Dmitry V. Levin
2018-12-10 4:29 ` [PATCH v5 11/25] nds32: define syscall_get_arch() Dmitry V. Levin
2018-12-10 4:30 ` [PATCH v5 12/25] nios2: " Dmitry V. Levin
2018-12-10 4:30 ` [PATCH v5 13/25] m68k: add asm/syscall.h Dmitry V. Levin
2018-12-10 8:45 ` Geert Uytterhoeven
2018-12-10 12:40 ` Dmitry V. Levin
2018-12-10 13:06 ` Geert Uytterhoeven
2018-12-10 13:30 ` Dmitry V. Levin
2018-12-12 8:55 ` Dmitry V. Levin
2018-12-12 9:01 ` Geert Uytterhoeven
2018-12-12 9:27 ` Dmitry V. Levin
2018-12-12 9:43 ` Geert Uytterhoeven
2018-12-12 12:04 ` Dmitry V. Levin
2018-12-12 12:27 ` Geert Uytterhoeven
2018-12-12 12:37 ` Dmitry V. Levin
2018-12-12 12:54 ` Geert Uytterhoeven
2018-12-12 13:07 ` Dmitry V. Levin
2018-12-12 23:12 ` Dmitry V. Levin
2019-03-29 22:04 ` Dmitry V. Levin
2019-03-30 20:57 ` Geert Uytterhoeven
2018-12-10 4:30 ` [PATCH v5 14/25] mips: define syscall_get_error() Dmitry V. Levin
2018-12-10 4:30 ` [PATCH v5 15/25] parisc: " Dmitry V. Levin
2018-12-10 4:30 ` [PATCH v5 16/25] powerpc: " Dmitry V. Levin
2018-12-10 4:30 ` [PATCH v5 17/25] riscv: define syscall_get_arch() Dmitry V. Levin
2018-12-10 4:30 ` [PATCH v5 18/25] Move EM_XTENSA to uapi/linux/elf-em.h Dmitry V. Levin
2018-12-10 4:30 ` [PATCH v5 19/25] xtensa: define syscall_get_* functions Dmitry V. Levin
2018-12-10 5:02 ` Max Filippov
2018-12-10 12:53 ` Dmitry V. Levin
2018-12-10 20:14 ` Max Filippov
2018-12-10 20:24 ` Dmitry V. Levin
2018-12-10 20:30 ` Dmitry V. Levin
2018-12-10 21:29 ` Max Filippov
2018-12-12 10:45 ` kbuild test robot
2018-12-19 5:58 ` kbuild test robot
2018-12-10 4:30 ` [PATCH v5 20/25] Move EM_UNICORE to uapi/linux/elf-em.h Dmitry V. Levin
2018-12-10 4:30 ` [PATCH v5 21/25] unicore32: add asm/syscall.h Dmitry V. Levin
2018-12-10 4:31 ` [PATCH v5 22/25] syscall_get_arch: add "struct task_struct *" argument Dmitry V. Levin
2018-12-10 17:29 ` Kees Cook
2018-12-11 22:44 ` Mark Salter
2018-12-10 4:31 ` [PATCH v5 23/25] powerpc/ptrace: replace ptrace_report_syscall() with a tracehook call Dmitry V. Levin
2018-12-10 4:31 ` [PATCH v5 24/25] ptrace: add PTRACE_GET_SYSCALL_INFO request Dmitry V. Levin
2018-12-10 14:11 ` Oleg Nesterov
2018-12-10 16:21 ` Dmitry V. Levin
2018-12-11 15:29 ` Oleg Nesterov
2018-12-11 16:23 ` Dmitry V. Levin
2018-12-11 20:27 ` Dmitry V. Levin
2018-12-12 18:00 ` Oleg Nesterov
2018-12-10 14:26 ` kbuild test robot
2018-12-10 16:09 ` Dmitry V. Levin
2018-12-10 18:04 ` Paul Burton
2018-12-10 21:04 ` Palmer Dabbelt
2018-12-10 19:38 ` Andy Lutomirski
2018-12-10 17:44 ` Kees Cook
2018-12-12 9:28 ` kbuild test robot
2018-12-10 4:31 ` Dmitry V. Levin [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181210043133.GY6131@altlinux.org \
--to=ldv@altlinux.org \
--cc=esyr@redhat.com \
--cc=lineprinter@altlinux.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mpe@ellerman.id.au \
--cc=oleg@redhat.com \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome