Documentation Contents

# API for Privileged Blocks

This document provides background information about what privileged code is and what it is used for, followed by illustrations of the use of the API. It covers the following topics:

- What It Means to Have Privileged Code
- Using the doPrivileged API
  - No Return Value, No Exception Thrown
  - Returning Values
  - Accessing Local Variables
  - Handling Exceptions
  - Asserting a Subset of Privileges
    - Least Privilege
    - More Privilege
- Reflection

## What It Means to Have Privileged Code

The policy for a JDK installation specifies what permissions — which types of system resource accesses — are allowed for code from specified code sources. A code source (of type `CodeSource`) essentially consists of the code location (URL) and a reference to the certificates containing the public keys corresponding to the private keys used to sign the code (if it was signed).

The policy is represented by a `Policy` object. More specifically, it is represented by a `Policy` subclass providing an implementation of the abstract methods in the `Policy` class (which is in the `java.security` package).

The source location for the policy information used by the `Policy` object depends on the `Policy` implementation. The `Policy` reference implementation obtains its information from policy configuration files. See Default Policy Implementation and Policy File Syntax for information about the `Policy` reference implementation and the syntax that must be used in policy files it reads. For information about using the Policy Tool to create a policy file (without needing to know the required syntax), see the Policy Tool documentation (for Unix) (for Windows).

A protection domain encompasses a `CodeSource` instance and the permissions granted to code from that `CodeSource`, as determined by the security policy currently in effect. Thus, classes signed by the same keys and from the same URL are typically placed in the same domain, and a class belongs to one and only one protection domain. (However, classes signed by the same keys and from the same URL but loaded by separate class loader instances are typically placed in separate domains.) Classes that have the same permissions but are from different code sources belong to different domains.

Currently, all classes shipped with the JDK are loaded with all permissions (this may change in future releases). Most of these classes are placed in a unique system domain. In addition, the extension class loader loads code from JAR files contained in the `$JAVA_HOME/jre/lib/ext` directory into separate domains (because the code in these JAR files have unique URLs), but these domains are separate from the unique system domain reserved for classes shipped with the JDK.

Each applet or application runs in its appropriate domain, determined by its code source. For an applet (or an application running under a security manager) to be allowed to perform a secured action (such as reading or writing a file), the applet or application must be granted permission for that particular action.

More specifically, whenever a resource access is attempted, all code traversed by the execution thread up to that point must have permission for that resource access, unless some code on the thread has been marked as privileged. That is, suppose that access control checking occurs in a thread of execution that has a chain of multiple callers. (Think of this as multiple method calls that potentially cross the protection domain boundaries.) When the `AccessController`.`checkPermission` method is invoked by the most recent caller, the basic algorithm for deciding whether to allow or deny the requested access is as follows: If the code for any caller in the call chain does not have the requested permission, then an `AccessControlException` is thrown, unless the following is true: a caller whose code is granted the said permission has been marked as privileged, and all parties subsequently called by this caller (directly or indirectly) have the said permission.

Note that the method `AccessController.checkPermission` is normally invoked indirectly through invocations of specific `SecurityManager` methods that begin with the word `check` such as `checkConnect` or through the method `SecurityManager.checkPermission`. Normally, these checks only occur if a `SecurityManager` has been installed; code checked by the `AccessController.checkPermission` method first checks if the method `System.getSecurityManager` returns null.

Marking code as privileged enables a piece of trusted code to temporarily enable access to more resources than are available directly to the code that called it. This is necessary in some situations. For example, an application might not be allowed direct access to files that contain fonts, but the system utility to display a document must obtain those fonts, on behalf of the user. The system utility must become privileged in order to obtain the fonts.

## Using the doPrivileged API

The use of the privileged feature is described in the following sections.

### No Return Value, No Exception Thrown

If you do not need to return a value from within the privileged block, your call to `doPrivileged` can look like the following example, which specifies privileged code three ways: in a class that implements the interface `PrivilegedAction`, in an anonymous class, and in a lambda expression:

    import java.security.*;

    public class NoReturnNoException {

        class MyAction implements PrivilegedAction<Void> {
            public Void run() {
                // Privileged code goes here, for example:
                System.loadLibrary("awt");
                return null; // nothing to return
            }
        }

        public void somemethod() {

            MyAction mya = new MyAction();

            // Become privileged:
            AccessController.doPrivileged(mya);

            // Anonymous class
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    // Privileged code goes here, for example:
                    System.loadLibrary("awt");
                    return null; // nothing to return
                }
            });

            // Lambda expression
            AccessController.doPrivileged((PrivilegedAction<Void>)
                () -> {
                    // Privileged code goes here, for example:
                    System.loadLibrary("awt");
                    return null; // nothing to return
                }
            );
        }

        public static void main(String... args) {
            NoReturnNoException myApplication = new NoReturnNoException();
            myApplication.somemethod();
        }
    }

