2012-07-13 42 views
5

我想在我的服务器上执行任意(潜在危险)的二进制文件。因此,我使用objcopy将“main”符号重命名为“other_main”,以便我可以链接到我自己的小主函数中,该函数在调用other_main之前为RLIMIT_CPU设置适当的值并切换SECCOMP标志。到目前为止,我对这个解决方案非常满意。SECCOMP:如何模拟malloc,realloc和free?

现在的问题是,第三方程序代码可能包含一些对malloc的调用,可能会立即终止程序(sbrk不允许)。因此,我希望在设置应该由malloc/realloc/calloc/free使用的SECCOMP之前预先分配一些合理大小的数组(例如20MB)。不幸的是,我不知道如何归档最后一步。我是否必须自己实施所有这4项功能?我怎样才能将自己的函数注入到stdlib中(例如,printf在内部调用malloc时会发生什么?)。

+0

是否重命名符号realy作品?我真的不知道操作系统是如何处理被剥离的二进制文件的。 – 2012-07-13 20:34:09

+0

重命名符号在这里工作正常。 objcopy似乎非常强大。你显然不允许去除二进制文件,但这对我来说不是问题,因为我自己编译二进制文件。这只是不可信的C代码。 – tux21b 2012-07-13 20:46:44

+0

你能否为你的用户提供一个不同于你的操作系统库的C库(例如Newlib)?如果是这样,编写自己的'sbrk'(不能离开你的沙箱),然后malloc/realloc/calloc/free和朋友都可以工作。 – 2012-07-13 20:59:15

回答

3

并非所有的malloc实现都基于sbrk(),例如有GNU mmalloc。如果需要自定义实现,This doc也可能有用。

+两个简单的malloc实现here

+0

唯一被允许的系统调用是读,写,签名和退出。所以我也不能使用mmap,除非我在程序开始时预先分配足够的内存(合理大小的静态数组似乎对我的用例来说没问题)。这个链接看起来很有用,假设我真的需要实现我自己的malloc。但我仍然不知道如何替换printf和stdlib中其他地方使用的内部malloc调用。 – tux21b 2012-07-13 20:57:27

+0

我已经更正了答案:dlmalloc实际上使用sbrk()。但是,我发现基于mmap()的GNU mmaloc。在你的情况下,你可能会考虑在其基础上使用静态池[]代替堆+简单处理功能。例如,你也可以在静态数组中保存N个引用。那当然是假动态记忆。 – pmod 2012-07-13 21:09:16

1

seccompsandbox

  • 使的Seccomp在一个线程中,其执行RPC(超过经由read/write一个预分配socketpair)到另一个(非的Seccomp)线程在相同的进程中能够执行特权操作,如mmap
  • 修补功能,如malloc(内存中,在运行时)重定向到ir seccomp-safe wrappers

Chromium's seccomp Sandbox有一些关于工作原理的更多细节。

2

对于malloc和free,你的程序只需要定义它自己的版本。我见过的大多数libc实现(包括glibc,klibc和dietlibc)都会很乐意使用您的内存分配器例程。因此,在进入seccomp模式之前,使用mmap或sbrk分配一大块内存,然后从这个块中分配你的malloc/free。 memmgr是一个简单的堆分配器,可以很容易地适应从固定缓冲区分配。

seccomp的真正问题在于它允许的系统调用集(读,写,退出和sigreturn)根本不足以运行链接到或多或少与任何 libc链接的程序。例如:

  • glibc中,出口和_exit调用exit_group glibc中
  • ,printf的可以调用MMAP在dietlibc
  • ,scanf的可调用的ioctl
  • 等等等等

这些调用是必要的,通常有很好的理由。例如,当从stdin读取输入时,dietlibc使用ioctl检查stdin是否为tty,以便刷新标准输出。这是标准行为,以确保在读取交互式输入之前提示是可见的,前提是输出是行缓冲的。

所以,我得出结论,原来的seccomp模式或多或少是无用的。然而,模式2(又名“过滤器模式”)更有用,因为它允许您将特定的系统调用列入白名单。我的github页面上有一个proof of concept,它运行seccomp模式2中的程序,但允许它们使用printf和scanf,以及使用malloc/free分配内存。