why java security manager doesn’t forbid neither creating new Thread() nor starting 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")

Leave a Comment