如何在具有内存和时间限制的沙箱中运行不受信任的Groovy代码?

5

我正在创建一个能执行任何Groovy代码的程序(一个IRC机器人)。我知道如何通过使用SecurityManagers限制文件访问、线程等,但是我想要在脚本超出了128MB的内存使用或者执行时间超过3秒时杀死该脚本(以免有人运行while (true){})。这是我的代码:

private static Object eval(String code) {
    GroovyShell sh = new GroovyShell()
    return sh.parse(code).run()
}

我不想启动一个新的JVM,因为我希望将异常传递给主程序并传递实际对象而不是字符串(以便将来重用其他前端)。


你无法停止任意的Java线程,因此我认为唯一的方法是在单独的进程中生成它。 - pditommaso
1个回答

2

简短概述

只需在单独的进程中运行每个脚本。

在同一进程中运行的选项

有几个需要注意的事项。首先,将每个脚本放入其自己的类加载器中,该类加载器具有扩展类加载器或甚至是引导类加载器作为其父级。这是为了控制Groovy脚本对应用程序类的访问。

监视执行时间很容易。只需在其自己的线程中运行每个脚本,并在超过3秒限制时中断线程即可。但请记住,中断线程仅会引发InterruptedException异常,该异常可以在该线程内被捕获和处理。如果代码设计为从这些异常中恢复,则很难停止线程。

内存部分是真正崩溃的地方。 这个答案基本上说了所有需要说的 - 不可能。有人可以轻松地占用堆空间并使jvm崩溃。

在它们自己的进程中运行

最终,我真的建议只需在单独的进程中运行每个脚本。这样做有几个好处,其中最重要的是可以通过利用将其作为单独用户运行来对它们进行沙箱处理。这样,您可以从操作系统获得另一层保护。

此外,如果要将异常传递回主Java进程,则可以很容易地完成此操作,因为Exception实现了Serializable。这意味着您可以轻松地通过SocketChannel或HTTP将异常发送回主进程,序列化到文件,或使用任何协议。请参阅本文以获取有关Serialization的基本信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接