Expose only extension-api to extensions
Unless a plugin declares "Gerrit-ApiType: plugin" in its manifest, assume it is an extension and only make the gerrit-extension-api available to it through the ClassLoader. For non-plugins, do not make any Guice bindings available from the server. This further restricts what an extension can see and do with the system internals. Change-Id: Ia38336c42786afb1419d64c06b0d908ae92a64d1
This commit is contained in:
@@ -31,9 +31,10 @@ import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.CodeSource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
@@ -196,7 +197,7 @@ public final class GerritLauncher {
|
||||
throw e;
|
||||
}
|
||||
|
||||
final ArrayList<URL> jars = new ArrayList<URL>();
|
||||
final SortedMap<String, URL> jars = new TreeMap<String, URL>();
|
||||
try {
|
||||
final ZipFile zf = new ZipFile(path);
|
||||
try {
|
||||
@@ -208,6 +209,7 @@ public final class GerritLauncher {
|
||||
}
|
||||
|
||||
if (ze.getName().startsWith("WEB-INF/lib/")) {
|
||||
String name = ze.getName().substring("WEB-INF/lib/".length());
|
||||
final File tmp = createTempFile(safeName(ze), ".jar");
|
||||
final FileOutputStream out = new FileOutputStream(tmp);
|
||||
try {
|
||||
@@ -224,7 +226,7 @@ public final class GerritLauncher {
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
jars.add(tmp.toURI().toURL());
|
||||
jars.put(name, tmp.toURI().toURL());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -237,13 +239,38 @@ public final class GerritLauncher {
|
||||
if (jars.isEmpty()) {
|
||||
return GerritLauncher.class.getClassLoader();
|
||||
}
|
||||
Collections.sort(jars, new Comparator<URL>() {
|
||||
public int compare(URL o1, URL o2) {
|
||||
return o1.toString().compareTo(o2.toString());
|
||||
}
|
||||
});
|
||||
|
||||
return new URLClassLoader(jars.toArray(new URL[jars.size()]));
|
||||
// The extension API needs to be its own ClassLoader, along
|
||||
// with a few of its dependencies. Try to construct this first.
|
||||
List<URL> extapi = new ArrayList<URL>();
|
||||
move(jars, "gerrit-extension-api-", extapi);
|
||||
move(jars, "guice-", extapi);
|
||||
move(jars, "javax.inject-1.jar", extapi);
|
||||
move(jars, "aopalliance-1.0.jar", extapi);
|
||||
move(jars, "guice-servlet-", extapi);
|
||||
move(jars, "servlet-api-", extapi);
|
||||
|
||||
ClassLoader parent = ClassLoader.getSystemClassLoader();
|
||||
if (!extapi.isEmpty()) {
|
||||
parent = new URLClassLoader(
|
||||
extapi.toArray(new URL[extapi.size()]),
|
||||
parent);
|
||||
}
|
||||
return new URLClassLoader(
|
||||
jars.values().toArray(new URL[jars.size()]),
|
||||
parent);
|
||||
}
|
||||
|
||||
private static void move(SortedMap<String, URL> jars,
|
||||
String prefix,
|
||||
List<URL> extapi) {
|
||||
SortedMap<String, URL> matches = jars.tailMap(prefix);
|
||||
if (!matches.isEmpty()) {
|
||||
String first = matches.firstKey();
|
||||
if (first.startsWith(prefix)) {
|
||||
extapi.add(jars.remove(first));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String safeName(final ZipEntry ze) {
|
||||
|
Reference in New Issue
Block a user