13

您是否知道解释为什么 java 安全管理器不禁止创建新线程或启动它们?new FileWriter 在安全管理器下,但 new Thread() 和 threadInstance.start() 都不是安全管理器下的,并且可以调用。

  1. 禁止它不是有用吗?
  2. 实施起来会不会很困难?
  3. 或者创建和启动新线程与禁止它无关?
4

2 回答 2

20

使用标准 Java SecurityManager 定义阻止代码创建和启动新线程的安全策略是不可能的。

假设您有以下代码:

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();
  }
}

并使用以下命令运行它:

java -Djava.security.manager -Djava.security.policy==/dev/null Test

它会运行得很好并输出:

Secure
Ran

即使我们将安全策略设置为 /dev/null,这将对任何代码授予零权限。因此,不可能授予更少的权限来阻止代码创建该线程。

这是因为标准 java.lang.SecuritManager 仅在代码尝试在根 ThreadGroup 中创建线程时执行权限检查。同时,SecurityManager 的 getThreadGroup 方法总是返回当前 Thread 的线程组,它永远不会是根线程组,所以总是会授予创建新 Thread 的权限。

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")
于 2015-06-25T01:59:30.343 回答
3

在 Thread 构造函数中执行访问检查,以查看调用者是否有权更改将添加新线程的 ThreadGroup。这就是您将如何实施安全策略以禁止创建新线程的方式。

(还有另一个检查 ThreadGroups 的创建...检查您是否有权将新组添加到其父组。)

所以回答你的问题:

为什么 java 安全管理器既不禁止创建 new Thread() 也不禁止启动它?

原因是您的 JVM 当前的安全策略允许父线程修改其ThreadGroup. 您应该能够修改该策略设置以防止这种情况发生,从而防止创建子线程。

禁止它不是有用吗?

这是。允许不受信任的代码创建/启动线程是不明智的,因为:1)一旦启动的线程就不能被安全地杀死,以及 2)创建/启动大量线程会使 JVM(可能还有操作系统)陷入困境。

实施起来会不会很困难?

从您的角度来看,只需更改政策即可。

于 2013-04-07T22:51:37.443 回答