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

我应注意什么,以便ptrace() d进程及其子级(递归)无法绕过沙箱?上司在fork()时应该采取什么特殊措施来避免出现竞赛情况?是否可以读取例如的文件名参数来自子进程的rename()没有竞争条件?

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

  • 时避免使用
  • PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE,避免(某些)种族条件
  • 默认情况下禁止所有系统调用,并撰写允许的系统调用白名单
  • 确保正确保护了fork()系统调用变体(例如*at())

  • 我还要注意什么?

    最佳答案

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

    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"
    

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

    另一种方法是对每个潜在危险的syscall周围的跟踪组中的所有其他进程SIGSTOP,等待它们实际停止,然后允许syscall继续进行。返回之后,您就可以对其进行SIGCONT编码(除非它们已被停止)。不用说,这可能会对性能产生重大影响。

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

    关于linux - Linux ptrace如何不安全或包含竞争条件?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4414605/

    10-12 06:07