sandbox.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. static inline void get_args(struct s_sandboxenv *env)
  11. {
  12. }
  13. int waitForSyscall(const int pid, int _status)
  14. {
  15. int status;
  16. static int current_status = SANDBOX_SYS_EXIT;
  17. if (current_status == _status || (_status != SANDBOX_SYS_ENTER && _status != SANDBOX_SYS_EXIT))
  18. return 0;
  19. ptrace(PTRACE_SYSCALL, pid, NULL, 0);
  20. current_status = _status;
  21. if (waitpid(pid, &status, 0) == -1)
  22. return -1;
  23. return 0;
  24. }
  25. int manageSyscall(struct s_sandboxenv *env)
  26. {
  27. t_syscall_fnc ovr_fnc;
  28. if (env->syscall_no.syscall_no >= NR_syscalls ||
  29. !(ovr_fnc = env->functions[env->syscall_no.syscall_no]))
  30. {
  31. /* Unrecognized syscall */
  32. return 0;
  33. }
  34. return (ovr_fnc)(env);
  35. }
  36. void read_registers(struct s_sandboxenv *env)
  37. {
  38. struct iovec iov = { &(env->registers), sizeof(env->registers) };
  39. ptrace(PTRACE_GETREGSET, env->child_pid, NT_PRSTATUS, &iov);
  40. #ifdef __x86_64__
  41. env->syscall_no.syscall_no = (unsigned int) env->registers.orig_rax;
  42. env->syscall_no.syscall_return = (unsigned int) env->registers.rax;
  43. REGISTER_TYPE result[] = { env->registers.rdi, env->registers.rsi,
  44. env->registers.rdx, env->registers.r10,
  45. env->registers.r8, env->registers.r9 };
  46. #else
  47. env->syscall_no.syscall_no = (unsigned int) env->registers.orig_eax;
  48. env->syscall_no.syscall_return = (unsigned int) env->registers.eax;
  49. REGISTER_TYPE result[] = { env->registers.ebx, env->registers.ecx,
  50. env->registers.edx, env->registers.esi,
  51. env->registers.edi, env->registers.ebp };
  52. #endif
  53. memcpy(env->syscall_args, result, sizeof(REGISTER_TYPE) * 6);
  54. }
  55. void doTrace(int pid, const t_param *params)
  56. {
  57. int status;
  58. struct s_sandboxenv sandbox_env;
  59. ptrace(PTRACE_ATTACH, pid, 0, 0);
  60. kill(pid, SIGTRAP);
  61. waitpid(pid, &status, 0);
  62. sandbox_env.params = params;
  63. sandbox_env.child_pid = pid;
  64. //TODO get error output from command-line
  65. sandbox_env.errorOutput = stderr;
  66. sandbox_env.filetable = sllist_create();
  67. init_syscalls(&sandbox_env);
  68. while (1)
  69. {
  70. if (waitForSyscall(pid, SANDBOX_SYS_ENTER))
  71. break;
  72. read_registers(&sandbox_env);
  73. if (manageSyscall(&sandbox_env))
  74. ptrace(PTRACE_SETREGS, pid, 0, &(sandbox_env.registers));
  75. if (waitForSyscall(pid, SANDBOX_SYS_EXIT))
  76. break;
  77. }
  78. prompt_sandbox(&sandbox_env);
  79. sllist_destroy(sandbox_env.filetable);
  80. }
  81. int launch_program(const t_param *params)
  82. {
  83. int child = fork();
  84. if (child == -1)
  85. return -1;
  86. else if (child == 0)
  87. doExec(getpid(), params);
  88. else
  89. doTrace(child, params);
  90. return 0;
  91. }