Policy.setPolicy() doesn't seem to work properly
Asked Answered
L

1

2

I want to set a custom Policy by defining my own class that extends the Policy class as follows:

public class MyPolicy extends Policy {

    public MyPolicy() {
        super();
    }

    @Override
    public PermissionCollection getPermissions(ProtectionDomain domain) {
        // return PermissionCollection with no permissions
        PermissionCollection pc = new PermissionCollection();
        return pm;
    }
}

Then, at the beginning of my application I set the my custom Policy class and I also enable the SecurityManager so that the new policy is in effect:

Policy.setPolicy(new MyPolicy());
System.setSecurityManager(new SecurityManager());

The problem with the above is that it doesn't work. The idea of the above example is to introduce a Policy that will prevent the application from doing anything that would require any kind of permission. So, for example, when I my application executes:

System.getenv();

I expect the above to result in AccessControlException that should be thrown by the SecurityManager. Instead, my application runs just fine. However, when I initialize the Policy and the SecurityManager as follows:

// setting the policy twice intentionally 
Policy.setPolicy(new MyPolicy());
Policy.setPolicy(new MyPolicy());
System.setSecurityManager(new SecurityManager());

Then executing System.getenv() actually results in the expected AccessControlException.

Here are my questions/concerns that I'd like to get an explanation on:

  • why do I have to set a Policy twice to make the Policy be in effect after setting the SecurityManager?
  • is it above issue some kind of bug or was the Policy class intentionally design to behave this way (if so - why?)?
Letaletch answered 16/7, 2015 at 15:44 Comment(1)
Related but not quite duplicate question: #53143574Decor
N
2

There are "interesting" problems dealing with the stack inspection-based security mechanism when parts of the implementation itself may not be trusted. It's a lot easier when it is implemented with bootstrap classes as the checking is bypassed for the null class loader.

When you setPolicy for the first time, the ProtectionDomain of the Policy implementation is given all permissions. So all your code is privileged - not what you wanted.

For subsequently setPolicy calls, the previous Policy supplies the permissions of the Policy implementation ProtectionDomain. In your case that causes all your code to have your empty PermissionCollection permissions. (You should probably call setReadOnly on this - nasty API. Also it's an abstract class, so should not compile.)

So, you'd probably want to use separate class loader to load your untrusted code and your security mechanism.

Only you've probably gone and broken lots of things by assuming nothing has any permissions. Boot classes get a pass because of their null class loader. For instance, loading classes probably requires permissions, so you don't want to be denying everything there.

Much better to use the normal policy file configuration to configure policy.

Nibble answered 16/7, 2015 at 17:23 Comment(2)
Thanks for the answer! You're right - the above code won't compile, instead of "PermissionCollection" I meant "Permissions". I made the above example only to illustrate the issue, so having no permissions on anything was my point. You said that boot classes get a pass because of Bootstrap classloader - can you explain this a little further? Why would they get a pass despite the fact that the application has no permission at all?Letaletch
@pgbus Boot classes have a null ProtectionDomain. So it's not possible to call ProtectionDomain.implies.Nibble

© 2022 - 2024 — McMap. All rights reserved.