背景
在参与开发的Java工程中,需要使用GraalVM执行用户输入的JS代码。这些代码是不可信的,可能存在恶意代码,因此需要限制执行代码时使用的各种资源。
在2023年6月发布的GraalVM企业版中,首次支持sandbox特性,支持限制CPU时间、堆内存、语句数量等条件。本文介绍在本地运行示例代码的过程,以及部分阅读源码的结果。
官方介绍文档:https://www.graalvm.org/latest/security-guide/polyglot-sandbox/
准备工作
- Windows 10系统
- 下载并配置最新版本的GraalVM企业版(社区版不支持沙箱功能)
测试代码与结果
使用单元测试执行以下代码,均抛出资源限制相关异常。
限制最大语句数量
@Test
public void testGraalSandboxMaxStatements() {
// 限制最大语句数量
try (Context context = Context.newBuilder("js")
.option("sandbox.MaxStatements", "2").option("sandbox.MaxCPUTime", "2s").build()) {
context.eval("js", "print('Hello JavaScript1!');print('Hello JavaScript2!');print('Hello JavaScript3!');");
}
}
限制CPU时间
@Test
public void testGraalSandboxMaxCPUTime() {
// 限制CPU时间
try (Context context = Context.newBuilder("js")
.option("sandbox.MaxCPUTime", "1s").build()) {
context.eval("js", "while(true){};print('hello')");
}
}
限制堆内存大小
@Test
public void testGraalSandboxMaxHeapMemory() {
// 限制堆内存大小
try (Context context = Context.newBuilder("js")
.option("sandbox.MaxHeapMemory", "10MB").build()) {
context.eval("js", "var r = {}; var o = r; while(true) { o.o = {}; o = o.o; };");
}
}
注意事项
- GraalVM的沙箱功能只能在企业版使用。GraalVM社区版和OpenJDK均无法使用。
部分源码
sandbox相关的源码在com.oracle.truffle.sandbox.enterprise
包中,估计被混淆了,无法查看。
计算堆内存的源码在类com.oracle.truffle.polyglot.PolyglotContextImpl
的calculateHeapSize
方法