Linux ptrace如何不安全或包含竞争条件?

pts*_*pts 5 linux ptrace sandbox

我想ptrace()通过一个我开始的过程实现一个沙箱,它的所有孩子都会创建(包括孙子等).该ptrace()父进程,即监督者.将是一个简单的C或Python程序,从概念上讲,它将限制文件系统访问(基于路径名和访问方向(读或写)和套接字访问(例如禁止套接字创建).

我应该注意什么,以便ptrace()d进程及其子进程(递归)将无法绕过沙箱?主管应该及时做些什么fork()来避免竞争条件?是否可以在rename()没有竞争条件的情况下读取例如来自子进程的文件名参数?

这是我已经计划做的事情:

  • PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE为了避免(一些)比赛coditions时,fork()荷兰国际集团
  • 默认情况下禁止所有系统调用,并组成允许的系统调用的白名单
  • 确保*at()系统调用变量(例如openat)得到适当保护

我还应该注意什么?

caf*_*caf 12

主要问题是许多系统调用参数(如文件名)作为用户空间指针传递给内核.任何允许同时运行且对指针指向的内存具有写访问权限的任务可以在主管检查这些参数并在内核对其进行操作之前有效地修改这些参数.当内核跟随指针时,指向的内容可能已被另一个可访问该内存的可调度任务(进程或线程)故意更改.例如:

Thread 1                           Supervisor             Thread 2
-----------------------------------------------------------------------------------------------------
strcpy(filename, "/dev/null");
open(filename, O_RDONLY);
                                   Check filename - OK
                                                          strcpy(filename, "/home/user/.ssh/id_rsa");
(in kernel) opens "/home/user/.ssh/id_rsa"
Run Code Online (Sandbox Code Playgroud)

阻止这种情况的一种方法是禁止clone()使用CLONE_VM标志进行调用,另外防止任何可写MAP_SHARED内存映射的创建(或者至少跟踪它们,以便拒绝任何试图直接从这种映射引用数据的系统调用).在允许系统调用继续之前,您还可以将任何此类参数复制到非共享跳出缓冲区中.这将有效地防止任何线程应用程序在沙箱中运行.

替代方案是SIGSTOP跟踪组中的每个其他进程围绕每个潜在危险的系统调用,等待它们实际停止,然后允许系统调用继续进行.它返回后,你然后SIGCONT他们(除非他们已经停止).不用说,这可能会对性能产生重大影响.

(在堆栈上传递的syscall参数和共享打开文件表也存在类似的问题).