Files
RedBear-OS/tests/ptrace.c
T
Anhad Singh 2c307616d8 fix(tests/ptrace.c): persistent logs
Even though it might seem like it, it is not necessary that write(2) is
the only system call performed. It could be that the libc has to
allocate memory (via MMAP) or makes use of a futex. To produce
consistant results, only log on SYS_write and when the syscall number
has been patched.

Signed-off-by: Anhad Singh <andypython@protonmail.com>
2024-12-31 00:54:58 +11:00

86 lines
2.4 KiB
C

#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <unistd.h>
#include "test_helpers.h"
#ifdef __linux__
#define SYS_write 1
#endif
#ifdef __redox__
#define SYS_write 0x21000004
#endif
int main() {
int pid = fork();
ERROR_IF(fork, pid, == -1);
if (pid == 0) {
// Test behavior on Redox when TRACEME hasn't been activated
// before waitpid is invoked!
sleep(1);
int result = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
ERROR_IF(ptrace, result, == -1);
UNEXP_IF(ptrace, result, != 0);
// Alert parent: I'm ready
result = raise(SIGSTOP);
ERROR_IF(raise, result, == -1);
UNEXP_IF(raise, result, != 0);
puts("This is printed to STDOUT.");
puts("Or, at least, that's what I thought.");
puts("But all write(...) syscalls are actually redirected to STDERR by the tracer.");
puts("Big surprise, right!");
} else {
// Wait for child process to be ready
int result = waitpid(pid, NULL, 0);
ERROR_IF(waitpid, result, == -1);
int status;
while (true) {
// puts("----- Pre-syscall -----");
result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
ERROR_IF(ptrace, result, == -1);
UNEXP_IF(ptrace, result, != 0);
// puts("Wait...");
result = waitpid(pid, &status, 0);
ERROR_IF(waitpid, result, == -1);
if (WIFEXITED(status))
break;
struct user_regs_struct regs;
// puts("Get regs");
result = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
ERROR_IF(ptrace, result, == -1);
if (regs.orig_rax == SYS_write || regs.orig_rax == SYS_write) {
regs.rdi = 2;
puts("Set regs");
result = ptrace(PTRACE_SETREGS, pid, NULL, &regs);
ERROR_IF(ptrace, result, == -1);
}
// puts("Post-syscall");
result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
ERROR_IF(ptrace, result, == -1);
UNEXP_IF(ptrace, result, != 0);
// puts("Wait...");
result = waitpid(pid, &status, 0);
ERROR_IF(waitpid, result, == -1);
if (WIFEXITED(status))
break;
}
printf("Child exited with status %d\n", WEXITSTATUS(status));
}
}