sandbox.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include <sys/ptrace.h>
  2. #include <sys/types.h>
  3. #include <sys/wait.h>
  4. #include <sys/reg.h>
  5. #include <sys/uio.h>
  6. #include <strings.h>
  7. #include <string.h>
  8. #include <elf.h>
  9. #include "sandbox.h"
  10. /* DEBUG HEADER */
  11. #include <stdio.h>
  12. static inline void get_args(struct s_sandboxenv *env)
  13. {
  14. #ifdef __x86_64__
  15. REGISTER_TYPE result[] = { env->registers.rdi, env->registers.rsi,
  16. env->registers.rdx, env->registers.r10,
  17. env->registers.r8, env->registers.r9 };
  18. #else
  19. REGISTER_TYPE result[] = { env->registers.ebx, env->registers.ecx,
  20. env->registers.edx, env->registers.esi,
  21. env->registers.edi, env->registers.ebp };
  22. #endif
  23. memcpy(env->syscall_args, result, sizeof(REGISTER_TYPE) * 6);
  24. }
  25. static inline void init_syscalls(struct s_sandboxenv *env)
  26. {
  27. bzero(env->functions, sizeof(*(env->functions)) * NR_syscalls);
  28. env->functions[__NR_write] = ovr_write;
  29. env->functions[__NR_open] = ovr_open;
  30. env->functions[__NR_close] = ovr_close;
  31. }
  32. static inline int waitForSyscall(const int pid)
  33. {
  34. int status;
  35. ptrace(PTRACE_SYSCALL, pid, NULL, 0);
  36. if (waitpid(pid, &status, 0) == -1)
  37. return -1;
  38. return 0;
  39. }
  40. int manageSyscall(struct s_sandboxenv *env)
  41. {
  42. t_syscall_fnc ovr_fnc;
  43. unsigned int syscall_nr;
  44. #ifdef __x86_64__
  45. syscall_nr = (unsigned int) env->registers.orig_rax;
  46. #else
  47. syscall_nr = (unsigned int) env->registers.orig_eax;
  48. #endif
  49. if (syscall_nr >= NR_syscalls ||
  50. !(ovr_fnc = env->functions[syscall_nr]))
  51. {
  52. /* TODO verbose -v */
  53. return 0;
  54. }
  55. get_args(env);
  56. (ovr_fnc)(env);
  57. return 1;
  58. }
  59. void doTrace(int pid, const t_param *params)
  60. {
  61. int status;
  62. struct s_sandboxenv sandbox_env;
  63. struct iovec iov = { &(sandbox_env.registers), sizeof(sandbox_env.registers) };
  64. ptrace(PTRACE_ATTACH, pid, 0, 0);
  65. kill(pid, SIGTRAP);
  66. waitpid(pid, &status, 0);
  67. sandbox_env.params = params;
  68. sandbox_env.child_pid = pid;
  69. init_syscalls(&sandbox_env);
  70. while (1)
  71. {
  72. if (waitForSyscall(pid))
  73. break;
  74. ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov);
  75. if (manageSyscall(&sandbox_env))
  76. ptrace(PTRACE_SETREGS, pid, 0, &(sandbox_env.registers));
  77. if (waitForSyscall(pid))
  78. break;
  79. iov.iov_len = sizeof(sandbox_env.registers);
  80. ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov);
  81. manageSyscall(&sandbox_env);
  82. }
  83. }
  84. int launch_program(const t_param *params)
  85. {
  86. int child = fork();
  87. if (child == -1)
  88. return -1;
  89. else if (child == 0)
  90. doExec(getpid(), params);
  91. else
  92. doTrace(child, params);
  93. return 0;
  94. }