The `AccessController.doPrivileged` method takes an object of type `java.security.PrivilegedAction` and invokes its `run` method in privileged mode. The implementation guarantees that privileges will be revoked after the `run` method is executed, even if execution of `doPrivileged` is interrupted by an asynchronous exception. Note that the invocation of `doPrivileged` with a lambda expression explicitly casts the lambda expression as of type `PrivilegedAction<Void>`. Another version of the method `doPrivileged` exists that takes an object of type `PrivilegedExceptionAction`; see Handling Exceptions for more information about this version.

`PrivilegedAction` is a functional interface with a single abstract method, named `run`, that returns a value of type specified by its type parameter.

Note that this example ignores the return value of the `run` method. Also, depending on what privileged code actually consists of, you might have to make some changes due to the way inner classes work. For example, if privileged code throws an exception or attempts to access local variables, then you will have to make some changes, which is described later.

Be very careful in your use of the privileged construct, and always remember to make the privileged code section as small as possible. That is, try to limit the code within the `run` method to only what needs to be run with privileges, and do more general things outside the `run` method. Also note that the call to `doPrivileged` should be made in the code that wants to enable its privileges. Do not be tempted to write a utility class that itself calls `doPrivileged` as that could lead to security holes. You can write utility classes for `PrivilegedAction` classes though, as shown in the preceding example. See Guideline 9-3: Safely invoke `java.security.AccessController.doPrivileged` in Secure Coding Guidelines for the Java Programming Language for more information.

### Returning Values

If you need to return a value, then you can do something like the following:

    System.out.println(
        AccessController.doPrivileged((PrivilegedAction<String>)
            () -> System.getProperty("user.name")
        )
    );

### Accessing Local Variables

If you are using a lambda expression or anonymous inner class, then any local variables you access must be `final` or effectively final. For example:

    String lib = "awt";
    AccessController.doPrivileged((PrivilegedAction<Void>)
        () -> {
            System.loadLibrary(lib);
            return null; // nothing to return
        }
    );

    AccessController.doPrivileged(new PrivilegedAction<Void>() {
        public Object run() {
            System.loadLibrary(lib);
            return null; // nothing to return
        }
    });

The variable `lib` is effectively final because its value has not been modified. For example, suppose you add the following assignment statement after the declaration of the variable `lib`:

    lib = "swing";

The compiler generates the following errors when it encounters the invocation `System.loadLibrary` both in the lambda expression and the anonymous class:

- `error: local variables referenced from a lambda expression must be final or effectively final`
- `error: local variables referenced from an inner class must be final or effectively final`

See Accessing Members of an Enclosing Class in Local Classes for more information.

If there are cases where you cannot make an existing variable effectively final (because it gets set multiple times), then you can create a new `final` variable right before invoking the `doPrivileged` method, and set that variable equal to the other variable. For example:

    String lib;

    // The lib variable gets set multiple times so you can't make it
    // effectively final.

    // Create a final String that you can use inside of the run method
    final String fLib = lib;

    AccessController.doPrivileged((PrivilegedAction<Void>)
        () -> {
            System.loadLibrary(fLib);
            return null; // nothing to return
        }
    );

### Handling Exceptions

If the action performed in your `run` method could throw a checked exception (one that must be listed in the `throws` clause of a method), then you need to use the `PrivilegedExceptionAction` interface instead of the `PrivilegedAction` interface:

    public void processSomefile() throws IOException {

        try {
            Path path = FileSystems.getDefault().getPath("somefile");
            BufferedReader br = AccessController.doPrivileged(
                (PrivilegedExceptionAction<BufferedReader>)
                    () -> Files.newBufferedReader(path)
            );
            // ... read from file and do something
        } catch (PrivilegedActionException e) {

            // e.getException() should be an instance of IOException
            // as only checked exceptions will be wrapped in a
            // PrivilegedActionException.
            throw (IOException) e.getException();
        }
    }

If a checked exception is thrown during execution of the `run` method, then it is placed in a `PrivilegedActionException` wrapper exception that is then thrown and should be caught by your code, as illustrated in this example.

### Asserting a Subset of Privileges

