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