14

I'm trying to get myself familiar with the SecurityManager but even this simple scenario fails. When I run the following from inside my IDE or from command line I get the following exception;

access denied ("java.util.PropertyPermission" "java.home" "read")

I thought I allowed everything with this code:

Policy.setPolicy(new Policy() {

    @Override
    public PermissionCollection getPermissions(CodeSource codesource) {
        Permissions perm = new Permissions();
        perm.add(new AllPermission());
        return perm;
    }
});
System.setSecurityManager(new SecurityManager());
System.out.println(System.getProperty("java.home"));

Has this something to-do with the derived policy from the JVM? How can I cleanly setPolicy()?

The same misunderstanding seems to happen for the following code:

System.setSecurityManager(new SecurityManager());
final Permissions allPermission = new Permissions();
allPermission.add(new AllPermission());
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
    System.out.println(System.getProperty("java.home"));
    return null;
}, new AccessControlContext(new ProtectionDomain[]{new ProtectionDomain(null, allPermission)}));

Update: the second case is understandable as the provided permission is only a further restriction: (javadoc) The action is performed with the intersection of the permissions possessed by the caller's protection domain, and those possessed by the domains represented by the specified AccessControlContext

buræquete
  • 14,226
  • 4
  • 44
  • 89
Karussell
  • 17,085
  • 16
  • 97
  • 197
  • I'm trying to increase security of my java application and for that I need to understand the mechanisms. Just enabling the SecurityManager is not possible as I need a few exceptions. I have to understand a bit more how this all works together as it is not a standard use case. – Karussell Nov 07 '18 at 21:30
  • I'm unable to reproduce this (tried on JDK 8 and 11). I doubt the default policy implementation to be the cause. Something non-standard interposes between the security manager and your custom policy, effectively preventing or overriding queries to the latter; e.g. a custom class loader having assigned a [static](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/security/ProtectionDomain.html#%3Cinit%3E(java.security.CodeSource,java.security.PermissionCollection)), unprivileged protection domain to your classes. – Uux Nov 07 '18 at 21:46
  • @Uux Thanks a lot for taking the time. So in your case you can access the java.home property? If yes, can you gist your policy file? – Karussell Nov 08 '18 at 09:18
  • 1
    @Karussell Yes, your snippet runs just fine (within a plain old `main` method, launched via plain old `java -cp `). I didn't modify my .policy file, because it ultimately doesn't matter -- once `Policy.setPolicy` has returned, it is *your* policy implementation that gets consulted, not the previous, default, file-backed one. You might want to try running with `-Djava.security.debug="access,failure"` and attach its output to your question. – Uux Nov 08 '18 at 12:22
  • I now better understand what I was trying to achieve: I want a programmatic way to set the policy where I see that if I set no permision then the System.getProperty call fails and if I grant PropertyPermission or AllPermission then the call goes through. And indeed the 2nd part works now (no idea why) but the 1st part goes through without any permission. And when I do Policy.getPolicy exactly the opposite happens (both parts fail,) – Karussell Nov 09 '18 at 10:16
  • Related but not quite duplicate question: https://stackoverflow.com/questions/31458821/policy-setpolicy-doesnt-seem-to-work-properly – Caesar Apr 26 '22 at 07:57

3 Answers3

15

I was able to recreate your case with an extra Policy.getPolicy() before the Policy.setPolicy() call, the reason why it affects the behaviour is that with the get policy call, you trigger a default policy creation, and permissions from java.policy are set, but without a setSecurityManager() they are not activated, that is the reason when you do a custom AllPermission policy set, you still get a "java.util.PropertyPermission" "java.home" "read" issue, for many of such default policies are not overridden with the set policy. Very confusing structure indeed.

Policy.getPolicy();
Policy.setPolicy(policyWithAllPermission);
System.setSecurityManager(new SecurityManager());
System.out.println(System.getProperty("java.home"));
// results in 'access denied ("java.util.PropertyPermission" "java.home" "read")'

But if you use the following custom policy;

Policy allPermissionPolicy = new Policy() {

    @Override
    public boolean implies(ProtectionDomain domain, Permission permission) {
        return true;
    }
};

It overrides all permission definitions, and lets all actions through, a possible fix for this confusion.

buræquete
  • 14,226
  • 4
  • 44
  • 89
  • 2
    Turns out you were intuitively on the right track from the very beginning (extra credit for having caught the OP's reference of calling `getPolicy` in addition to, and prior to, `setPolicy`, in the comments)! As for the *"why, exactly"* part of the story, see source of `java.security.Policy#initPolicy`. – Uux Nov 10 '18 at 15:48
1

In which context are you running your code above ?

from command line with a simple JVM or inside a webapp running on top of some JavaEE container? On which OS? with which JVM (Oracle, OpenJDK, IBM J9...) and which version?

If you're running from command line, have a look at the java.policy file located in your JVM installation path. Its content may narrow your grants and thus prevent you from accessing this particular system variable ?

buræquete
  • 14,226
  • 4
  • 44
  • 89
Michael Zilbermann
  • 1,398
  • 9
  • 19
  • Have updated my question. So the policy file overwrites Policy.setPolicy? If this is really the case the javadocs for this method are more than misleading IMO. – Karussell Nov 07 '18 at 10:46
0

Eventually, if you need SecurityManager that will allow everything, just use this:

System.setSecurityManager(new SecurityManager() {
    @Override
    public void checkPermission(Permission perm) {
    }

    @Override
    public void checkPermission(Permission perm, Object context) {
    }
});
msangel
  • 9,895
  • 3
  • 50
  • 69