Hep*_*tic 5 c linux posix sandbox mprotect
我有一个小程序,可以映射具有潜在危险的可执行代码(使用PROT_EXEC),prctl(PR_SET_SECCOMP, 1)然后调用并执行此mmap编码。这一切都很好,并允许我通过将mmap'd区域同步到磁盘来“保存”评估状态,然后稍后将其重新加载(很可能在另一台计算机上进行负载平衡)。但是,这种技术并不总是有效的-因为此代码可能已对不在mmap'd区域中的程序进行了更改,因此这些信息将丢失。
因此,我想做的是在调用代码之前使所有内容(除了此mmap'd区域之外)绝对都是只读的。这样,我保证可执行代码除了可以随意进行序列化/反序列化的mmap'd区域之外,不会更改任何状态。
顺便说一句,这是x86_64上的Linux
谢谢
首先,观察一下:没有任何内容表明您必须mmap()将机器指令放入内存或将它们保存回文件中。read()也write()可以这样做,只是请注意,您应该为此目的创建一个可写且可执行的私有映射。
显然,如果要在同一进程中执行,则无法可靠地禁用对将调用要加载的可执行代码的堆栈区域的写入,因为这将使堆栈无法使用。您可以通过注释变量或使用程序集来解决此问题。
您的下一个选择是fork()。您可以exec将子项放入一个特殊的包装可执行文件中,该可执行文件允许恶意可执行代码造成的损坏和内省最小化(提供简单的加载/转储),或者您可以通过让子项修改自身以达到相同的效果来执行相同的操作。这仍然不是 100% 安全。
-nodefaultlibs。fork在子级中的,之后ptrace(PTRACE_TRACEME)(以便您可以可靠地读取内存内容并进行其他干预),并关闭除管道之外的所有句柄(只是为了stdin简单起见)。exec()进入前面提到的包装二进制文件。在包装二进制文件中:
mmap位于已知位置的具有写入和执行权限的私有区域。或者,如果大小固定,您可以静态分配该区域。prctl(PR_SET_SECCOMP, 1)。现在唯一有效的系统调用是_exit和sigreturn。既然这个过程不能raise,sigreturn应该没有任何有用的效果。在父级中:
ptrace或wait捕获错误或成功完成。/proc/<pid>/mem通过文件或等效文件读取已知位置处的映射区域。