Imposing constraints or restrictions on method body, in Java
Have a look at java policy files. I've not used them, and I'm not sure they'll fit your problem exactly, but with some digging into the docs they may be a fit. Here's a couple SO questions that may be of help
Limiting file access in Java
What is a simple Java security policy for restricting file writes to a single directory?
And here's some documentation on the policy file.
http://docs.oracle.com/javase/6/docs/technotes/guides/security/PolicyFiles.html
You can restrict the classes used by untrusted code with a custom class loader:
public class SafeClassLoader extends ClassLoader {
Set<String> safe = new HashSet<>();
{
String[] s = {
"java.lang.Object",
"java.lang.String",
"java.lang.Integer"
};
safe.addAll(Arrays.asList(s));
}
@Override
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
if (safe.contains(name)) {
return super.loadClass(name, resolve);
} else {
throw new ClassNotFoundException(name);
}
}
}
public class Sandboxer {
public static void main(String[] args) throws Exception {
File f = new File("bin/");
URL[] urls = {f.toURI().toURL()};
ClassLoader loader = new URLClassLoader(urls, new SafeClassLoader());
Class<?> good = loader.loadClass("tools.sandbox.Good");
System.out.println(good.newInstance().toString());
Class<?> evil = loader.loadClass("tools.sandbox.Evil");
System.out.println(evil.newInstance().toString());
}
}
public class Good {
@Override
public String toString() {
return "I am good";
}
}
public class Evil {
@Override
public String toString() {
new Thread().start();
return "I am evil.";
}
}
Running this will result in
I am good
Exception in thread "main" java.lang.NoClassDefFoundError: java/lang/Thread
at tools.sandbox.Evil.toString(Evil.java:7)
at tools.sandbox.Sandboxer.main(Sandboxer.java:18)
Caused by: java.lang.ClassNotFoundException: java.lang.Thread
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 2 more
Of course, this assumes care is taken with the classes you white list. It also can't prevent denial of service stuff such as
while (true) {}
or
new long[1000000000];
I think that the direction in this question is good.
- Use a specific
ClassLoader
lo load the class. Beware, that they're an interesting type of horse, it usually happens that the class itself is loaded by a parent classloader. Probably you want some sort of UrlClassLoader, and the parent classloader would be set to the Root classloader It is not enough, though. - Use
threads
to avoid infinite loops (rather implementingRunnable
than extendingThread
, like there) - this may be unnecessary if you're not worrying about it. - Use SecurityManager to avoid
java.io
operations
In addition to the above, I recommend 2 options:
Give the method a controller, that would contain the functions it can call
For example:
public void foo(Controller ctrl) {
}
public class Controller {
public boolean commit();
public boolean rollback();
}
This can give the user a handle, what operations are allowed.
Use an Intent
-like command pattern
In Android, the components of the system are quite closed. They cannot directly communicate to each other, they only can fire an event, that "this happened", or "I want to do that".
This way the set of the usable commands are not restricted. Usually, if the methods do only small business logic, that is enough.