I am playing around with the java .policy file and was wondering how I could go about doing something like preventing calls to java.util.Date(), as an example.
I just want to get a better sense of the .policy file works and how it can be used to sandbox code.
You'll be out of luck there I'm afraid.
As Paŭlo Ebermann says, package.access
can block out package hierarchies. You can be more precise about this with a custom SecurityManager
, which is usually a damn good indication you are doing something really dodgy.
In general you can make a ClassLoader
that doesn't always delegate to its parent. Technically against the current Java SE spec, although the Java EE spec encourages it. You could block out java.util.Date
. It's still accessible through reflection if any other class references it, or you can get an instance of it. You could block out the transitive closure of uses of Date
, including those that in some way return a Date
. However, to complete the scheme with your minimal date you'd have to load a java.util.Date
in your class loader, which you can't along with all other java.*
classes.
So, err, replace the java.util.Date
class in rt.jar (possibly using a Java Agent), and substitute in any class you don't want to restrict new Date()
with new Date(System.currentTimeMillis())
.
(Btw, +1 to anything that reduces the dependency on System.currentTimeMillis()
and other magic methods.)
To restrict access to certain packages, you have actually to change not the .policy
file, but the security.properties
. There is an entry package.access=...
which lists the packages for which RuntimePermissions are needed. So, you can't restrict specifically the access to a single class, only to a whole package (including subpackages, if needed), i.e. java.util
.
(You can alternatively access this by the Security.?etProperty
methods.)
If you did this, you later can add the right RuntimePermission to the Policy to let the "good" code use it.
I think quite a good part of the JRE would cease working if you restrict access to java.util, so better try another class for testing.
The way the sandbox mostly works is that there are calls from classes that do security-sensitive stuff to the current SecurityManager to check whether or not such a call should succeed. Since the Date class isn't perceived to be security-sensitive, no such calls exist in it's code and that's why - as explained by Tom and Paulo - it is very difficult to restrict it.
For example, in contrast: File operations are perceived to be security sensitive and that's why the File class has calls to the SecurityManager. As an example the delete method:
public boolean delete() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkDelete(path);
}
return fs.delete(this);
}
And thanks to the SecurityManager check in the File class you can restrict File delete operations in the .policy file with more ease.