Implementing an execution timeout.
Would it be possible to implement a timeout for running a function? I'm running untrusted, sandboxed code, and I need the execution of functions to be limited. Do you have some pointers as to how this could be achieved?
No idea, never needed this.
skorokithakis, I recommend you look into my HardLupa project. It's for exactly this type of thing, and runs code with a stripped down set of libraries in a separate process. It's still in early development, so it doesn't have timeouts built in yet, but it does have placeholders for where they will be implemented. If you're up for it, it probably won't be too hard to do that little patch yourself! I'd certainly pull any changes to that effect.
You likely also want to use this if what you're after is a sandbox:
https://github.com/scoder/lupa#restricting-lua-access-to-python-objects
@campadrenalin, thanks for that, it looks ideal. C is not my strong suit, but I'll have a look and see if I can do something about it. Right now I just use the resource module, limiting CPU and RAM, but it kills the Python process if the limits get exceeded, so it's not very graceful.
@scoder Thanks, the project doesn't really have to access any Python objects (I remove them from the sandbox) but I implemented that just in case. Do you know if it's possible to execute bytecode with Lupa? I'd hate to have a vulnerability that way...
Thanks, scoder! While I wasn't planning on supporting anything fancier than raw values, this is a necessity if I ever extend it to do so.
I would really need this. What's the odds this will require a separate thread running Lua?
Fairly low, but that's just a guess. Threads never work for these things. I would expect Lua to support something like this somehow, at least within limits. This looks relevant at first sight, for example:
http://lua-users.org/lists/lua-l/2006-10/msg00758.html
A quick web search should bring more answers. If you want full safety and control, only a separate process can give you that, which you can kill at any time.
The feature originally requested can be achieved using the count parameter of debug.sethook. (One could check the clock time every so often, or just bound the total number of instructions allowed in the sandbox.)
There are two issues, however:
- AFAICT there's nothing the hook function could do do interrupt the Lua interpreter other than raising a Lua error or a Python exception. Therefore, the sandboxing only works if
pcallandxpcallare hidden from the user. This could be fixed in lupa, by providing a suitable method to stop the interpreter. - The debug hook is not inherited by coroutines, so care needs to be taken with the the
coroutinetable: either exclude it from the sandboxed environment, or patch the coroutine creation functions... Perhaps there is some other better approach.
What do you think about the first point?