JDK-8203316 : Provide a mechanism to make system's security manager immutable
  • Type: CSR
  • Component: security-libs
  • Sub-Component: java.security
  • Priority: P2
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 12
  • Submitted: 2018-05-16
  • Updated: 2018-10-10
  • Resolved: 2018-10-09
Related Reports
CSR :  
Description
Summary
-------

A mechanism to prevent a SecurityManager from being enabled at runtime in order to allow for performance optimizations.


Problem
-------

A `SecurityManager` can be installed at startup with the `java.security.manager` system property, or later, at runtime by calling the `setSecurityManager` method of `java.lang.System`.  This latter approach can incur runtime overhead even for applications that do not install a `SecurityManager`.  These applications ideally should not have to incur the cost of supporting a `SecurityManager` if it is not used.  If we knew at startup that a `SecurityManager` was not going to be installed, we could optimize the code and increase performance for applications that do not use a `SecurityManager`.


Solution
--------

The solution consists of 2 main changes:

 1. Introduce specification changes that optionally prevent the installation of a `SecurityManager` at runtime, via the `setSecurityManager` method of `java.lang.System`.  
 2. Add new options to the `java.security.manager` system property to toggle this behavior in the JDK implementation.  Note that the `java.security.manager` is an implementation-specific property, even though it starts with `java`.


Specification
-------------

A zip file containing the javadoc for SecurityManager and System is also attached.

1. The `setSecurityManager` method of `java.lang.System` has been modified to optionally throw an `UnsupportedOperationException` and an `implNote` has been added to document its behavior when the `java.security.manager` system property is set to "disallow":

```
     /**
-     * Sets the System security.
+     * Sets the system-wide security manager.
      *
      * If there is a security manager already installed, this method first
      * calls the security manager's {@code checkPermission} method
@@ -306,27 +317,46 @@
      * security manager has been established, then no action is taken and
      * the method simply returns.
      *
-     * @param      s   the security manager.
-     * @throws     SecurityException  if the security manager has already
-     *             been set and its {@code checkPermission} method
-     *             doesn't allow it to be replaced.
+     * @implNote In the JDK implementation, if the Java virtual machine is
+     * started with the system property {@code java.security.manager} set to
+     * the special token "{@code disallow}" then the {@code setSecurityManager}
+     * method cannot be used to set a security manager.
+     *
+     * @param  sm the security manager or {@code null}
+     * @throws SecurityException
+     *         if the security manager has already been set and its {@code
+     *         checkPermission} method doesn't allow it to be replaced
+     * @throws UnsupportedOperationException
+     *         if {@code sm} is non-null and a security manager is not allowed
+     *         to be set dynamically
```
2.  The existing JDK-specific `java.security.manager` system property has been enhanced to support two new tokens, "disallow" and "allow". Additional text has been added to the class description of the `SecurityManager` class to describe the syntax of the `java.security.manager` system property (which had never been previously described in the javadocs) and the behavior of these new tokens:
```
- * The current security manager is set by the
- * <code>setSecurityManager</code> method in class
- * <code>System</code>. The current security manager is obtained
- * by the <code>getSecurityManager</code> method.
+ * Environments using a security manager will typically set the security
+ * manager at startup. In the JDK implementation, this is done by setting
+ * the system property {@code java.security.manager} on the command line to
+ * the class name of the security manager. It can also be set to the empty
+ * String ("") or the special token "{@code default}" to use the
+ * default {@code java.lang.SecurityManager}. If a class name is specified,
+ * it must be {@code java.lang.SecurityManager} or a public subclass and have
+ * a public no-arg constructor. The class is loaded by the
+ * {@linkplain ClassLoader#getSystemClassLoader() built-in system class loader}
+ * if it is not {@code java.lang.SecurityManager}. If the
+ * {@code java.security.manager} system property is not set, the default value
+ * is {@code null}, which means a security manager will not be set at startup.
+ * <p>
+ * The Java run-time may also allow, but is not required to allow, the security
+ * manager to be set dynamically by invoking the
+ * {@link System#setSecurityManager(SecurityManager) setSecurityManager} method.
+ * In the JDK implementation, if the Java virtual machine is started with
+ * the {@code java.security.manager} system property set to the special token
+ * "{@code disallow}" then a security manager will not be set at startup and
+ * cannot be set dynamically (the
+ * {@link System#setSecurityManager(SecurityManager) setSecurityManager}
+ * method will throw an {@code UnsupportedOperationException}). If the
+ * {@code java.security.manager} system property is not set or is set to the
+ * special token "{@code allow}", then a security manager will not be set at
+ * startup but can be set dynamically. Finally, if the
+ * {@code java.security.manager} system property is set to the class name of
+ * the security manager, or to the empty String ("") or the special token
+ * "{@code default}", then a security manager is set at startup (as described
+ * previously) and can also be subsequently replaced (or disabled) dynamically
+ * (subject to the policy of the currently installed security manager). The
+ * following table illustrates the behavior of the JDK implementation for the
+ * different settings of the {@code java.security.manager} system property:
+ * <table class="striped">
+ * <caption style="display:none">property value,
+ *  the SecurityManager set at startup,
+ *  can dynamically set a SecurityManager
+ * </caption>
+ * <thead>
+ * <tr>
+ * <th scope="col">Property Value</th>
+ * <th scope="col">The SecurityManager set at startup</th>
+ * <th scope="col">System.setSecurityManager run-time behavior</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ *
+ * <tr>
+ *   <th scope="row">null</th>
+ *   <td>None</td>
+ *   <td>Success or throws {@code SecurityException} if not permitted by
+ * the currently installed security manager</td>
+ * </tr>
+ *
+ * <tr>
+ *   <th scope="row">empty String ("")</th>
+ *   <td>{@code java.lang.SecurityManager}</td>
+ *   <td>Success or throws {@code SecurityException} if not permitted by
+ * the currently installed security manager</td>
+ * </tr>
+ *
+ * <tr>
+ *   <th scope="row">"default"</th>
+ *   <td>{@code java.lang.SecurityManager}</td>
+ *   <td>Success or throws {@code SecurityException} if not permitted by
+ * the currently installed security manager</td>
+ * </tr>
+ *
+ * <tr>
+ *   <th scope="row">"disallow"</th>
+ *   <td>None</td>
+ *   <td>Always throws {@code UnsupportedOperationException}</td>
+ * </tr>
+ *
+ * <tr>
+ *   <th scope="row">"allow"</th>
+ *   <td>None</td>
+ *   <td>Success or throws {@code SecurityException} if not permitted by
+ * the currently installed security manager</td>
+ * </tr>
+ *
+ * <tr>
+ *   <th scope="row">a class name</th>
+ *   <td>the named class</td>
+ *   <td>Success or throws {@code SecurityException} if not permitted by
+ * the currently installed security manager</td>
+ * </tr>
+ *
+ * </tbody>
+ * </table>
+ * <p> A future release of the JDK may change the default value of the
+ * {@code java.security.manager} system property to "{@code disallow}".
+ * <p>
+ * The current security manager is returned by the
+ * {@link System#getSecurityManager() getSecurityManager} method.
```
Comments
Aside from tests, the chances of customers/developers deploying with custom security managers named "allow" and "disallow" (all lower case, unnamed package) is low and should not be a compatibility concern.
10-10-2018

