Why can I get out of the restricted AccessControlContext with AccessController.doPrivileged?

I am figuring out how to run external code (from another JAR) without permissions so that it doesn't harm my own system. Almost everything works for me, but I came to find a weird situation where the call System.exit(0)

is still killing the whole system.

The idea is that various JAR files will be loaded into a multi-threaded environment, so it System.exit(0)

does well in the worst that can happen, among many other security threats on the server.

I have the following code (in SSCEE):

public class RestrictAccessControlContext {
    private static final PermissionCollection ALLOWED_PERMISSIONS = new Permissions();
    static {
        //add permissions
    }
    private static final AccessControlContext RESTRICTED_ACCESS_CONTROL_CONTEXT = 
        new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, ALLOWED_PERMISSIONS)});

    private static void executeSandboxed(final Runnable runnable) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<?> future = executorService.submit(() -> {
            AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
                runnable.run();
                return null;
            }, RESTRICTED_ACCESS_CONTROL_CONTEXT);
        });
        try {
            future.get();
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        } catch (ExecutionException ex) {
            throw new RuntimeException(ex.getCause());
        } finally {
            executorService.shutdown();
        }
    }

    public static void main(String[] args) {
        executeSandboxed(() -> {
            AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
                System.exit(0);
                return null;
            });
        });
    }
}

      

Who do you need to work with VM arguments:

-Djava.security.manager -Djava.security.policy = src / java.policy

Where java.policy

:

grant {
    permission java.security.AllPermission;
};

      

The idea is that my own code still has full permissions, but this sandboxed code has limitations (in this case: no).

However, in this example, it just exits, note that the following variations of the main method work:

public static void main(String[] args) {
    executeSandboxed(() -> System.exit(0));
}

      

and

public static void main(String[] args) {
    executeSandboxed(() -> new Thread(() -> System.exit(0)).start());
}

      

What am I doing wrong here, why is it possible to make a call AccessController.doPrivileged

that raises the permissions when they were restricted before? I expect to be one of the following:

  • There would be a special call permission AccessController.doPrivileged

    that could be specified.
  • In the block, the AccessController.doPrivileged

    permissions will be the intersection of the "parent" AccessControlContext

    and the given permission.

Both will result in the given code throwing correctly AccessControlException

, but it doesn't, why is it?

+3


source to share


1 answer


You don't have sandboxed code. Their code, which has full permissions, uses them. The code will not be able to exit without proper permission. The solution should be to load untrusted code with untrusted ProtectionDomain

.

Getting a permit for a permit would be pointless. This will be equivalent to having all the permissions.



Internally, there is a variant in OpenJDK doPrivileged

that allows for overlapping permissions, but is designed to reduce permissions when there are multiple sources of mistrust.

+1


source







All Articles