Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I run untrusted Groovy code in a sandbox with memory and time limits?

I'm creating something that will take arbitrary Groovy code and execute it (an IRC bot). I know how to sandbox file access, threads, etc, with SecurityManagers, but I want to have the script killed if it goes over 128 MB of RAM use or 3 seconds of execution time (so nobody makes it run while (true){}). Here's my code:

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

I really don't want to spawn a new JVM as I would like to have exceptions passed to the main program and actual objects passed instead of strings (to re-use if I ever intend to make other front-ends).

like image 364
CrateMuncher Avatar asked Oct 31 '22 20:10

CrateMuncher


1 Answers

tl;dr

Just run each script in a separate process.

Options for running withing the same process

There's a couple of things to look at. The first would be to put each script into it's own classLoader that has the Extensions ClassLoader or maybe even the Bootstrap classloader as it's parent. This is to control the groovy script's access to your application's classes.

Monitoring the execution time is easy. Just run each script in it's own thread and interrupt the thread if it goes over the 3 second limit. Keep in mind, though, that interrupting the thread simply raises an InterruptedException, which can be caught and handled within that thread. It's not easy to stop a thread if the code is designed to recover from those exceptions.

The memory part is where things really fall apart. This answer pretty much says everything that needs to be said about that - not possible. Somebody could easily run you out of heap space and crash the jvm.

Running in their own processes

Ultimately, I would really recommend just running each one in a separate process. There's a couple of benefits to this, not the least of which being that it's way easier to sandbox them by taking advantage of running them as a separate user. That way you can get another level of protection from the OS.

Also, if you want to pass exceptions back to the main java process, this can be done pretty easily because Exception implements Serializable. This means that you can easily send the Exception back to the main process over a SocketChannel, or by http, serializing to a file, or using whatever protocol you want. Take a look at this article for some basic info in Serialization.

like image 177
allTwentyQuestions Avatar answered Nov 09 '22 08:11

allTwentyQuestions