javasecuritymanagerjava-security-manager

A java SecurityManager that is identical to NO security manager except for a single check adjustment for System.exit


I am not well versed in java security managers and therefore want to confirm my understanding:

I have a java process that randomly stops (shutdown hook runs) even though there is no trace of someone killing it. As a result I decided to install a security manager and override checkExit(int status) to make sure the reason for the stop is not something calling System.exit(). Basically I wrote this:

            System.setSecurityManager(new SecurityManager() {
                @Override
                public void checkExit(int status) {
                    Thread.dumpStack();
                    super.checkExit(status);
                }
            });

I was expecting that my program would run as usual, with the only change being that a stack trace would be dumped if System.exit() was called. I found that this is NOT the case. It fails to start with this security exception:

java.security.AccessControlException: access denied ("java.util.PropertyPermission" "config" "read")
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472) ~[na:1.8.0_74]
        at java.security.AccessController.checkPermission(AccessController.java:884) ~[na:1.8.0_74]
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) ~[na:1.8.0_74]
        at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1294) ~[na:1.8.0_74]
        at java.lang.System.getProperty(System.java:717) ~[na:1.8.0_74]
        at Main.main(Main.java:161) ~[na:na]

It appears that the SecurityManager does NOT replicate the default behavior and after reading about it would seem that it applies the default policy under ${JAVA_HOME}/jre/lib/security/java.policy which is quite restrictive.

What is the real default behavior of Java when there is NO security manager? Is it to 'allow everything' or is there something else happening?

What should I install as a security manager if I wanted to replicate the default behavior, apart from that single adjustment above?

On that last point, I can see that System.setSecurityManager() actually expects an instance of java.lang.SecurityManager which means I am forced to use that implementation (that relies on policy files). What would be the most efficient way of overriding methods in that class to replicate the actual default behavior of NO security manager?

EDIT: As per the discussion below, this seems to do it

            System.setSecurityManager(new SecurityManager() {
                @Override
                public void checkPermission(Permission perm) {
                    return; // no security manager behaviour
                }

                @Override
                public void checkPermission(Permission perm, Object context) {
                    return; // no security manager behaviour
                }

                @Override
                public void checkExit(int status) {
                    Thread.dumpStack();
                    super.checkExit(status);
                }
            });

Solution

  • You are confused.

    It appears that the SecurityManager does NOT replicate the default behavior and after reading about it would seem that it applies the default policy under ${JAVA_HOME}/jre/lib/security/java.policy which is quite restrictive.

    The default behaviour of a SecurityManager is to obey the contract stated in the Javadoc, except as permitted by the default .policy file, which is indeed quite restrictive. The default behaviour in the absence of a security manager is to allow anything and everything.

    What is the real default behavior of Java when there is NO security manager? Is it to 'allow everything'

    Yes.

    or is there something else happening?

    No.

    What should I install as a security manager if I wanted to replicate the default behavior, apart from that single adjustment above?

    A security manager that does exactly that. If you want it to enforce nothing except the one override you have implemented, you have to provide empty overrides for all its other methods.