1

我正在尝试为不受信任的 java 代码编写沙箱。
我使用java编写了沙箱。沙盒需要:

  1. 限制不受信任代码的内存使用。如果不受信任的代码使用的内存超过指定的限制,沙箱应该终止程序。
  2. 如果不受信任的代码没有超过指定的限制,沙箱也应该能够确定使用的“最大内存峰值”。

顺便说一句,当我在这里说内存时,它的意思是堆+非堆内存。

我发现您可以设置内存阈值并在内存池之一超过阈值时收到通知。但这不是我想要的,因为我想设置 Heap + Non-Heap 内存的限制。

我目前唯一的解决方案是每小毫秒轮询一次,使用来自 MemoryMXBean 的 getHeapMemoryUsage() 和 getNonHeapMemoryUsage() 获取堆+非堆内存并检查它是否超过了限制。

但我知道这个解决方案也绝对不好(并且有缺陷)。还有其他更好的解决方案吗?

4

2 回答 2

5

单个 JVM 在所有线程之间有一个共享堆。您不能“沙盒”内存。如果您希望管理每个应用程序的内存,则必须运行一个单独的进程。

现在,如果您想限制整体内存(堆 + 非堆),您可以通过JNA调用系统函数setrlimit(如果您正在运行 Linux) ,或者您可以在运行 Java 进程之前调用ulimit 。

要了解您的进程正在使用多少内存,请从ManagementFactory.getOperatingSystemMXBean()获取 CommittedVirutalMemorySize 属性(但没有获取器)。

如果您想收到即将关闭的通知,请使用 setrlimit/ulimit 的软限制。您的进程将定期收到超出软限制的信号。如果您设置了硬限制并且超过了该限制,则该进程将被终止。

编辑:添加了关于获取内存大小和 setrlimit 信号的段落。

于 2012-12-14T04:15:13.280 回答
1

我认为如果没有深奥的魔法,这是不可能的:要么重写不受信任代码的字节码,要么修改底层 JVM 以跟踪内存使用情况。

作为一个实验,我已经实现了前者(重写字节码),以限制不受信任代码的内存分配(和指令消耗),使用-javaagents 在加载时重写 java 类的字节码并插入检查在每次内存分配之前。

有了这个,我们可以调用一个函数并将该函数(以及它调用的任何东西)限制为,例如 1024 字节的内存分配和 10000 条指令,如果它超出,就会导致它抛出异常。kinda-sorta 工作代码可在

https://github.com/lihaoyi/6858

tl; 博士:这该死的很难。并非不可能,但如果你有截止日期,你不会尝试这样做,如果你真的能做到,你可能会发表一篇会议论文。

于 2012-12-30T04:42:47.483 回答