why java security manager doesn't forbid neither creating new Thread() nor starting it?
Asked Answered
D

2

13

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.

  1. Wouldn't it be usefull to forbid it ?
  2. Would it be hard to implement ?
  3. Or creating and starting new Thread isn't so relevant to forbid it?
Depilate answered 7/4, 2013 at 22:20 Comment(2)
Which programming language?Corfu
java, I added to topic and description.Depilate
F
20

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")
Freckle answered 25/6, 2015 at 1:59 Comment(0)
D
3

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.

Dilks answered 7/4, 2013 at 22:51 Comment(5)
There are lots of ways of brings a JVM to its knees. You are going to need to give untrusted code access to at least some threads. It's kind of quite useful to be able to create threads.Insolvable
@Tom You don't generally need to grant access to threads, but in that case you often have to grant access to replacement facilities. It wouldn't be so bad, except that Java's asynchronous IO handling still isn't very strong.Ladd
what is the scenario in which I can receive exception when creating new thread under security manager? I have tried in my own main java -Djava.security.manager -Djava.security.policy=app.policy -cp bin pl.com.App with empty app.policy, and under Tomcat with (-security enabled) in my servlet (in catalina.policy there is no Thread permission) but I always can create and start new thread without exception.Depilate
"The reason is that your JVM's current security policy allows the parent thread to modify its ThreadGroup" -- where is it documented ? default policymanager attitude in most cases is to forbid everything that is not explicitly allowedDepilate
The security check is documented here: docs.oracle.com/javase/6/docs/api/java/lang/…Dilks

© 2022 - 2024 — McMap. All rights reserved.