ptrace.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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. #ifdef __linux__
  10. const int SYS_write = 1;
  11. #endif
  12. #ifdef __redox__
  13. const int SYS_write = 0x21000004;
  14. #endif
  15. int main() {
  16. int pid = fork();
  17. ERROR_IF(fork, pid, == -1);
  18. if (pid == 0) {
  19. // Test behavior on Redox when TRACEME hasn't been activated
  20. // before waitpid is invoked!
  21. sleep(1);
  22. int result = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
  23. ERROR_IF(ptrace, result, == -1);
  24. UNEXP_IF(ptrace, result, != 0);
  25. // Alert parent: I'm ready
  26. result = raise(SIGSTOP);
  27. ERROR_IF(raise, result, == -1);
  28. UNEXP_IF(raise, result, != 0);
  29. puts("This is printed to STDOUT.");
  30. puts("Or, at least, that's what I thought.");
  31. puts("But all write(...) syscalls are actually redirected to STDERR by the tracer.");
  32. puts("Big surprise, right!");
  33. } else {
  34. // Wait for child process to be ready
  35. int result = waitpid(pid, NULL, 0);
  36. ERROR_IF(waitpid, result, == -1);
  37. int status;
  38. while (true) {
  39. // Pre-syscall:
  40. result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
  41. ERROR_IF(ptrace, result, == -1);
  42. UNEXP_IF(ptrace, result, != 0);
  43. result = waitpid(pid, &status, 0);
  44. ERROR_IF(waitpid, result, == -1);
  45. if (WIFEXITED(status)) { break; }
  46. struct user_regs_struct regs;
  47. result = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
  48. ERROR_IF(ptrace, result, == -1);
  49. if (regs.orig_rax == SYS_write || regs.orig_rax == SYS_write) {
  50. regs.rdi = 2;
  51. result = ptrace(PTRACE_SETREGS, pid, NULL, &regs);
  52. ERROR_IF(ptrace, result, == -1);
  53. }
  54. // Post-syscall:
  55. result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
  56. ERROR_IF(ptrace, result, == -1);
  57. UNEXP_IF(ptrace, result, != 0);
  58. result = waitpid(pid, &status, 0);
  59. ERROR_IF(waitpid, result, == -1);
  60. if (WIFEXITED(status)) { break; }
  61. }
  62. printf("Child exited with status %d\n", WEXITSTATUS(status));
  63. }
  64. }