Skip to content

Commit 96f262d

Browse files
shkhlnemaste
authored andcommitted
tests/sys/arch/amd64: Add a basic ptrace syscall tampering test
Signed-off-by: Alex S <iwtcex@gmail.com> Reviewed-by: kib Pull-request: #2190
1 parent 45fa572 commit 96f262d

2 files changed

Lines changed: 90 additions & 0 deletions

File tree

tests/sys/arch/amd64/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
TESTSDIR= ${TESTSBASE}/sys/arch/amd64
22

33
PLAIN_TESTS_C+= int0x80
4+
PLAIN_TESTS_C+= ptrace-sce-tamper
45

56
BINDIR= ${TESTSDIR}
67

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* SPDX-License-Identifier: BSD-2-Clause
3+
*
4+
* Copyright (c) 2026 Alex S <iwtcex@gmail.com>
5+
*/
6+
7+
#include <machine/reg.h>
8+
#include <sys/ptrace.h>
9+
#include <sys/syscall.h>
10+
#include <sys/wait.h>
11+
12+
#include <assert.h>
13+
#include <err.h>
14+
#include <stdio.h>
15+
#include <stdlib.h>
16+
#include <unistd.h>
17+
18+
#ifndef __amd64__
19+
#error "amd64 only"
20+
#endif
21+
22+
/*
23+
* This test substitutes exit(42) instead of getpid() using ptrace.
24+
*/
25+
26+
static const int EXPECTED_EXIT_CODE = 42;
27+
28+
static void
29+
tamper(pid_t pid)
30+
{
31+
struct ptrace_lwpinfo info;
32+
struct reg regs;
33+
34+
if (ptrace(PT_LWPINFO, pid, (caddr_t)&info, sizeof(info)) == -1)
35+
err(1, "ptrace(PT_LWPINFO)");
36+
37+
if ((info.pl_flags & PL_FLAG_SCE) != 0 &&
38+
info.pl_syscall_code == SYS_getpid) {
39+
if (ptrace(PT_GETREGS, pid, (caddr_t)&regs, sizeof(regs)) == -1)
40+
err(1, "ptrace(PT_GETREGS)");
41+
42+
regs.r_rax = SYS_exit;
43+
regs.r_rdi = EXPECTED_EXIT_CODE;
44+
45+
if (ptrace(PT_SETREGS, pid, (caddr_t)&regs, sizeof(regs)) == -1)
46+
err(1, "ptrace(PT_SETREGS)");
47+
}
48+
}
49+
50+
int
51+
main(void)
52+
{
53+
pid_t pid;
54+
int status;
55+
56+
pid = fork();
57+
if (pid == -1)
58+
err(1, "fork");
59+
60+
if (pid == 0) {
61+
(void)ptrace(PT_TRACE_ME, 0, 0, 0);
62+
(void)getpid();
63+
exit(0);
64+
} else {
65+
if (ptrace(PT_ATTACH, pid, 0, 0) == -1)
66+
err(1, "ptrace(PT_ATTACH)");
67+
68+
for (;;) {
69+
if (wait(&status) == -1)
70+
err(1, "wait");
71+
72+
if (WIFEXITED(status)) {
73+
if (WEXITSTATUS(status) == EXPECTED_EXIT_CODE) {
74+
printf("exit code changed\n");
75+
exit(0);
76+
} else {
77+
printf("unable to change exit code\n");
78+
exit(1);
79+
}
80+
}
81+
82+
assert(WIFSTOPPED(status));
83+
tamper(pid);
84+
85+
if (ptrace(PT_TO_SCE, pid, (caddr_t)1, 0) == -1)
86+
err(1, "ptrace(PT_TO_SCE)");
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)