why java security manager doesn't forbid neither creating new Thread() nor starting it?
do you happen to know explanation why java security manager doesn't forbid creating new threads or starting them? new FileWriter is under security manager, but neither new Thread(), nor threadInstance.start() isn't uneder security manager, and are possible to call.
- Wouldn't it be usefull to forbid it ?
- Would it be hard to implement ?
- Or creating and starting new Thread isn't so relevant to forbid it?
It isn't possible to define a security policy that will prevent code from creating and starting a new thread using the standard Java SecurityManager.
Let's say you have the following code:
public class Test {
public static void main(String [] args) {
System.out.println(System.getSecurityManager() != null ? "Secure" : "");
Thread thread = new Thread(
new Runnable() {
public void run() {
System.out.println("Ran");
}
});
thread.start();
}
}
and you run it with the following command:
java -Djava.security.manager -Djava.security.policy==/dev/null Test
it will run just fine and output:
Secure
Ran
even though we set the security policy to /dev/null, which will grant zero permissions to any code. It's therefore impossible to grant fewer permissions to prevent the code from creating that thread.
This is because the the standard java.lang.SecuritManager only performs an permission check if code tries to create a thread in the root ThreadGroup. At the same time, the SecurityManager's getThreadGroup mehtod always returns the current Thread's thread group, which will never be the root thread group, so permission to create a new Thread will always be granted.
One way to get round this is to subclass java.lang.SecurityManager and override the getThreadGroup method to return the root ThreadGroup. This will then allow you to control whether code can create threads based on whether it has the java.lang.RuntimePermission "modifyThreadGroup".
So if we now define a subclass of SecurityManager as follows:
public class ThreadSecurityManager extends SecurityManager {
private static ThreadGroup rootGroup;
@Override
public ThreadGroup getThreadGroup() {
if (rootGroup == null) {
rootGroup = getRootGroup();
}
return rootGroup;
}
private static ThreadGroup getRootGroup() {
ThreadGroup root = Thread.currentThread().getThreadGroup();
while (root.getParent() != null) {
root = root.getParent();
}
return root;
}
}
and then run our command again, but this time specifying our subclassed ThreadSecurityManager:
java -Djava.security.manager=ThreadSecurityManager -Djava.security.policy==/dev/null Test
We get an exception in our Test class when we try to create the new thread:
Exception in thread "main" java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup")
There is an access check performed in the Thread constructor to see if the caller has permission to change the ThreadGroup that the new thread would be added to. That is how you would implement a security policy to forbid creation of new threads.
(And there is another check on the creation of ThreadGroups ... that checks if you have permission to add the new group to its parent.)
So to answer your questions:
Why java security manager doesn't forbid neither creating new Thread() nor starting it?
The reason is that your JVM's current security policy allows the parent thread to modify its ThreadGroup
. You should be able to modify that policy setting to prevent that, and hence prevent creation of child threads.
Wouldn't it be useful to forbid it?
It is. It is unwise to allow untrusted code to create / start threads because: 1) threads once started cannot be safely killed, and 2) creating / starting lots of threads can bring the JVM (and maybe the OS) to its knees.
Would it be hard to implement?
From your perspective, just change the policy.