ptrace.c 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. puts("----- Pre-syscall -----");
  40. result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
  41. ERROR_IF(ptrace, result, == -1);
  42. UNEXP_IF(ptrace, result, != 0);
  43. puts("Wait...");
  44. result = waitpid(pid, &status, 0);
  45. ERROR_IF(waitpid, result, == -1);
  46. if (WIFEXITED(status)) { break; }
  47. struct user_regs_struct regs;
  48. puts("Get regs");
  49. result = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
  50. ERROR_IF(ptrace, result, == -1);
  51. if (regs.orig_rax == SYS_write || regs.orig_rax == SYS_write) {
  52. regs.rdi = 2;
  53. puts("Set regs");
  54. result = ptrace(PTRACE_SETREGS, pid, NULL, &regs);
  55. ERROR_IF(ptrace, result, == -1);
  56. }
  57. puts("Post-syscall");
  58. result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
  59. ERROR_IF(ptrace, result, == -1);
  60. UNEXP_IF(ptrace, result, != 0);
  61. puts("Wait...");
  62. result = waitpid(pid, &status, 0);
  63. ERROR_IF(waitpid, result, == -1);
  64. if (WIFEXITED(status)) { break; }
  65. }
  66. printf("Child exited with status %d\n", WEXITSTATUS(status));
  67. }
  68. }