What is privileged code?

It allows you to temporarily grant permission to code that would normally not have permission to run. Normally, the entire execution stack (all callers) needs to have permission to do a sensitive operation.

With Privileged Code, you can specify in a fine-grained way that only the final class in the execution stack needs permission.

For example, consider the following two classes.

Main.java:

public class Main
{
   public static void main(String []args) {
      LowLevel.executeLowLevelAction();
   }
}

LowLevel.java:

public class LowLevel
{
   public static void executeLowLevelAction() {
      System.out.println(System.getProperty("test"));
   }
}

The Main class just executes the static method executeLowLevelAction that gets the property
test.
Run log:

C:> java -Dtest="Hello, World!" Main
Hello, World!
 
C:> java -Dtest="Hello, World!" -Djava.security.manager Main
Exception in thread "main" java.security.AccessControlException: access denied
java.util.PropertyPermission test read)
        at java.security.AccessControlContext.checkPermission(AccessControlCont
xt.java:195)
        at java.security.AccessController.checkPermission(AccessController.java
403)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
        at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1
43)
        at java.lang.System.getProperty(System.java:539)
        at LowLevel.executeLowLevelAction(LowLevel.java:6)
        at Main.main(Main.java:4)

As you expected, the first run can just get the property test without needing any permissions (as no security manager is installed by default). In the second run, we ask the VM to set up a default SecurityManager which results in an AccessControlException because reading System Property “test” is not allowed.

To grant permission to read this property, we need to write a policy security configuration file. But we really only want the class LowLevel to have permission to read the property. We do not want to grant the calling class Main that permission.

So what we could do is jar the LowLevel class up and write a policy file to grant that jar file additional permissions:

C:> jar cvf LowLevel.jar LowLevel.class
added manifest
adding: LowLevel.class(in = 474) (out= 308)(deflated 35%)

C:> del LowLevel.class

mypolicy:

grant codeBase "file:/c:/LowLevel.jar" {
   Permission java.util.PropertyPermission "test", "read";
};

Run log:

C:> java -Dtest="Hello, World!" -Djava.security.manager 
          -Djava.seurity.policy=mypolicy Main
 
Exception in thread "main" java.security.AccessControlException: access denied
java.util.PropertyPermission test read)
        at java.security.AccessControlContext.checkPermission(AccessControlCont
xt.java:195)
        at java.security.AccessController.checkPermission(AccessController.java
403)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
        at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1
43)
        at java.lang.System.getProperty(System.java:539)
        at LowLevel.executeLowLevelAction(LowLevel.java:6)
        at Main.main(Main.java:4)

AccessControlException!!? How come? Didn’t we grant the permission to LowLevel.jar to read the property “test”? The problem lays in the requirement that every class in the execution stack must have the permission.

The solution is to make the System.getProperty call in a Privileged Block. This could be done as follows.

LowLevel.java:

import java.security.*;
 
public class LowLevel
{
   public static void executeLowLevelAction() {
      String testprop = (String) AccessController.doPrivileged(new PrivilegedAction() {
         public Object run() {
            return System.getProperty("test");
         }
      });
      System.out.println(testprop);
   }
}

Compile and jar it up:

C:> javac LowLevel.java

C:> jar cvf LowLevel.jar LowLevel.class LowLevel$1.class
added manifest
adding: LowLevel.class(in = 603) (out= 384)(deflated 36%)
adding: LowLevel$1.class(in = 449) (out= 307)(deflated 31%)
 
C:> del LowLevel*.class

and run it again:

C:> java -Dtest="Hello, World!" -Djava.security.manager -Djava.sec
urity.policy=mypolicy Main
Hello, World!

Now we get the correct response: allowing only the class LowLevel to run “sensitive” code, no matter who called it, so without worrying about the executing stack.