salmanahmad / silo

The Silo Programming Language
0 stars 0 forks source link

Try in Your Browser #29

Open salmanahmad opened 10 years ago

salmanahmad commented 10 years ago

Create a Silo REPL shell that allows developers to execute commands. The shell would also need to include a sandbox capability because I would want to deploy this shell interface over the Web for a "Try in your Browser".

Variables

The first challenge is supporting local variables in a sane way. One way that I could handle this is to macro expand the code and then re-write assignment nodes (=) so that they use a HashMapActor or something. This HashMap actor can be serialized and even stored in a cookie to reduce for the Web app.

Runtime

Each session should run in its own runtime so I can avoid name clashes.

Security

The first thing that I need to do is prevent against obvious security issues. I can do this by enabling sandboxing in the JVM with a security manager as described here:

http://stackoverflow.com/questions/502218/sandbox-against-malicious-code-in-a-java-application

In addition, I need to be wary of users that create threads. To prevent creating threads I need to look into ThreadGroups and setting the security manager to prevent new threads from being created.

This is a good start but I also need to be wary of run away code that could run in an infinite loop or attempt to allocate a huge amount of memory. To prevent this, I need to run each command on new thread with a timeout that is canceled after a certain amount of time. There are certain ways of doing this. One simple way is to use a Executors.newSingleThreadExecutor and Future#get(DURATION, TimeUnits.SECONDS) followed by a ExecutorService#shutdownNow(). The problem with shutdownNow() like here:

http://stackoverflow.com/questions/2275443/how-to-timeout-a-thread

However, we are not there yet. This only works if the user code pays attention to Thread.interrupt() and a malicious thread may ignore that. To avoid that we could use "Thread.stop()", which is deprecated but is an option, or we could macro expand the code and then insert if(thread.isInterrupted()) throw("foo"). Both of these work nicely, however, a malicious thread could still circumvent them by catching all exceptions (including the ThreadDead execution from Thread.stop()) and ignore it. Which leads us to our last security precaution a simple blacklist:

https://github.com/Raynes/tryclojure

https://github.com/Raynes/clojail/blob/master/src/clojail/testers.clj

Basically, we blacklist certain commands / forms that we do not like. The try-catch statement is one of those.

Fall Back

As a fallback, I should kill the JVM process every 20 minutes to ensure proper quality of service. To do this, I should have a Silo program that is monitoring another Silo program running in another JVM. This will avoid any run away threads that may be leaked.

Additionally, the Silo program should be run on a dedicated linux box that is disconnected from everything else (so SSH keys, etc). The OS user account should also be a low-priviledge user. This is not as simple as it may seem since I would want the process to be listening on port 80. Perhaps I create a Silo reverse proxy application (or just use nginx / haproxy which is less interesting).

salmanahmad commented 10 years ago

I am re-naming this issues for JUST the Try in Your Browser. I am opening another issue to track the progress on the actual REPL.