Wed, 19 Nov 2014 14:21:09 -0800
8064667: Add -XX:+CheckEndorsedAndExtDirs flag to JDK 8
Reviewed-by: coleenp, ccheung
1.1 --- a/src/share/vm/runtime/arguments.cpp Wed Nov 19 18:14:01 2014 +0100 1.2 +++ b/src/share/vm/runtime/arguments.cpp Wed Nov 19 14:21:09 2014 -0800 1.3 @@ -2962,6 +2962,23 @@ 1.4 #endif 1.5 // -D 1.6 } else if (match_option(option, "-D", &tail)) { 1.7 + if (CheckEndorsedAndExtDirs) { 1.8 + if (match_option(option, "-Djava.endorsed.dirs=", &tail)) { 1.9 + // abort if -Djava.endorsed.dirs is set 1.10 + jio_fprintf(defaultStream::output_stream(), 1.11 + "-Djava.endorsed.dirs will not be supported in a future release.\n" 1.12 + "Refer to JEP 220 for details (http://openjdk.java.net/jeps/220).\n"); 1.13 + return JNI_EINVAL; 1.14 + } 1.15 + if (match_option(option, "-Djava.ext.dirs=", &tail)) { 1.16 + // abort if -Djava.ext.dirs is set 1.17 + jio_fprintf(defaultStream::output_stream(), 1.18 + "-Djava.ext.dirs will not be supported in a future release.\n" 1.19 + "Refer to JEP 220 for details (http://openjdk.java.net/jeps/220).\n"); 1.20 + return JNI_EINVAL; 1.21 + } 1.22 + } 1.23 + 1.24 if (!add_property(tail)) { 1.25 return JNI_ENOMEM; 1.26 } 1.27 @@ -3395,6 +3412,146 @@ 1.28 } 1.29 } 1.30 1.31 +static bool has_jar_files(const char* directory) { 1.32 + DIR* dir = os::opendir(directory); 1.33 + if (dir == NULL) return false; 1.34 + 1.35 + struct dirent *entry; 1.36 + char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal); 1.37 + bool hasJarFile = false; 1.38 + while (!hasJarFile && (entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { 1.39 + const char* name = entry->d_name; 1.40 + const char* ext = name + strlen(name) - 4; 1.41 + hasJarFile = ext > name && (os::file_name_strcmp(ext, ".jar") == 0); 1.42 + } 1.43 + FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); 1.44 + os::closedir(dir); 1.45 + return hasJarFile ; 1.46 +} 1.47 + 1.48 +// returns the number of directories in the given path containing JAR files 1.49 +// If the skip argument is not NULL, it will skip that directory 1.50 +static int check_non_empty_dirs(const char* path, const char* type, const char* skip) { 1.51 + const char separator = *os::path_separator(); 1.52 + const char* const end = path + strlen(path); 1.53 + int nonEmptyDirs = 0; 1.54 + while (path < end) { 1.55 + const char* tmp_end = strchr(path, separator); 1.56 + if (tmp_end == NULL) { 1.57 + if ((skip == NULL || strcmp(path, skip) != 0) && has_jar_files(path)) { 1.58 + nonEmptyDirs++; 1.59 + jio_fprintf(defaultStream::output_stream(), 1.60 + "Non-empty %s directory: %s\n", type, path); 1.61 + } 1.62 + path = end; 1.63 + } else { 1.64 + char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtInternal); 1.65 + memcpy(dirpath, path, tmp_end - path); 1.66 + dirpath[tmp_end - path] = '\0'; 1.67 + if ((skip == NULL || strcmp(dirpath, skip) != 0) && has_jar_files(dirpath)) { 1.68 + nonEmptyDirs++; 1.69 + jio_fprintf(defaultStream::output_stream(), 1.70 + "Non-empty %s directory: %s\n", type, dirpath); 1.71 + } 1.72 + FREE_C_HEAP_ARRAY(char, dirpath, mtInternal); 1.73 + path = tmp_end + 1; 1.74 + } 1.75 + } 1.76 + return nonEmptyDirs; 1.77 +} 1.78 + 1.79 +// Returns true if endorsed standards override mechanism and extension mechanism 1.80 +// are not used. 1.81 +static bool check_endorsed_and_ext_dirs() { 1.82 + if (!CheckEndorsedAndExtDirs) 1.83 + return true; 1.84 + 1.85 + char endorsedDir[JVM_MAXPATHLEN]; 1.86 + char extDir[JVM_MAXPATHLEN]; 1.87 + const char* fileSep = os::file_separator(); 1.88 + jio_snprintf(endorsedDir, sizeof(endorsedDir), "%s%slib%sendorsed", 1.89 + Arguments::get_java_home(), fileSep, fileSep); 1.90 + jio_snprintf(extDir, sizeof(extDir), "%s%slib%sext", 1.91 + Arguments::get_java_home(), fileSep, fileSep); 1.92 + 1.93 + // check endorsed directory 1.94 + int nonEmptyDirs = check_non_empty_dirs(Arguments::get_endorsed_dir(), "endorsed", NULL); 1.95 + 1.96 + // check the extension directories but skip the default lib/ext directory 1.97 + nonEmptyDirs += check_non_empty_dirs(Arguments::get_ext_dirs(), "extension", extDir); 1.98 + 1.99 + // List of JAR files installed in the default lib/ext directory. 1.100 + // -XX:+CheckEndorsedAndExtDirs checks if any non-JDK file installed 1.101 + static const char* jdk_ext_jars[] = { 1.102 + "access-bridge-32.jar", 1.103 + "access-bridge-64.jar", 1.104 + "access-bridge.jar", 1.105 + "cldrdata.jar", 1.106 + "dnsns.jar", 1.107 + "jaccess.jar", 1.108 + "jfxrt.jar", 1.109 + "localedata.jar", 1.110 + "nashorn.jar", 1.111 + "sunec.jar", 1.112 + "sunjce_provider.jar", 1.113 + "sunmscapi.jar", 1.114 + "sunpkcs11.jar", 1.115 + "ucrypto.jar", 1.116 + "zipfs.jar", 1.117 + NULL 1.118 + }; 1.119 + 1.120 + // check if the default lib/ext directory has any non-JDK jar files; if so, error 1.121 + DIR* dir = os::opendir(extDir); 1.122 + if (dir != NULL) { 1.123 + int num_ext_jars = 0; 1.124 + struct dirent *entry; 1.125 + char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(extDir), mtInternal); 1.126 + while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { 1.127 + const char* name = entry->d_name; 1.128 + const char* ext = name + strlen(name) - 4; 1.129 + if (ext > name && (os::file_name_strcmp(ext, ".jar") == 0)) { 1.130 + bool is_jdk_jar = false; 1.131 + const char* jarfile = NULL; 1.132 + for (int i=0; (jarfile = jdk_ext_jars[i]) != NULL; i++) { 1.133 + if (os::file_name_strcmp(name, jarfile) == 0) { 1.134 + is_jdk_jar = true; 1.135 + break; 1.136 + } 1.137 + } 1.138 + if (!is_jdk_jar) { 1.139 + jio_fprintf(defaultStream::output_stream(), 1.140 + "%s installed in <JAVA_HOME>/lib/ext\n", name); 1.141 + num_ext_jars++; 1.142 + } 1.143 + } 1.144 + } 1.145 + FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); 1.146 + os::closedir(dir); 1.147 + if (num_ext_jars > 0) { 1.148 + nonEmptyDirs += 1; 1.149 + } 1.150 + } 1.151 + 1.152 + // check if the default lib/endorsed directory exists; if so, error 1.153 + dir = os::opendir(endorsedDir); 1.154 + if (dir != NULL) { 1.155 + jio_fprintf(defaultStream::output_stream(), "<JAVA_HOME>/lib/endorsed exists\n"); 1.156 + os::closedir(dir); 1.157 + nonEmptyDirs += 1; 1.158 + } 1.159 + 1.160 + if (nonEmptyDirs > 0) { 1.161 + jio_fprintf(defaultStream::output_stream(), 1.162 + "Endorsed standards override mechanism and extension mechanism" 1.163 + "will not be supported in a future release.\n" 1.164 + "Refer to JEP 220 for details (http://openjdk.java.net/jeps/220).\n"); 1.165 + return false; 1.166 + } 1.167 + 1.168 + return true; 1.169 +} 1.170 + 1.171 jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required) { 1.172 // This must be done after all -D arguments have been processed. 1.173 scp_p->expand_endorsed(); 1.174 @@ -3404,6 +3561,10 @@ 1.175 Arguments::set_sysclasspath(scp_p->combined_path()); 1.176 } 1.177 1.178 + if (!check_endorsed_and_ext_dirs()) { 1.179 + return JNI_ERR; 1.180 + } 1.181 + 1.182 // This must be done after all arguments have been processed. 1.183 // java_compiler() true means set to "NONE" or empty. 1.184 if (java_compiler() && !xdebug_mode()) {
2.1 --- a/src/share/vm/runtime/globals.hpp Wed Nov 19 18:14:01 2014 +0100 2.2 +++ b/src/share/vm/runtime/globals.hpp Wed Nov 19 14:21:09 2014 -0800 2.3 @@ -1210,6 +1210,9 @@ 2.4 product(bool, CheckJNICalls, false, \ 2.5 "Verify all arguments to JNI calls") \ 2.6 \ 2.7 + product(bool, CheckEndorsedAndExtDirs, false, \ 2.8 + "Verify the endorsed and extension directories are not used") \ 2.9 + \ 2.10 product(bool, UseFastJNIAccessors, true, \ 2.11 "Use optimized versions of Get<Primitive>Field") \ 2.12 \
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/runtime/CheckEndorsedAndExtDirs/EndorsedExtDirs.java Wed Nov 19 14:21:09 2014 -0800 3.3 @@ -0,0 +1,60 @@ 3.4 +/* 3.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/* 3.28 + * @test 3.29 + * @bug 8064667 3.30 + * @summary Sanity test for -XX:+CheckEndorsedAndExtDirs 3.31 + * @library /testlibrary 3.32 + * @run main/othervm -XX:+CheckEndorsedAndExtDirs EndorsedExtDirs 3.33 + */ 3.34 + 3.35 +import com.oracle.java.testlibrary.*; 3.36 +import java.util.ArrayList; 3.37 +import java.util.List; 3.38 + 3.39 +public class EndorsedExtDirs { 3.40 + static final String cpath = System.getProperty("test.classes", "."); 3.41 + public static void main(String arg[]) throws Exception { 3.42 + fatalError("-XX:+CheckEndorsedAndExtDirs", "-Djava.endorsed.dirs=foo"); 3.43 + fatalError("-XX:+CheckEndorsedAndExtDirs", "-Djava.ext.dirs=bar"); 3.44 + } 3.45 + 3.46 + static void fatalError(String... args) throws Exception { 3.47 + List<String> commands = new ArrayList<>(); 3.48 + String java = System.getProperty("java.home") + "/bin/java"; 3.49 + commands.add(java); 3.50 + for (String s : args) { 3.51 + commands.add(s); 3.52 + } 3.53 + commands.add("-cp"); 3.54 + commands.add(cpath); 3.55 + commands.add("EndorsedExtDirs"); 3.56 + 3.57 + System.out.println("Launching " + commands); 3.58 + ProcessBuilder pb = new ProcessBuilder(commands); 3.59 + OutputAnalyzer output = new OutputAnalyzer(pb.start()); 3.60 + output.shouldContain("Could not create the Java Virtual Machine"); 3.61 + output.shouldHaveExitValue(1); 3.62 + } 3.63 +}