162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#define _GNU_SOURCE
362306a36Sopenharmony_ci#include "../kselftest_harness.h"
462306a36Sopenharmony_ci#include <stdio.h>
562306a36Sopenharmony_ci#include <string.h>
662306a36Sopenharmony_ci#include <errno.h>
762306a36Sopenharmony_ci#include <sys/wait.h>
862306a36Sopenharmony_ci#include <sys/syscall.h>
962306a36Sopenharmony_ci#include <sys/prctl.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include "linux/ptrace.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic int sys_ptrace(int request, pid_t pid, void *addr, void *data)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	return syscall(SYS_ptrace, request, pid, addr, data);
1662306a36Sopenharmony_ci}
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciTEST(get_set_sud)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	struct ptrace_sud_config config;
2162306a36Sopenharmony_ci	pid_t child;
2262306a36Sopenharmony_ci	int ret = 0;
2362306a36Sopenharmony_ci	int status;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	child = fork();
2662306a36Sopenharmony_ci	ASSERT_GE(child, 0);
2762306a36Sopenharmony_ci	if (child == 0) {
2862306a36Sopenharmony_ci		ASSERT_EQ(0, sys_ptrace(PTRACE_TRACEME, 0, 0, 0)) {
2962306a36Sopenharmony_ci			TH_LOG("PTRACE_TRACEME: %m");
3062306a36Sopenharmony_ci		}
3162306a36Sopenharmony_ci		kill(getpid(), SIGSTOP);
3262306a36Sopenharmony_ci		_exit(1);
3362306a36Sopenharmony_ci	}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	waitpid(child, &status, 0);
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	memset(&config, 0xff, sizeof(config));
3862306a36Sopenharmony_ci	config.mode = PR_SYS_DISPATCH_ON;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	ret = sys_ptrace(PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, child,
4162306a36Sopenharmony_ci			 (void *)sizeof(config), &config);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	ASSERT_EQ(ret, 0);
4462306a36Sopenharmony_ci	ASSERT_EQ(config.mode, PR_SYS_DISPATCH_OFF);
4562306a36Sopenharmony_ci	ASSERT_EQ(config.selector, 0);
4662306a36Sopenharmony_ci	ASSERT_EQ(config.offset, 0);
4762306a36Sopenharmony_ci	ASSERT_EQ(config.len, 0);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	config.mode = PR_SYS_DISPATCH_ON;
5062306a36Sopenharmony_ci	config.selector = 0;
5162306a36Sopenharmony_ci	config.offset = 0x400000;
5262306a36Sopenharmony_ci	config.len = 0x1000;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	ret = sys_ptrace(PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG, child,
5562306a36Sopenharmony_ci			 (void *)sizeof(config), &config);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	ASSERT_EQ(ret, 0);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	memset(&config, 1, sizeof(config));
6062306a36Sopenharmony_ci	ret = sys_ptrace(PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, child,
6162306a36Sopenharmony_ci			 (void *)sizeof(config), &config);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	ASSERT_EQ(ret, 0);
6462306a36Sopenharmony_ci	ASSERT_EQ(config.mode, PR_SYS_DISPATCH_ON);
6562306a36Sopenharmony_ci	ASSERT_EQ(config.selector, 0);
6662306a36Sopenharmony_ci	ASSERT_EQ(config.offset, 0x400000);
6762306a36Sopenharmony_ci	ASSERT_EQ(config.len, 0x1000);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	kill(child, SIGKILL);
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ciTEST_HARNESS_MAIN
73