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 org.elasticsearch.common.logging.Loggers;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.nio.file.FileVisitResult; 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 * @throws IllegalStateException if jar hell was found
*/ */
public static void checkJarHell() throws Exception { public static void checkJarHell() throws Exception {
ClassLoader loader = JarHell.class.getClassLoader(); ClassLoader loader = JarHell.class.getClassLoader();
if (loader instanceof URLClassLoader == false) {
return;
}
ESLogger logger = Loggers.getLogger(JarHell.class); ESLogger logger = Loggers.getLogger(JarHell.class);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("java.class.path: {}", System.getProperty("java.class.path")); logger.debug("java.class.path: {}", System.getProperty("java.class.path"));
logger.debug("sun.boot.class.path: {}", System.getProperty("sun.boot.class.path")); logger.debug("sun.boot.class.path: {}", System.getProperty("sun.boot.class.path"));
if (loader instanceof URLClassLoader ) {
logger.debug("classloader urls: {}", Arrays.toString(((URLClassLoader)loader).getURLs())); 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.io.*;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.AccessMode; import java.nio.file.AccessMode;
import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files; import java.nio.file.Files;
@ -133,9 +132,7 @@ final class Security {
*/ */
@SuppressForbidden(reason = "proper use of URL") @SuppressForbidden(reason = "proper use of URL")
static void setCodebaseProperties() { static void setCodebaseProperties() {
ClassLoader loader = Security.class.getClassLoader(); for (URL url : JarHell.parseClassPath()) {
if (loader instanceof URLClassLoader) {
for (URL url : ((URLClassLoader)loader).getURLs()) {
for (Map.Entry<Pattern,String> e : SPECIAL_JARS.entrySet()) { for (Map.Entry<Pattern,String> e : SPECIAL_JARS.entrySet()) {
if (e.getKey().matcher(url.getPath()).matches()) { if (e.getKey().matcher(url.getPath()).matches()) {
String prop = e.getValue(); String prop = e.getValue();
@ -151,10 +148,6 @@ final class Security {
System.setProperty(prop, "file:/dev/null"); // no chance to be interpreted as "all" 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());
}
} }
/** returns dynamic Permissions to configured paths */ /** returns dynamic Permissions to configured paths */

View File

@ -41,7 +41,6 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.*; import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFileAttributeView;
@ -315,10 +314,7 @@ public class PluginManager {
private void jarHellCheck(Path candidate, boolean isolated) throws IOException { private void jarHellCheck(Path candidate, boolean isolated) throws IOException {
// create list of current jars in classpath // create list of current jars in classpath
final List<URL> jars = new ArrayList<>(); final List<URL> jars = new ArrayList<>();
ClassLoader loader = PluginManager.class.getClassLoader(); jars.addAll(Arrays.asList(JarHell.parseClassPath()));
if (loader instanceof URLClassLoader) {
Collections.addAll(jars, ((URLClassLoader) loader).getURLs());
}
// read existing bundles. this does some checks on the installation too. // read existing bundles. this does some checks on the installation too.
List<Bundle> bundles = PluginsService.getPluginBundles(environment.pluginsFile()); 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.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; 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 // pluginmanager does it, but we do it again, in case lusers mess with jar files manually
try { try {
final List<URL> jars = new ArrayList<>(); final List<URL> jars = new ArrayList<>();
ClassLoader parentLoader = getClass().getClassLoader(); jars.addAll(Arrays.asList(JarHell.parseClassPath()));
if (parentLoader instanceof URLClassLoader) {
for (URL url : ((URLClassLoader) parentLoader).getURLs()) {
jars.add(url);
}
}
jars.addAll(bundle.urls); jars.addAll(bundle.urls);
JarHell.checkJarHell(jars.toArray(new URL[0])); JarHell.checkJarHell(jars.toArray(new URL[0]));
} catch (Exception e) { } catch (Exception e) {

View File

@ -86,7 +86,7 @@ public class BootstrapForTesting {
// initialize paths the same exact way as bootstrap. // initialize paths the same exact way as bootstrap.
Permissions perms = new Permissions(); Permissions perms = new Permissions();
// add permissions to everything in classpath // 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()); Path path = PathUtils.get(url.toURI());
// resource itself // resource itself
perms.add(new FilePermission(path.toString(), "read,readlink")); perms.add(new FilePermission(path.toString(), "read,readlink"));