/src/ptracetest1.c

http://github.com/Eelis/geordi · C · 69 lines · 49 code · 16 blank · 4 comment · 11 complexity · 92405821e3bcd45a9b9b77ca56ad7dba MD5 · raw file

  1. #include <assert.h>
  2. #include <sys/ptrace.h>
  3. #include <linux/ptrace.h>
  4. #include <sys/types.h>
  5. #include <sys/wait.h>
  6. #include <unistd.h>
  7. #include <linux/user.h>
  8. #include <sys/syscall.h>
  9. #include <syscall.h>
  10. #include <sys/reg.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #ifdef __x86_64__
  14. #define SYSCALL_OFF (ORIG_RAX * 8)
  15. #else
  16. #define SYSCALL_OFF (ORIG_EAX * 4)
  17. #endif
  18. void checked (char const * const s, int const r) { if (r == -1) { perror(s); abort(); } }
  19. int main()
  20. {
  21. pid_t const child = fork();
  22. checked("fork", child);
  23. if(child == 0)
  24. {
  25. checked("ptrace", ptrace(PTRACE_TRACEME, 0, NULL, NULL));
  26. checked("execl", execl("/usr/bin/whoami", "whoami", NULL));
  27. }
  28. int status;
  29. checked("wait", wait(&status));
  30. assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP);
  31. // No way to know whether this SIGTRAP was caused by entry/exit, because we couldn't set PTRACE_O_TRACESYSGOOD until now (see ptracetest2.c).
  32. printf("opaque trap passed\n");
  33. checked("ptrace", ptrace(PTRACE_SETOPTIONS, child, NULL, PTRACE_O_TRACESYSGOOD));
  34. for(;;)
  35. {
  36. checked("ptrace", ptrace(PTRACE_SYSCALL, child, NULL, NULL));
  37. checked("wait", wait(&status));
  38. if (WIFEXITED(status)) break;
  39. if (WSTOPSIG(status) == (SIGTRAP | 0x80))
  40. {
  41. printf("syscall trap %ld\n", ptrace(PTRACE_PEEKUSER, child, SYSCALL_OFF, NULL));
  42. }
  43. else
  44. {
  45. assert(WSTOPSIG(status) == SIGTRAP);
  46. printf("non-syscall trap\n");
  47. }
  48. }
  49. return 0;
  50. }
  51. // On Eelis' machines, no syscall traps for execve are shown. On CoffeeBuzz' dual core machine, one syscall trap for execve is shown.
  52. // Conclusion: Using execve as "first SIGTRAP" foundation, one cannot know whether the first observed syscall trap is an entry or exit.
  53. // This testcase assumes that on syscall exit traps, ORIG_EAX/ORIG_RAX still holds the syscall number.