1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3 #include "../kselftest_harness.h"
4 #include <stdio.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <sys/wait.h>
8 #include <sys/syscall.h>
9 #include <sys/prctl.h>
10 
11 #include "linux/ptrace.h"
12 
13 static int sys_ptrace(int request, pid_t pid, void *addr, void *data)
14 {
15 	return syscall(SYS_ptrace, request, pid, addr, data);
16 }
17 
18 TEST(get_set_sud)
19 {
20 	struct ptrace_sud_config config;
21 	pid_t child;
22 	int ret = 0;
23 	int status;
24 
25 	child = fork();
26 	ASSERT_GE(child, 0);
27 	if (child == 0) {
28 		ASSERT_EQ(0, sys_ptrace(PTRACE_TRACEME, 0, 0, 0)) {
29 			TH_LOG("PTRACE_TRACEME: %m");
30 		}
31 		kill(getpid(), SIGSTOP);
32 		_exit(1);
33 	}
34 
35 	waitpid(child, &status, 0);
36 
37 	memset(&config, 0xff, sizeof(config));
38 	config.mode = PR_SYS_DISPATCH_ON;
39 
40 	ret = sys_ptrace(PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, child,
41 			 (void *)sizeof(config), &config);
42 
43 	ASSERT_EQ(ret, 0);
44 	ASSERT_EQ(config.mode, PR_SYS_DISPATCH_OFF);
45 	ASSERT_EQ(config.selector, 0);
46 	ASSERT_EQ(config.offset, 0);
47 	ASSERT_EQ(config.len, 0);
48 
49 	config.mode = PR_SYS_DISPATCH_ON;
50 	config.selector = 0;
51 	config.offset = 0x400000;
52 	config.len = 0x1000;
53 
54 	ret = sys_ptrace(PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG, child,
55 			 (void *)sizeof(config), &config);
56 
57 	ASSERT_EQ(ret, 0);
58 
59 	memset(&config, 1, sizeof(config));
60 	ret = sys_ptrace(PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, child,
61 			 (void *)sizeof(config), &config);
62 
63 	ASSERT_EQ(ret, 0);
64 	ASSERT_EQ(config.mode, PR_SYS_DISPATCH_ON);
65 	ASSERT_EQ(config.selector, 0);
66 	ASSERT_EQ(config.offset, 0x400000);
67 	ASSERT_EQ(config.len, 0x1000);
68 
69 	kill(child, SIGKILL);
70 }
71 
72 TEST_HARNESS_MAIN
73