1

AccessController.doPriviliged() メソッドでスレッドの作成を禁止しようとしています。以下のメソッドは、スレッドを作成して実行します。これを -Djava.security.manager で実行します。このリンクによると、modifyThreadGroup が許可されていない場合、スレッドの作成は許可されませんか?

http://docs.oracle.com/javase/7/docs/technotes/guides/security/permissions.html

なぜこれが起こっているのか、そしてAccessControllerを使用してスレッドの作成を禁止する正しい方法について誰かが教えてくれますか?

// .java.policy in $UserHome:

grant codeBase "file:/C:/-" {
    permission java.security.AllPermission;
};


public class ThreadTest {
  public void testModifyThreadGroup() {

    // grant no permissions
    Permissions perms = new Permissions();

    ProtectionDomain domain = new ProtectionDomain(
            new CodeSource( null, (Certificate[]) null ), perms );
    AccessControlContext _accessControlContext = new AccessControlContext(
            new ProtectionDomain[] { domain } );

    try {
        AccessController.doPrivileged(new PrivilegedExceptionAction(){
            @Override
            public Object run() {
                try {
                    // modifyThreadGroup not granted, so should not be able
                    // to call Thread constructor???
                    Thread t = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println("Thread.run()");
                        }
                    });
                    t.run();
                } catch (Exception ex) {
                    System.out.println("Error running thread: " + ex);
                }
                return null;
        }}, _accessControlContext);
    } catch(Exception e) {
        System.out.println("Access Error running doPrivileged: " + e);
    }
  }
}
4

2 に答える 2

3

スレッドが作成または開始されたときに行われる唯一のチェックは、呼び出し元のスレッドがスレッド グループを変更する権限を持っているかどうかを確認することです。ご想像のとおり、これは、呼び出し元のスレッドに「modifyThreadGroup」権限があるかどうかを確認するためのものではありません。

代わりに、問題の ThreadGroup が「modifyThreadGroup」権限がチェックされるシステム スレッド グループでない限り、 (デフォルトで) 常にアクセスを許可します。問題の ThreadGroup がシステム スレッド グループであることはほとんどありません。

独自の実装で SecurityManager を拡張し、独自のチェックを行う必要があります。おそらく、独自の新しい許可を作成する必要があります。例として、既存のアクセス許可を使用してハックを実装しました。既定のポリシーが与えられた場合、スレッドが (exitVM) を持つことがわかっていました。

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;

public class QuickTest {

    public static class NoThreadsSecurityManager extends SecurityManager {

        public void checkAccess(ThreadGroup g) {
            super.checkAccess(g);
            checkPermission(new RuntimePermission("exitVM"));
        }

    }

    public static class SimpleRunnable implements PrivilegedExceptionAction<Object> {
        @Override
        public Object run() {
            try {
                Thread t = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("Thread.run()");
                    }
                });
                t.start();
                t.join();
            } catch (Exception ex) {
                System.out.println("Error running thread: " + ex);
            }
            return null;
        }
    }

    public void testModifyThreadGroup() {

        // grant no permissions
        Permissions perms = new Permissions();

        ProtectionDomain domain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), perms);
        AccessControlContext _accessControlContext = new AccessControlContext(new ProtectionDomain[] { domain });

        try {
            AccessController.doPrivileged(new SimpleRunnable(), _accessControlContext);
        } catch (Exception e) {
            System.out.println("Access Error running doPrivileged: " + e);
        }

        new SimpleRunnable().run();

    }

    public static void main(String[] args) {
        System.setSecurityManager(new NoThreadsSecurityManager());
        new QuickTest().testModifyThreadGroup();
    }

}
于 2013-07-08T22:07:43.330 に答える