As of JDK 8, a variant of `AccessController.doPrivileged` is available that enables code to assert a subset of its privileges, without preventing the full traversal of the stack to check for other permissions. This variant of the `doPrivileged` variant has three parameters, one of which you use to specify this subset of privileges. For example, the following excerpt asserts a privilege to retrieve system properties:

    // Returns the value of the specified property. All code
    // is allowed to read the app.version and app.vendor
    // properties.

    public String getProperty(final String prop) {
        return AccessController.doPrivileged(
            (PrivilegedAction<String>) () -> System.getProperty(prop),
            null,
            new java.util.PropertyPermission("app.version", "read"),
            new java.util.PropertyPermission("app.vendor", "read")
        );
    }

The first parameter of this version of `doPrivileged` is of type `java.security.PrivilegedAction`. In this example, the first parameter is a lambda expression that implements the functional interface `PrivilegedAction` whose `run` method returns the value of the system property specified by the parameter `prop`.

The second parameter of this version of `doPrivileged` is of type `AccessControlContext`. Sometimes you need to perform an additional security check within a different context, such as a worker thread. You can obtain an `AccessControlContext` instance from a particular calling context with the method `AccessControlContext.getContext`. If you specify `null` for this parameter (as in this example), then the invocation of `doPrivileged` does not perform any additional security checks.

The third parameter of this version of `doPrivileged` is of type `Permission...`, which is a varargs parameter. This means that you can specify one or more `Permission` parameters or an array of `Permission` objects, as in `Permission[]`. In this example, the invocation of `doPrivileged` can retrieve the properties `app.version` and `app.vendor`.

You can use this three parameter variant of `doPrivileged` in a mode of least privilege or a mode of more privilege.

#### Least Privilege

The typical use case of the `doPrivileged` method is to enable the method that invokes it to perform one or more actions that require permission checks without requiring the callers of the current method to have all the necessary permissions. For example, the current method might need to open a file or make a network request for its own internal implementation purposes.

Before JDK 8, calls to `doPrivileged` methods had only two parameters. They worked by granting temporary privileges to the calling method and stopping the normal full traversal of the stack for access checking when it reached that class, rather than continuing up the call stack where it might reach a method whose defining class does not have the required permission. Typically, the class that is calling `doPrivileged` might have additional permissions that are not required in that code path and which might also be missing from some caller classes.

Normally, these extra permissions are not exercised at runtime. Not elevating them through use of `doPrivileged` helps to block exploitation of any incorrect code that could perform unintended actions. This is especially true when the `PrivilegedAction` is more complex than usual, or when it calls code outside the class or package boundary that might evolve independently over time.

The three-parameter variant of `doPrivileged` is generally safer to use because it avoids unnecessarily elevating permissions that are not intended to be required. However, it executes less efficiently so simple or performance-critical code paths might choose not to use it.

#### More Privilege

Sometimes when coding the current method, you want to temporarily extend the permission of the calling method to perform an action. For example, a framework I/O API might have a general purpose method for opening files of a particular data format. This API would take a normal file path parameter and use it to open an underlying `FileInputStream` using the calling code's permissions. However, this might also allow any caller to open the data files in a special directory that contains some standard demonstration samples.

The callers of this API could be directly granted a `FilePermission` for read access. However, it might not be convenient or possible for the security policy of the calling code to be updated. For example, the calling code could be a sandboxed applet.

One way to implement this is for the code to check the incoming path and determine if it refers to a file in the special directory. If it does, then it would call `doPrivileged`, enabling all permissions, then open the file inside the `PrivilegedAction`. If the file was not in the special directory, the code would open the file without using `doPrivileged`.

This technique requires the implementation to carefully handle the requested file path to determine if it refers to the special shared directory. The file path must be canonicalized before calling `doPrivileged` so that any relative path will be processed (and permission to read the `user.dir` system property will be checked) prior to determining if the path refers to a file in the special directory. It must also prevent malicious "../" path elements meant to escape out of the special directory.

A simpler and better implementation would use the variant of `doPrivileged` with the third parameter. It would pass a `FilePermission` with read access to the special directory as the third parameter. Then any manipulation of the file would be inside the `PrivilegedAction`. This implementation is simpler and much less prone to contain a security flaw.

## Reflection

One subtlety that must be considered is the interaction of this API with reflection. The `doPrivileged` method can be invoked reflectively using `java.lang.reflect.Method.invoke`. In this case, the privileges granted in privileged mode are not those of `Method.invoke` but of the non-reflective code that invoked it. Otherwise, system privileges could erroneously (or maliciously) be conferred on user code. Note that similar requirements exist when using reflection in the existing API.

Copyright © 1993, 2018, Oracle and/or its affiliates. All rights reserved.
Contact Us