Voting to Approve. I will note the very small behavioral compatibility risk could be further reduced by making all the special tokens keywords or literals in the language, strawman proposal: * default -- already a keyword * void -- replacement for "disallow" * volatile -- replacement for "allow"
09-10-2018

[~mullan] FYI, coming soon, a new javadoc tag `{@systemProperty NAME} that will cause the named property to appear in the search and A-Z index. JDK-5076751
09-10-2018

[~darcy] I changed the referenced sentence to "In the JDK implementation, if the Java virtual machine is started with the system property ...". Most of the other proposed text in SecurityManager already has that. I only saw one other passage in SecurityManager that needed that type of clarification. I changed this sentence: "The following table illustrates the behavior of the different settings of the {@code java.security.manager} system property:" to: "The following table illustrates the behavior of the JDK implementation for the different settings of the {@code java.security.manager} system property:"
09-10-2018

As written, the text + * @implNote If the Java virtual machine is started with the system property + * {@code java.security.manager} set to the special token + * "{@code disallow}" then the {@code setSecurityManager} method cannot be + * used to set a security manager. sounds much more like a requirement of all implementations rather than an implementation choice of the JDK reference implementation. Please rephrase this and related passages.
09-10-2018

Returning to Draft status to address some additional comments from [~smarks], see http://mail.openjdk.java.net/pipermail/security-dev/2018-October/018407.html. Will finalize afterwards.
04-10-2018

Instead of adding a new property to disallow the setting of a SecurityManager at runtime, we have added new tokens to the existing "java.security.manager" system property, named "disallow", and "allow" to toggle this behavior. There are a couple of new paragraphs in the SecurityManager class description describing the JDK-specific "java.security.manager" property and how the new tokens work.
03-10-2018

I believe a related system property `java.security.policy` is also JDK-specific. We should clarify the `java.security.*` system properties and better to do it as a separate issue.
28-09-2018

[~alanb] is correct. The `java.security.manager` system property has never been formally specified in the API or other specification docs and is assumed to be a non-standard property, even though it starts with "java". The TCK does not use this property in any of the tests which test `SecurityManager` functionality. In the specification changes for this CSR, I have added a description of the `java.security.manager` property to the class description of `SecurityManager` and noted that it is implementation-specific: "In the JDK implementation, this is done by setting the system property "{@code java.security.manager}" on the command line to the class name of the security manager. If no class name, "{@code default}", or the empty String ("") is specified, the default security manager is utilized."
28-09-2018

I don't think the system property `java.security.manager` is defined in any of the API docs, meaning I think it's JDK-specific rather than Java SE.
27-09-2018

[~darcy] For this enhancement, I believe an implementation-specific property gives us more flexibility to adapt the behavior to future changes in the SecurityManager area. For example, we have discussed potentially changing the default value of the jdk.allowSecurityManager property to false (instead of true), and even removing the need for the property altogether by changing setSecurityManager to unconditionally throw UnsupportedOperationException. An SE specific property would seem to be harder to make changes like that. [~alanb], [~mchung] - any thoughts/opinions?
26-09-2018

As security managers are a Java SE feature and there is already a Java SE security manager-related system property, I think any additional system property to disable installing a security manager should be part of SE rather than JDK specific. Moving the request to Provisional with a recommendation to reconsider this aspect of the design before finalizing.
26-09-2018