selftest, ptrace: Add selftest for syscall user dispatch config api
authorGregory Price <gourry.memverge@gmail.com>
Fri, 7 Apr 2023 17:18:34 +0000 (13:18 -0400)
committerThomas Gleixner <tglx@linutronix.de>
Sun, 16 Apr 2023 12:23:08 +0000 (14:23 +0200)
Validate that the following new ptrace requests work as expected

 * PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG
   returns the contents of task->syscall_dispatch

 * PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG
   sets the contents of task->syscall_dispatch

Signed-off-by: Gregory Price <gregory.price@memverge.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20230407171834.3558-5-gregory.price@memverge.com
tools/testing/selftests/ptrace/.gitignore
tools/testing/selftests/ptrace/Makefile
tools/testing/selftests/ptrace/get_set_sud.c [new file with mode: 0644]

index 792318aaa30cd209c9269f71e4d34e8ddc22e592..b7dde152e75a9a2f75bfa1961117d2d9bb775824 100644 (file)
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 get_syscall_info
+get_set_sud
 peeksiginfo
 vmaccess
index 96ffa94afb9136237649b019a20a44a628b4654a..1c631740a730af922ddfe8363aff7fb4948bf55b 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 CFLAGS += -std=c99 -pthread -Wall $(KHDR_INCLUDES)
 
-TEST_GEN_PROGS := get_syscall_info peeksiginfo vmaccess
+TEST_GEN_PROGS := get_syscall_info peeksiginfo vmaccess get_set_sud
 
 include ../lib.mk
diff --git a/tools/testing/selftests/ptrace/get_set_sud.c b/tools/testing/selftests/ptrace/get_set_sud.c
new file mode 100644 (file)
index 0000000..5297b10
--- /dev/null
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include "../kselftest_harness.h"
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#include <sys/prctl.h>
+
+#include "linux/ptrace.h"
+
+static int sys_ptrace(int request, pid_t pid, void *addr, void *data)
+{
+       return syscall(SYS_ptrace, request, pid, addr, data);
+}
+
+TEST(get_set_sud)
+{
+       struct ptrace_sud_config config;
+       pid_t child;
+       int ret = 0;
+       int status;
+
+       child = fork();
+       ASSERT_GE(child, 0);
+       if (child == 0) {
+               ASSERT_EQ(0, sys_ptrace(PTRACE_TRACEME, 0, 0, 0)) {
+                       TH_LOG("PTRACE_TRACEME: %m");
+               }
+               kill(getpid(), SIGSTOP);
+               _exit(1);
+       }
+
+       waitpid(child, &status, 0);
+
+       memset(&config, 0xff, sizeof(config));
+       config.mode = PR_SYS_DISPATCH_ON;
+
+       ret = sys_ptrace(PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, child,
+                        (void *)sizeof(config), &config);
+
+       ASSERT_EQ(ret, 0);
+       ASSERT_EQ(config.mode, PR_SYS_DISPATCH_OFF);
+       ASSERT_EQ(config.selector, 0);
+       ASSERT_EQ(config.offset, 0);
+       ASSERT_EQ(config.len, 0);
+
+       config.mode = PR_SYS_DISPATCH_ON;
+       config.selector = 0;
+       config.offset = 0x400000;
+       config.len = 0x1000;
+
+       ret = sys_ptrace(PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG, child,
+                        (void *)sizeof(config), &config);
+
+       ASSERT_EQ(ret, 0);
+
+       memset(&config, 1, sizeof(config));
+       ret = sys_ptrace(PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, child,
+                        (void *)sizeof(config), &config);
+
+       ASSERT_EQ(ret, 0);
+       ASSERT_EQ(config.mode, PR_SYS_DISPATCH_ON);
+       ASSERT_EQ(config.selector, 0);
+       ASSERT_EQ(config.offset, 0x400000);
+       ASSERT_EQ(config.len, 0x1000);
+
+       kill(child, SIGKILL);
+}
+
+TEST_HARNESS_MAIN