| // 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 |