Skip to content

Commit

Permalink
Avoid referencing ClassLoaders in ProtectionDomains
Browse files Browse the repository at this point in the history
This removes a whole class of metaspace leaks caused by
Thread.inheritedAccessControlContext referencing ProtectionDomains which
reference older classloaders.

Of course this may have impacts on how the SecurityManager behaves, but
as I understand it, absolutely no part of Quarkus is ready to run with a
SecurityManager enabled anyway.
  • Loading branch information
yrodiere committed Oct 18, 2023
1 parent 186cfe3 commit e9b279b
Show file tree
Hide file tree
Showing 11 changed files with 19 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -478,8 +478,8 @@ public Set<String> getProvidedResources() {
}

@Override
public ProtectionDomain getProtectionDomain(ClassLoader classLoader) {
return delegate.getProtectionDomain(classLoader);
public ProtectionDomain getProtectionDomain() {
return delegate.getProtectionDomain();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ default ArtifactKey getDependencyKey() {
*
* @return The protection domain that should be used to define classes from this element
*/
ProtectionDomain getProtectionDomain(ClassLoader classLoader);
ProtectionDomain getProtectionDomain();

Manifest getManifest();

Expand Down Expand Up @@ -115,7 +115,7 @@ public Set<String> getProvidedResources() {
}

@Override
public ProtectionDomain getProtectionDomain(ClassLoader classLoader) {
public ProtectionDomain getProtectionDomain() {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public void accept(Path path) {
}

@Override
public ProtectionDomain getProtectionDomain(ClassLoader classLoader) {
public ProtectionDomain getProtectionDomain() {
URL url = null;
try {
URI uri = root.toUri();
Expand All @@ -169,8 +169,7 @@ public ProtectionDomain getProtectionDomain(ClassLoader classLoader) {
throw new RuntimeException("Unable to create protection domain for " + root, e);
}
CodeSource codesource = new CodeSource(url, (Certificate[]) null);
ProtectionDomain protectionDomain = new ProtectionDomain(codesource, null, classLoader, null);
return protectionDomain;
return new ProtectionDomain(codesource, null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public Set<String> getProvidedResources() {
}

@Override
public ProtectionDomain getProtectionDomain(ClassLoader classLoader) {
return delegate.getProtectionDomain(classLoader);
public ProtectionDomain getProtectionDomain() {
return delegate.getProtectionDomain();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,15 @@ public Set<String> apply(JarFile jarFile) {
}

@Override
public ProtectionDomain getProtectionDomain(ClassLoader classLoader) {
public ProtectionDomain getProtectionDomain() {
final URL url;
try {
url = jarPath.toURI().toURL();
} catch (URISyntaxException | MalformedURLException e) {
throw new RuntimeException("Unable to create protection domain for " + jarPath, e);
}
CodeSource codesource = new CodeSource(url, (Certificate[]) null);
return new ProtectionDomain(codesource, null, classLoader, null);
return new ProtectionDomain(codesource, null, null, null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,15 @@ public Set<String> getProvidedResources() {
}

@Override
public ProtectionDomain getProtectionDomain(ClassLoader classLoader) {
public ProtectionDomain getProtectionDomain() {
URL url = null;
try {
url = new URL(null, "quarkus:/", new MemoryUrlStreamHandler("quarkus:/"));
} catch (MalformedURLException e) {
throw new RuntimeException("Unable to create protection domain for memory element", e);
}
CodeSource codesource = new CodeSource(url, (Certificate[]) null);
ProtectionDomain protectionDomain = new ProtectionDomain(codesource, null, classLoader, null);
return protectionDomain;
return new ProtectionDomain(codesource, null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ protected Manifest readManifest() {
}

@Override
public ProtectionDomain getProtectionDomain(ClassLoader classLoader) {
public ProtectionDomain getProtectionDomain() {
URL url = null;
final Path root = getRoot();
try {
Expand All @@ -168,8 +168,7 @@ public ProtectionDomain getProtectionDomain(ClassLoader classLoader) {
throw new RuntimeException("Unable to create protection domain for " + root, e);
}
CodeSource codesource = new CodeSource(url, (Certificate[]) null);
ProtectionDomain protectionDomain = new ProtectionDomain(codesource, null, classLoader, null);
return protectionDomain;
return new ProtectionDomain(codesource, null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
byte[] data = classPathElementResource.getData();
definePackage(name, classPathElement);
Class<?> cl = defineClass(name, data, 0, data.length,
protectionDomains.computeIfAbsent(classPathElement, (ce) -> ce.getProtectionDomain(this)));
protectionDomains.computeIfAbsent(classPathElement, ClassPathElement::getProtectionDomain));
if (Driver.class.isAssignableFrom(cl)) {
driverLoaded = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public interface ClassLoadingResource {
* A lifecycle hook that should be called when the ClassLoader to which this resource belongs to
* is constructed
*/
void init(ClassLoader runnerClassLoader);
void init();

byte[] getResourceData(String resource);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public JarResource(ManifestInfo manifestInfo, Path jarPath) {
}

@Override
public void init(ClassLoader runnerClassLoader) {
public void init() {
final URL url;
try {
String path = jarPath.toAbsolutePath().toString();
Expand All @@ -64,7 +64,7 @@ public void init(ClassLoader runnerClassLoader) {
} catch (URISyntaxException | MalformedURLException e) {
throw new RuntimeException("Unable to create protection domain for " + jarPath, e);
}
this.protectionDomain = new ProtectionDomain(new CodeSource(url, (Certificate[]) null), null, runnerClassLoader, null);
this.protectionDomain = new ProtectionDomain(new CodeSource(url, (Certificate[]) null), null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public static SerializedApplication read(InputStream inputStream, Path appRoot)
resourceDirectoryTracker.getResult(), parentFirstPackages,
nonExistentResources, FULLY_INDEXED_PATHS, directlyIndexedResourcesIndexMap);
for (ClassLoadingResource classLoadingResource : allClassLoadingResources) {
classLoadingResource.init(runnerClassLoader);
classLoadingResource.init();
}
return new SerializedApplication(runnerClassLoader, mainClass);
}
Expand Down

0 comments on commit e9b279b

Please sign in to comment.