Executive Summary: A new command line option (-XX:VMOptionsFile) will be added to the JVM to meet password concerns. This new command line option will specify an options file that accepts a superset of the options supported by the existing "configuration file" option (-XX:Flags). The existing option will likely be deprecated. 1. The Problem: The customer complaint is that the HotSpot VM does not provide a mechanism for specifying an option that contains a password without exposing it in clear text. The two options the customer is using are: -Djavax.net.ssl.keyStorePassword -Djavax.net.ssl.trustStorePassword This work is tracked by the following bugs: JDK-8044257 Widen variety of VM options JDK-8061999 Enhance VM Option parsing to allow options to be specified in a file. 2. Existing JVM Option Mechanisms: The JVM currently supports the following mechanisms for specifying options: * pseudo command line * environment variables * configuration file 2.1. Pseudo Command Line When the JVM is started it is usually the launcher that does that job so the launcher passes a list of options to the JVM at invocation time. The JVM is presented with a list of options as part of the running environment. The list of options the JVM receives is not an argv/argc list like you find in a normal application or utility. Instead the launcher presents a partially parsed list of arguments. The options are partially parsed because the launcher has parsed the traditional argv/argc list just enough to know who is the recipient of the option. The JVM may only receive a subset of options which were passed to the launcher. So for purposes of this document we will refer to this list of arguments passed to the JVM as a Pseudo Command line. 2.2. Environment Variables The JVM accepts two environment variables: _JAVA_OPTIONS and JAVA_TOOL_OPTIONS, that can be used to specify options. The environment variables can be used to specify any JVM option. If an option is set more than once in an environment variable the last setting specified is the value that will be used. If an option is set in both environment variables the value set in _JAVA_OPTIONS will be used. 2.3. Configuration Files The JVM also supports reading a configuration file that contains options. The default is to read from a file named .hotspotrc or the user can specify an option -XX:Flags= which allows the user to specify the path to a file. The existing parsing functionality that reads this file only supports '-XX:' style VM options which does not include the customer case. The configuration file parsing assumes all options are of the '-XX:' style and this parser does not recognize the other styles. Example line: Parse result ----------------------- -------------- +UseSerialGC recognized ErrorFile=my_error_file recognized MinRAMFraction=8 recognized -Xint not recognized Xint not recognized -Dfoo=baz not recognized Dfoo=baz not recognized 2.4. Parse Order for Options The parse order for each of the supported option containers is: 1. Environment variable JAVA_TOOL_OPTIONS 2. Flags file, configuration file, and .hotspotrc 3. Pseudo command line from launcher. 4. Environment variable _JAVA_OPTIONS Each option container is parsed left to right and top to bottom. For more info see the example at the end of the document. 2.5. Process Order for Options The process order for each of the supported option containers is: 1. Environment variable JAVA_TOOL_OPTIONS 2. Flags or configuration file. 3. Pseudo command line from launcher. 4. Environment variable _JAVA_OPTIONS Each option container is processed left to right and top to bottom. For more info see the example at the end of the document. 3. Security Analysis of Existing JVM Option Mechanisms 3.1. Pseudo Command line The command including all of its arguments are viewable at invocation and throughout the lifecycle of the process. The command line options can easily read by ps(1) on *NIX OS platforms and task manager on Windows platforms. 3.2. Environment Variables The environment variables can handle all of the options without modification, but can't be secured. The environment variables are viewable throughout the lifecycle of the process. The environment options can easily read by ps(1) on *NIX OS platforms and task manager on Windows platforms. 3.3. Configuration Files The '-XX:Flags=' option can be used to specify a path to a secure or trusted file. However, the existing parsing supports only '-XX:' style options in configuration file processing, but in a format that differs from that on the pseudo command line. This mechanism will not work for the specific options that the customer wants to use securely without modification. Modifications to the configuration file processing would include modifying the parsing rules and that would put existing configuration file semantics at risk. The existing configuration files are not adequate for our needs and the modifications to extend the semantics are risky. The configuration file solution has been dropped from further consideration. 4. New Option Mechanism Design: 4.1. Requirements The new mechanism must: * allow the options to be stored securely * support all VM password options The new mechanism should: * support the same argument syntax as pseudo command line * avoid adding to the existing option syntax nightmare * support all of the existing command line VM options * To avoid infinite recursion, the new VM options file option cannot be specified in the new VM options file itself 4.2. Security Mechanisms: There are many ways that we could secure the vulnerable options associated with the JVM. Some of these are databases, network services and local files. The simplest of these is a local file that is protected by the platform security mechanisms for files. The security policy for the file will be as follows: * The JVM will load/read/parse any options file that it can read. It is recommended that care be taken in selecting the proper access controls for your options file. * Proper access control includes both read and write restrictions. * Read access control needs to allow the file to be read by the JVM, but block the users that should not be permitted to see the contents. * The write access needs to block all users that are not trusted to set the options of the JVM. Failure to restrict write access could result in the tainting of the options set that is used by the JVM. 5. New Option Mechanism Implementation: 5.1. Details 5.1.1 Option Name: The new option is called -XX:VMOptionsFile, and the option will take a string that is the path to the file containing the options. 5.1.2. Options Processing The only options container that supports setting the -XX:VMOptionsFile is the pseudo command line in order to simplify the initial implementation. 5.1.3. Option File Error Handling: None of the existing error handling will be modified except for the new error paths introduced by adding the new option -XX:VMOptionsFile. The new option will not remove or modify any existing error handling or the existing associated error codes. There will be new log messages and errors codes that are reported by the new option processing. The new feature will have the following types of errors to report: - User introduced command line parsing errors. - User introduced options file parsing errors. - Missing or inaccessible options file. - Options file option specified on command line more than once. - Options file option specified in an options file. All of these errors will cause the JVM to exit with a non zero error status and an error message. The following will not be reported as errors and the status returned will be zero. No message will be output and the VM will not exit. - An empty options file - An options file with only whitespace. 6. Implementation Strategy: 6.1. Approaches Considered and Not Taken: Initially the implementation approach was to follow/clone the code for the -XX:Flags= option otherwise known as the configuration file. This code was thought to be closest to the functionality for the new option. However reading the file is the easy part of this. The backend of this approach has a code path that only supports '-XX:' style options. The APIs of the internal processing are completely incompatible with the parsing that we need to support. After some investigation this approach was dropped because of major parsing issues that would lead to a much larger code footprint and was likely to be hard to stabilize the code. The second approach considered was to do a hybrid. A configuration file front end and an environment variable backend. On paper it sounds good until you try to put the two pieces together. The parsing/processing for this does not support what we want, a general purpose mechanism that mimics the command line. The third approach was to try to use the existing command line parsing mechanism that reads options from a file, but makes calls to the same processing that the command line parsing was using. This would require many changes to existing code, including modifications to the calling arguments in many functions. The actual parse checks in the existing code span 5 functions and include one function that has a 600 line while loop full of 'if-then-else statements'. The modularity in this code is almost nonexistent in some places. This approach was deemed too risky and it was dropped. 6.2. The Current Approach The current approach takes advantage of the pseudo command line internal processing by merging the file options with the existing list of command line options. The merged options that we parse from the file are given the same treatment as the command line. This strategy requires that we identify a single place where we can merge the pseudo command line with the options file content. To be effective this merge must happen before any processing of the pseudo command line. This approach will allow all of the VM pseudo command line options in the options file except for the -XX:VMOptionsFile option. The environment variables JAVA_TOOL_OPTIONS and _JAVA_OPTIONS will allow the -XX:VMOptionsFile option to be set, but the option will not cause the options file to be read. The environment variables are not processed until later. 6.2.1. More detail: The pseudo command line merge process scans the pseudo command line copying the entry from the input list to the output list until a -XX:VMOptionsFile option is found. When an options file option is detected, the specified file is parsed and the parsed options are added to the output list. When the options file processing is completed the scanning and entry copying of the original pseudo command line resumes. This solution supports: 1) duplicate options in the options file and on the command line. 2) the existing semantic of "the last command line argument wins" is preserved With current design and implementation the user is allowed complete flexibility in the order and content of the arguments on the command line. Here is an example: Pseudo Command line: On the lines below notice there are a total of eight options. The '?opt' options are specified directly on the command line. The option -XX:VMOptionsFile allows some options to be added indirectly. Aopt Bopt Copt -XX:Flags= -XX:VMOptionsFile= Dopt Eopt Fopt After the above line is received, we read and process it merging any options specified in the files. The merged list below is the content that the JVM will process: Aopt Bopt Copt flags_file_opts opts_file_opts Dopt Eopt Fopt Therefore, this solution supports: 1) Duplicate options in the files and on the command line 2) The last duplicate argument from the last argument source wins. 7. Future Work: * refactor most the argument processing into an OO coding model * refactor options file read code to allow for multiple options files * refactor options file read code to allow options files to not be limited to 1024 bytes * refactor options file read and processing to not be limited to 64 options in an options file * consider deprecating the '-XX:Flags=' option