ptrace.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #include <signal.h>
  2. #include <stdbool.h>
  3. #include <stdio.h>
  4. #include <sys/ptrace.h>
  5. #include <sys/user.h>
  6. #include <sys/wait.h>
  7. #include <unistd.h>
  8. #include "test_helpers.h"
  9. int main() {
  10. int pid = fork();
  11. ERROR_IF(fork, pid, == -1);
  12. if (pid == 0) {
  13. int result = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
  14. ERROR_IF(ptrace, result, == -1);
  15. UNEXP_IF(ptrace, result, != 0);
  16. // Alert parent: I'm ready
  17. result = raise(SIGSTOP);
  18. ERROR_IF(raise, result, == -1);
  19. UNEXP_IF(raise, result, != 0);
  20. puts("This is printed to STDOUT.");
  21. puts("Or, at least, that's what I thought.");
  22. puts("But all write(...) syscalls are actually redirected to STDERR by the tracer.");
  23. puts("Big surprise, right!");
  24. } else {
  25. // Wait for child process to be ready
  26. int result = waitpid(pid, NULL, WUNTRACED);
  27. ERROR_IF(waitpid, result, == -1);
  28. int status;
  29. while (true) {
  30. // Pre-syscall:
  31. result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
  32. ERROR_IF(ptrace, result, == -1);
  33. UNEXP_IF(ptrace, result, != 0);
  34. result = waitpid(pid, &status, 0);
  35. ERROR_IF(waitpid, result, == -1);
  36. if (WIFEXITED(status)) { break; }
  37. struct user_regs_struct regs;
  38. result = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
  39. ERROR_IF(ptrace, result, == -1);
  40. if (regs.orig_rax == 1 || regs.orig_rax == 0x21000004) { // SYS_write on Redox and Linux
  41. regs.rdi = 2;
  42. result = ptrace(PTRACE_SETREGS, pid, NULL, &regs);
  43. ERROR_IF(ptrace, result, == -1);
  44. }
  45. // Post-syscall:
  46. result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
  47. ERROR_IF(ptrace, result, == -1);
  48. UNEXP_IF(ptrace, result, != 0);
  49. result = waitpid(pid, &status, 0);
  50. ERROR_IF(waitpid, result, == -1);
  51. if (WIFEXITED(status)) { break; }
  52. }
  53. printf("Child exited with status %d\n", WEXITSTATUS(status));
  54. }
  55. }