Skip to content

joeyac/cbox

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cbox

linux sandboxing by using seccomp-bpf and ptrace sandbox

总体流程

首先主进程fork出一个从进程,从进程依次设置以下限制:

  • prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
  • ptrace(PTRACE_TRACEME, 0, NULL, NULL);
  • 从配置文件当中读取时间内存(注意这里的时间是cpu时间)等限制,使用setrlimit做出限制
  • chdirchroot: chroot需要额外权限,可能不会使用
  • 重定向stdin, stdout, stderr
  • 增加seccomp规则
  • 给自己发送SIGSTOP信号,这一步是因为,父进程需要通过ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESECCOMP);来开始追踪子进程的非法系统调用,必须要在设置seccomp规则之后才能开始合法追踪,于是父进程可以先wait一下,如果获取到了子进程正常暂停,那么说明之前的限制都正确应用且此时可以开始追踪子进程。
  • 调用execve(config->file, config->argv, config->envp);执行程序,注意在seccomp规则中需要额外增加一条允许execve(config->file...)这样的系统调用执行。另外注意调用execve之后,如果本身是被ptrace的进程,在执行成功execve之后,会发送一个SIGTRAP的信号。

主进程本身在fork之后,需要配合从进程进行一些处理:

  • 首先调用一次wait,如果不是异常退出状态,说明限制正常应用,继续处理,否则退出程序。正常的信号应该为SIGSTOP(18)
  • 设置ptrace追踪属性:ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESECCOMP);
  • 在子进程execve之前,用setpgid(child,child);将子进程的组id改为它自己,这样方便使用kill(-child, XXX)来向子进程及其派生进程发送信号。
  • 调用ptrace(PTRACE_CONT, child, 0, 0);,然后子程序应该执行到execve完成之后
  • 调用wait获取状态,信号应该为SIGTRAP(5)
  • 调用ptrace(PTRACE_CONT, child, 0, 0);,从这里开始子程序应该开始真正的执行过程
  • 调用wait获取状态,此时获取到状态时应该有三种情况:
    • 正常退出 / 资源异常
    • 使用了非法的系统调用
    • 超过wall time限制

在最后正常退出 / 资源异常放在一起是因为这种情况下都可以从wait返回的status中拿到大部分信息;使用了非法的系统调用需要特殊处理一下并且手动终止程序;超过wall time限制则是使用setitimer设置定时器向自身发送SIGALRM信号,并在对应的信号处理函数中将子进程组全部关闭。

About

linux sandboxing by using seccomp-bpf sanbox

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published