cutover jarhell to parsing classpath all the time

This commit is contained in:
Robert Muir 2015-09-10 21:31:25 -04:00
parent cc5471c564
commit 6f59e3fca1
5 changed files with 44 additions and 36 deletions

View File

@ -26,6 +26,7 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.FileVisitResult;
@ -70,21 +71,43 @@ public class JarHell {
}
/**
* Checks the current classloader for duplicate classes
* Checks the current classpath for duplicate classes
* @throws IllegalStateException if jar hell was found
*/
public static void checkJarHell() throws Exception {
ClassLoader loader = JarHell.class.getClassLoader();
if (loader instanceof URLClassLoader == false) {
return;
}
ESLogger logger = Loggers.getLogger(JarHell.class);
if (logger.isDebugEnabled()) {
logger.debug("java.class.path: {}", System.getProperty("java.class.path"));
logger.debug("sun.boot.class.path: {}", System.getProperty("sun.boot.class.path"));
logger.debug("classloader urls: {}", Arrays.toString(((URLClassLoader)loader).getURLs()));
if (loader instanceof URLClassLoader ) {
logger.debug("classloader urls: {}", Arrays.toString(((URLClassLoader)loader).getURLs()));
}
}
checkJarHell(((URLClassLoader) loader).getURLs());
checkJarHell(parseClassPath());
}
/**
* Parses the classpath into a set of URLs
*/
@SuppressForbidden(reason = "resolves against CWD because that is how classpaths work")
public static URL[] parseClassPath() {
String elements[] = System.getProperty("java.class.path").split(System.getProperty("path.separator"));
URL urlElements[] = new URL[elements.length];
for (int i = 0; i < elements.length; i++) {
String element = elements[i];
// empty classpath element behaves like CWD.
if (element.isEmpty()) {
element = System.getProperty("user.dir");
}
try {
urlElements[i] = PathUtils.get(element).toUri().toURL();
} catch (MalformedURLException e) {
// should not happen, as we use the filesystem API
throw new RuntimeException(e);
}
}
return urlElements;
}
/**

View File

@ -24,7 +24,6 @@ import org.elasticsearch.env.Environment;
import java.io.*;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.AccessMode;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
@ -133,27 +132,21 @@ final class Security {
*/
@SuppressForbidden(reason = "proper use of URL")
static void setCodebaseProperties() {
ClassLoader loader = Security.class.getClassLoader();
if (loader instanceof URLClassLoader) {
for (URL url : ((URLClassLoader)loader).getURLs()) {
for (Map.Entry<Pattern,String> e : SPECIAL_JARS.entrySet()) {
if (e.getKey().matcher(url.getPath()).matches()) {
String prop = e.getValue();
if (System.getProperty(prop) != null) {
throw new IllegalStateException("property: " + prop + " is unexpectedly set: " + System.getProperty(prop));
}
System.setProperty(prop, url.toString());
for (URL url : JarHell.parseClassPath()) {
for (Map.Entry<Pattern,String> e : SPECIAL_JARS.entrySet()) {
if (e.getKey().matcher(url.getPath()).matches()) {
String prop = e.getValue();
if (System.getProperty(prop) != null) {
throw new IllegalStateException("property: " + prop + " is unexpectedly set: " + System.getProperty(prop));
}
System.setProperty(prop, url.toString());
}
}
for (String prop : SPECIAL_JARS.values()) {
if (System.getProperty(prop) == null) {
System.setProperty(prop, "file:/dev/null"); // no chance to be interpreted as "all"
}
}
for (String prop : SPECIAL_JARS.values()) {
if (System.getProperty(prop) == null) {
System.setProperty(prop, "file:/dev/null"); // no chance to be interpreted as "all"
}
} else {
// we could try to parse the classpath or something, but screw it for now.
throw new UnsupportedOperationException("Unsupported system classloader type: " + loader.getClass());
}
}

View File

@ -41,7 +41,6 @@ import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFileAttributeView;
@ -315,10 +314,7 @@ public class PluginManager {
private void jarHellCheck(Path candidate, boolean isolated) throws IOException {
// create list of current jars in classpath
final List<URL> jars = new ArrayList<>();
ClassLoader loader = PluginManager.class.getClassLoader();
if (loader instanceof URLClassLoader) {
Collections.addAll(jars, ((URLClassLoader) loader).getURLs());
}
jars.addAll(Arrays.asList(JarHell.parseClassPath()));
// read existing bundles. this does some checks on the installation too.
List<Bundle> bundles = PluginsService.getPluginBundles(environment.pluginsFile());

View File

@ -47,6 +47,7 @@ import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -331,12 +332,7 @@ public class PluginsService extends AbstractComponent {
// pluginmanager does it, but we do it again, in case lusers mess with jar files manually
try {
final List<URL> jars = new ArrayList<>();
ClassLoader parentLoader = getClass().getClassLoader();
if (parentLoader instanceof URLClassLoader) {
for (URL url : ((URLClassLoader) parentLoader).getURLs()) {
jars.add(url);
}
}
jars.addAll(Arrays.asList(JarHell.parseClassPath()));
jars.addAll(bundle.urls);
JarHell.checkJarHell(jars.toArray(new URL[0]));
} catch (Exception e) {

View File

@ -86,7 +86,7 @@ public class BootstrapForTesting {
// initialize paths the same exact way as bootstrap.
Permissions perms = new Permissions();
// add permissions to everything in classpath
for (URL url : ((URLClassLoader)BootstrapForTesting.class.getClassLoader()).getURLs()) {
for (URL url : JarHell.parseClassPath()) {
Path path = PathUtils.get(url.toURI());
// resource itself
perms.add(new FilePermission(path.toString(), "read,readlink"));