静态与动态链接沙盒

2 投票
3 回答
1107 浏览
提问于 2025-04-17 14:28

我在我的项目中尝试使用 libsandbox。我可以在这个沙盒里完美地运行 C/C++ 程序。

为了运行 C/C++ 程序,首先我需要将代码编译成:

g++  -lm  --static  <filename>  2> err.txt

然后,我需要用上面编译好的代码运行 示例沙盒程序

请注意,我上面使用的标志 --static 是非常重要的。这个 --static 的重要性在以下两个 StackOverflow 的回答中体现得很清楚 链接1链接2

现在,我想把这个沙盒也用在 Java 和 Python 上。

但是我不知道 Python 和 Java 中与 gcc/g++ --static 相对应的选项是什么。

下面的代码能行吗?

  javac --static    <filename>  2> err.txt 

  python  --static  <filename>  2>err.txt

我再说一遍,我很困惑,因为我不知道 Java 或 Python 中 --static 的对应选项。

谢谢!

3 个回答

-2

对于Java来说,似乎你唯一的选择就是使用一个叫做JNI的包装器,它是静态绑定的。可能已经有这样的包装器了,但如果没有的话,你可以自己写一个。

3

我觉得你把两件事情搞混了。你的Python程序并不是libsandbox所说的可执行文件。可执行文件是Python解释器。

所以,你不能用libsandbox来对一个Python脚本进行沙箱处理。

不过,你可以对Python解释器进行沙箱处理。你可以用和处理其他可执行文件相同的方法来做到这一点。具体来说,有两种方式:

  • 创建一个静态构建的Python解释器(把你需要的C扩展模块编译进去),然后在沙箱中运行它。这并不简单,但可以做到,Python源代码中和其他地方有一些信息可以帮助你。
  • 使用一个更宽松的沙箱,允许标准解释器做它需要做的事情(这可能包括动态加载扩展模块,具体取决于你是否需要这样做),但不允许其他的。

无论哪种方式,你都需要一些试验和错误来弄清楚哪些操作可以禁止,哪些不可以,以及如何将不同的Python代码映射到系统调用等等。而且,有些事情你是无法阻止你的脚本去做的,因为你不希望Python代码执行的系统调用对于解释器本身是必要的。

Java也是类似的情况。JVM是可执行文件,而不是你的程序。而且你真的不能静态链接JVM,所以你只能选择第二种方式。

当然,除非你使用gcj将你的Java代码编译成本地代码,而不是JVM代码。在这种情况下,你实际上使用的是和gccg++相同的后端,只需使用--static确保libgcj和其他所有内容都被静态链接。你可能仍然会遇到问题,因为libgcj在背后做的事情比libc多得多……但这个概念和C代码是一样的。

(JVM本身有自己的访问模型,你可以假设使用反射在类加载器中构建一些东西,以在Java API的层面上对Java程序进行沙箱处理,而不是Linux系统调用API。我不知道是否已经存在这样的东西。)


每当我尝试编译我想在沙箱中运行的程序时,如果不加“--static”,沙箱就无法工作。所以,再次强调,--static是非常关键的,这超出了我的知识范围。

很可能,你的实际代码并没有打开任何文件,所以你使用的是默认的沙箱设置,这禁止打开文件。但是如果你动态链接你的程序,它就必须打开.so文件来进行链接——这就不行,因为你的沙箱配置是禁止这样做的。

如果你静态链接同样的程序,这个问题就解决了,因为它不再需要打开任何.so文件来运行。简单来说,这就是静态链接在沙箱处理中的意义。你甚至在你问题的评论中解释过这一点,所以我无法想象你怎么会不理解,除非你根本不明白为什么要禁止SYS_open以及这样做的意义。

(a) 对于Java和Python,如果我不加“--static”编译,沙箱会有效吗?

是的,沙箱会正常工作。这意味着,如果你使用默认配置,它会禁止你打开文件。这意味着你的Java或Python程序会失败,因为虚拟机/解释器必须打开(除了其他事情)你的程序来运行它。

即使静态链接解释器或JVM也无济于事。你必须将你的程序的实际字节码静态链接到可执行文件中。这并不是不可能,但可能超出了你现在想要考虑的范围。

正确的做法是弄清楚你想禁止哪些系统调用,以及为什么要禁止它们,并相应地配置沙箱。默认配置对你来说是行不通的。

(b) 有一个叫做pysandbox的沙箱,由同一个开发者提供,地址是openjudge.net/~liuyu/Project/LibSandbox

pysandbox只是一个更简单的配置和启动沙箱的方法。你不会在沙箱代码内部使用它。(还有一个由其他开发者提供的pysandbox,它在Python层面上对你的代码进行沙箱处理。这可能对你有用,但与系统调用沙箱不是同一回事。)


在这一点上,我不确定你是否知道自己在做什么。你为什么想要对你的代码进行沙箱处理?你知道你的代码需要什么样的访问权限才能完成它需要做的事情吗?如果你知道自己在做什么,你确定系统调用级别的沙箱是强制执行的正确层面,而不是像RestrictedPython这样的东西吗?如果不知道你的实际使用案例,我甚至无法猜测这些问题的答案。但是如果你对这些问题没有立即的答案,你就无法完成任何有用的事情。

3

可以使用 libsandbox 来对 Python 解释器进行沙箱处理。沙箱处理就是限制程序的权限,让它不能随便做一些事情,比如加载共享库和导入默认的 Python 模块。你可以在 Richard Lobb 的 CodeRunner 项目中找到一个在 Python3 解释器上运行的示例。

https://github.com/trampgeek/CodeRunner

Java 自己有安全机制,所以不需要把 Java 虚拟机放在沙箱里。

免责声明:我是 libsandbox 的作者。

撰写回答