From 8981763af988c1502ba376cb41a1a0faf24b37f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Wed, 18 Oct 2023 14:18:39 +0200 Subject: [PATCH] Avoid referencing ClassLoaders in ProtectionDomains 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. --- .../java/io/quarkus/bootstrap/app/CuratedApplication.java | 4 ++-- .../io/quarkus/bootstrap/classloading/ClassPathElement.java | 4 ++-- .../bootstrap/classloading/DirectoryClassPathElement.java | 5 ++--- .../bootstrap/classloading/FilteredClassPathElement.java | 4 ++-- .../quarkus/bootstrap/classloading/JarClassPathElement.java | 4 ++-- .../bootstrap/classloading/MemoryClassPathElement.java | 5 ++--- .../bootstrap/classloading/PathTreeClassPathElement.java | 5 ++--- .../quarkus/bootstrap/classloading/QuarkusClassLoader.java | 2 +- .../io/quarkus/bootstrap/runner/ClassLoadingResource.java | 2 +- .../main/java/io/quarkus/bootstrap/runner/JarResource.java | 4 ++-- .../io/quarkus/bootstrap/runner/SerializedApplication.java | 2 +- 11 files changed, 19 insertions(+), 22 deletions(-) diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/app/CuratedApplication.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/app/CuratedApplication.java index fce442143c5e85..da469231ba265b 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/app/CuratedApplication.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/app/CuratedApplication.java @@ -478,8 +478,8 @@ public Set getProvidedResources() { } @Override - public ProtectionDomain getProtectionDomain(ClassLoader classLoader) { - return delegate.getProtectionDomain(classLoader); + public ProtectionDomain getProtectionDomain() { + return delegate.getProtectionDomain(); } @Override diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/ClassPathElement.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/ClassPathElement.java index 26ade4b620f43d..eefce68aa5f660 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/ClassPathElement.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/ClassPathElement.java @@ -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(); @@ -115,7 +115,7 @@ public Set getProvidedResources() { } @Override - public ProtectionDomain getProtectionDomain(ClassLoader classLoader) { + public ProtectionDomain getProtectionDomain() { return null; } diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/DirectoryClassPathElement.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/DirectoryClassPathElement.java index ad71f5d817fabd..ea78be461995fb 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/DirectoryClassPathElement.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/DirectoryClassPathElement.java @@ -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(); @@ -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 diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/FilteredClassPathElement.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/FilteredClassPathElement.java index 5e362a7e27d337..a72fcee9259ffa 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/FilteredClassPathElement.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/FilteredClassPathElement.java @@ -58,8 +58,8 @@ public Set getProvidedResources() { } @Override - public ProtectionDomain getProtectionDomain(ClassLoader classLoader) { - return delegate.getProtectionDomain(classLoader); + public ProtectionDomain getProtectionDomain() { + return delegate.getProtectionDomain(); } @Override diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/JarClassPathElement.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/JarClassPathElement.java index 4ffbabf05a7ae5..1c2aad6399a034 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/JarClassPathElement.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/JarClassPathElement.java @@ -256,7 +256,7 @@ public Set apply(JarFile jarFile) { } @Override - public ProtectionDomain getProtectionDomain(ClassLoader classLoader) { + public ProtectionDomain getProtectionDomain() { final URL url; try { url = jarPath.toURI().toURL(); @@ -264,7 +264,7 @@ public ProtectionDomain getProtectionDomain(ClassLoader classLoader) { 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 diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/MemoryClassPathElement.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/MemoryClassPathElement.java index 4458602ae57300..b77b6dbf181686 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/MemoryClassPathElement.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/MemoryClassPathElement.java @@ -111,7 +111,7 @@ public Set getProvidedResources() { } @Override - public ProtectionDomain getProtectionDomain(ClassLoader classLoader) { + public ProtectionDomain getProtectionDomain() { URL url = null; try { url = new URL(null, "quarkus:/", new MemoryUrlStreamHandler("quarkus:/")); @@ -119,8 +119,7 @@ public ProtectionDomain getProtectionDomain(ClassLoader classLoader) { 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 diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/PathTreeClassPathElement.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/PathTreeClassPathElement.java index cba6b34e0c08b5..6f05de1707e714 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/PathTreeClassPathElement.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/PathTreeClassPathElement.java @@ -159,7 +159,7 @@ protected Manifest readManifest() { } @Override - public ProtectionDomain getProtectionDomain(ClassLoader classLoader) { + public ProtectionDomain getProtectionDomain() { URL url = null; final Path root = getRoot(); try { @@ -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 diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java index bc2323fb2c0564..e1b20fe85d6574 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java @@ -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; } diff --git a/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/ClassLoadingResource.java b/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/ClassLoadingResource.java index 58bae161452b2c..a6a2540601a2dd 100644 --- a/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/ClassLoadingResource.java +++ b/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/ClassLoadingResource.java @@ -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); diff --git a/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/JarResource.java b/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/JarResource.java index 0a8ff83203eb30..6b8a6117414f34 100644 --- a/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/JarResource.java +++ b/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/JarResource.java @@ -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(); @@ -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 diff --git a/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/SerializedApplication.java b/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/SerializedApplication.java index fab316850bd732..1ba0a0fbbaf124 100644 --- a/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/SerializedApplication.java +++ b/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/SerializedApplication.java @@ -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); }