From b78ac7c94cf9780cc807b4f23fef548b8836a9e7 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Tue, 6 May 2025 10:50:49 -0700 Subject: [PATCH] Remove PrivilegedOperations (#127726) With the SecurityManager gone, the PrivilegedOperations class is no longer needed, these operations can be called directly. --- .../EmbeddedImplClassLoaderTests.java | 40 ++----- .../provider/ProviderLocatorTests.java | 31 ++--- .../painless/WhitelistLoaderTests.java | 2 +- .../plugins/ExtensionLoaderTests.java | 9 +- .../plugins/PluginIntrospectorTests.java | 6 +- .../plugins/PluginsLoaderTests.java | 5 +- .../plugins/PluginsServiceTests.java | 16 ++- .../bootstrap/BootstrapForTesting.java | 9 -- .../test/PrivilegedOperations.java | 113 ------------------ .../test/compiler/InMemoryJavaCompiler.java | 6 +- .../org/elasticsearch/test/jar/JarUtils.java | 6 +- 11 files changed, 40 insertions(+), 203 deletions(-) delete mode 100644 test/framework/src/main/java/org/elasticsearch/test/PrivilegedOperations.java diff --git a/libs/core/src/test/java/org/elasticsearch/core/internal/provider/EmbeddedImplClassLoaderTests.java b/libs/core/src/test/java/org/elasticsearch/core/internal/provider/EmbeddedImplClassLoaderTests.java index 34c8ed1c6d85..d8a963b84bc6 100644 --- a/libs/core/src/test/java/org/elasticsearch/core/internal/provider/EmbeddedImplClassLoaderTests.java +++ b/libs/core/src/test/java/org/elasticsearch/core/internal/provider/EmbeddedImplClassLoaderTests.java @@ -9,11 +9,11 @@ package org.elasticsearch.core.internal.provider; +import org.elasticsearch.core.IOUtils; import org.elasticsearch.core.Strings; import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.core.internal.provider.EmbeddedImplClassLoader.CompoundEnumeration; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.test.PrivilegedOperations; import org.elasticsearch.test.compiler.InMemoryJavaCompiler; import org.elasticsearch.test.jar.JarUtils; @@ -195,13 +195,10 @@ public class EmbeddedImplClassLoaderTests extends ESTestCase { Path outerJar = topLevelDir.resolve("impl.jar"); JarUtils.createJarWithEntries(outerJar, jarEntries); URL[] urls = new URL[] { outerJar.toUri().toURL() }; - URLClassLoader parent = URLClassLoader.newInstance(urls, EmbeddedImplClassLoaderTests.class.getClassLoader()); - try { + try (URLClassLoader parent = loader(urls)) { EmbeddedImplClassLoader loader = EmbeddedImplClassLoader.getInstance(parent, "x-foo"); Class c = loader.loadClass("p.FooBar"); return c.getConstructor().newInstance(); - } finally { - PrivilegedOperations.closeURLClassLoader(parent); } } @@ -245,8 +242,7 @@ public class EmbeddedImplClassLoaderTests extends ESTestCase { Path outerJar = topLevelDir.resolve("impl.jar"); JarUtils.createJarWithEntriesUTF(outerJar, jarEntries); URL[] urls = new URL[] { outerJar.toUri().toURL() }; - URLClassLoader parent = URLClassLoader.newInstance(urls, EmbeddedImplClassLoaderTests.class.getClassLoader()); - try { + try (URLClassLoader parent = loader(urls)) { EmbeddedImplClassLoader loader = EmbeddedImplClassLoader.getInstance(parent, "res"); // resource in a valid java package dir URL url = loader.findResource("p/res.txt"); @@ -274,8 +270,6 @@ public class EmbeddedImplClassLoaderTests extends ESTestCase { hasToString(endsWith("impl.jar!/IMPL-JARS/res/zoo-impl.jar/A-C/res.txt")) ) ); - } finally { - PrivilegedOperations.closeURLClassLoader(parent); } } @@ -326,9 +320,7 @@ public class EmbeddedImplClassLoaderTests extends ESTestCase { containsInAnyOrder("Parent Resource", "Embedded Resource") ); } finally { - for (URLClassLoader closeable : closeables) { - PrivilegedOperations.closeURLClassLoader(closeable); - } + IOUtils.close(closeables); } } @@ -463,9 +455,7 @@ public class EmbeddedImplClassLoaderTests extends ESTestCase { assertThat(new String(is.readAllBytes(), UTF_8), is("Hello World" + expectedVersion)); } } finally { - for (URLClassLoader closeable : closeables) { - PrivilegedOperations.closeURLClassLoader(closeable); - } + IOUtils.close(closeables); } } @@ -493,8 +483,7 @@ public class EmbeddedImplClassLoaderTests extends ESTestCase { Path outerJar = topLevelDir.resolve("impl.jar"); JarUtils.createJarWithEntriesUTF(outerJar, jarEntries); URL[] urls = new URL[] { outerJar.toUri().toURL() }; - URLClassLoader parent = URLClassLoader.newInstance(urls, EmbeddedImplClassLoaderTests.class.getClassLoader()); - try { + try (URLClassLoader parent = loader(urls)) { embedLoader = EmbeddedImplClassLoader.getInstance(parent, "res"); Class c = embedLoader.loadClass("java.lang.Object"); @@ -514,8 +503,6 @@ public class EmbeddedImplClassLoaderTests extends ESTestCase { expectThrows(NPE, () -> embedLoader.getResourceAsStream(null)); expectThrows(NPE, () -> embedLoader.resources(null)); expectThrows(NPE, () -> embedLoader.loadClass(null)); - } finally { - PrivilegedOperations.closeURLClassLoader(parent); } } @@ -542,8 +529,7 @@ public class EmbeddedImplClassLoaderTests extends ESTestCase { JarUtils.createJarWithEntries(outerJar, jarEntries); URL[] urls = new URL[] { outerJar.toUri().toURL() }; - URLClassLoader parent = URLClassLoader.newInstance(urls, EmbeddedImplClassLoaderTests.class.getClassLoader()); - try { + try (URLClassLoader parent = loader(urls)) { EmbeddedImplClassLoader loader = EmbeddedImplClassLoader.getInstance(parent, "blah"); Class c = loader.loadClass("p.Foo"); Object obj = c.getConstructor().newInstance(); @@ -555,8 +541,6 @@ public class EmbeddedImplClassLoaderTests extends ESTestCase { expectThrows(CNFE, () -> loader.loadClass("p.Unknown")); expectThrows(CNFE, () -> loader.loadClass("q.Unknown")); expectThrows(CNFE, () -> loader.loadClass("r.Unknown")); - } finally { - PrivilegedOperations.closeURLClassLoader(parent); } } @@ -577,18 +561,20 @@ public class EmbeddedImplClassLoaderTests extends ESTestCase { Path outerJar = topLevelDir.resolve("impl.jar"); JarUtils.createJarWithEntriesUTF(outerJar, jarEntries); URL[] urls = new URL[] { outerJar.toUri().toURL() }; - URLClassLoader parent = URLClassLoader.newInstance(urls, EmbeddedImplClassLoaderTests.class.getClassLoader()); - try { + + try (URLClassLoader parent = loader(urls)) { EmbeddedImplClassLoader loader = EmbeddedImplClassLoader.getInstance(parent, "blah"); var res = Collections.list(loader.getResources("res.txt")); assertThat(res, hasSize(3)); List l = res.stream().map(EmbeddedImplClassLoaderTests::urlToString).toList(); assertThat(l, containsInAnyOrder("fooRes", "barRes", "bazRes")); - } finally { - PrivilegedOperations.closeURLClassLoader(parent); } } + private static URLClassLoader loader(URL[] urls) { + return URLClassLoader.newInstance(urls, EmbeddedImplClassLoaderTests.class.getClassLoader()); + } + @SuppressForbidden(reason = "file urls") static String urlToString(URL url) { try { diff --git a/libs/core/src/test/java/org/elasticsearch/core/internal/provider/ProviderLocatorTests.java b/libs/core/src/test/java/org/elasticsearch/core/internal/provider/ProviderLocatorTests.java index 61d4a7c6bd70..63553ef72d08 100644 --- a/libs/core/src/test/java/org/elasticsearch/core/internal/provider/ProviderLocatorTests.java +++ b/libs/core/src/test/java/org/elasticsearch/core/internal/provider/ProviderLocatorTests.java @@ -10,11 +10,11 @@ package org.elasticsearch.core.internal.provider; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.test.PrivilegedOperations; import org.elasticsearch.test.compiler.InMemoryJavaCompiler; import org.elasticsearch.test.jar.JarUtils; import java.lang.module.ModuleDescriptor; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; @@ -117,12 +117,8 @@ public class ProviderLocatorTests extends ESTestCase { Path topLevelDir = createTempDir(getTestName()); Path outerJar = topLevelDir.resolve("impl.jar"); JarUtils.createJarWithEntries(outerJar, jarEntries); - URLClassLoader parent = URLClassLoader.newInstance( - new URL[] { outerJar.toUri().toURL() }, - ProviderLocatorTests.class.getClassLoader() - ); - try { + try (URLClassLoader parent = loader(outerJar)) { // test scenario ProviderLocator locator = new ProviderLocator<>("x-foo", IntSupplier.class, parent, "x.foo.impl", Set.of(), true); IntSupplier impl = locator.get(); @@ -139,8 +135,6 @@ public class ProviderLocatorTests extends ESTestCase { assertThat(md.exports(), containsInAnyOrder(exportsOf("p"))); assertThat(md.opens(), containsInAnyOrder(opensOf("q"))); assertThat(md.packages(), containsInAnyOrder(equalTo("p"), equalTo("q"), equalTo("r"))); - } finally { - PrivilegedOperations.closeURLClassLoader(parent); } } @@ -172,12 +166,8 @@ public class ProviderLocatorTests extends ESTestCase { Path topLevelDir = createTempDir(getTestName()); Path outerJar = topLevelDir.resolve("impl.jar"); JarUtils.createJarWithEntries(outerJar, jarEntries); - URLClassLoader parent = URLClassLoader.newInstance( - new URL[] { outerJar.toUri().toURL() }, - ProviderLocatorTests.class.getClassLoader() - ); - try { + try (URLClassLoader parent = loader(outerJar)) { // test scenario ProviderLocator locator = new ProviderLocator<>("x-foo", LongSupplier.class, parent, "", Set.of(), false); LongSupplier impl = locator.get(); @@ -185,8 +175,6 @@ public class ProviderLocatorTests extends ESTestCase { assertThat(impl.toString(), equalTo("Hello from FooLongSupplier - non-modular!")); assertThat(impl.getClass().getName(), equalTo("p.FooLongSupplier")); assertThat(impl.getClass().getModule().isNamed(), is(false)); - } finally { - PrivilegedOperations.closeURLClassLoader(parent); } } @@ -215,12 +203,7 @@ public class ProviderLocatorTests extends ESTestCase { Path pb = Files.createDirectories(barRoot.resolve("pb")); Files.write(pb.resolve("BarIntSupplier.class"), classToBytes.get("pb.BarIntSupplier")); - URLClassLoader parent = URLClassLoader.newInstance( - new URL[] { topLevelDir.toUri().toURL() }, - ProviderLocatorTests.class.getClassLoader() - ); - - try { + try (URLClassLoader parent = loader(topLevelDir)) { // test scenario ProviderLocator locator = new ProviderLocator<>("y-bar", IntSupplier.class, parent, "", Set.of(), false); IntSupplier impl = locator.get(); @@ -228,8 +211,10 @@ public class ProviderLocatorTests extends ESTestCase { assertThat(impl.toString(), equalTo("Hello from BarIntSupplier - exploded non-modular!")); assertThat(impl.getClass().getName(), equalTo("pb.BarIntSupplier")); assertThat(impl.getClass().getModule().isNamed(), is(false)); - } finally { - PrivilegedOperations.closeURLClassLoader(parent); } } + + private static URLClassLoader loader(Path jar) throws MalformedURLException { + return URLClassLoader.newInstance(new URL[] { jar.toUri().toURL() }, ProviderLocatorTests.class.getClassLoader()); + } } diff --git a/modules/lang-painless/spi/src/test/java/org/elasticsearch/painless/WhitelistLoaderTests.java b/modules/lang-painless/spi/src/test/java/org/elasticsearch/painless/WhitelistLoaderTests.java index b46bc118e091..7260a43e2fea 100644 --- a/modules/lang-painless/spi/src/test/java/org/elasticsearch/painless/WhitelistLoaderTests.java +++ b/modules/lang-painless/spi/src/test/java/org/elasticsearch/painless/WhitelistLoaderTests.java @@ -132,7 +132,7 @@ public class WhitelistLoaderTests extends ESTestCase { JarUtils.createJarWithEntries(jar, jarEntries); try (var loader = JarUtils.loadJar(jar)) { - Controller controller = JarUtils.loadModule(jar, loader.classloader(), "m"); + Controller controller = JarUtils.loadModule(jar, loader, "m"); Module module = controller.layer().findModule("m").orElseThrow(); Class ownerClass = module.getClassLoader().loadClass("p.TestOwner"); diff --git a/server/src/test/java/org/elasticsearch/plugins/ExtensionLoaderTests.java b/server/src/test/java/org/elasticsearch/plugins/ExtensionLoaderTests.java index 4f9bbc24fd9e..d877f4d5f6bb 100644 --- a/server/src/test/java/org/elasticsearch/plugins/ExtensionLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/plugins/ExtensionLoaderTests.java @@ -10,7 +10,6 @@ package org.elasticsearch.plugins; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.test.PrivilegedOperations.ClosableURLClassLoader; import org.elasticsearch.test.compiler.InMemoryJavaCompiler; import org.elasticsearch.test.jar.JarUtils; @@ -35,7 +34,7 @@ public class ExtensionLoaderTests extends ESTestCase { int getValue(); } - private ClosableURLClassLoader buildProviderJar(Map sources) throws Exception { + private URLClassLoader buildProviderJar(Map sources) throws Exception { var classToBytes = InMemoryJavaCompiler.compile(sources); Map jarEntries = new HashMap<>(); @@ -55,7 +54,7 @@ public class ExtensionLoaderTests extends ESTestCase { JarUtils.createJarWithEntries(jar, jarEntries); URL[] urls = new URL[] { jar.toUri().toURL() }; - return new ClosableURLClassLoader(URLClassLoader.newInstance(urls, this.getClass().getClassLoader())); + return URLClassLoader.newInstance(urls, this.getClass().getClassLoader()); } private String defineProvider(String name, int value) { @@ -79,7 +78,7 @@ public class ExtensionLoaderTests extends ESTestCase { public void testOneProvider() throws Exception { Map sources = Map.of("p.FooService", defineProvider("FooService", 1)); try (var loader = buildProviderJar(sources)) { - TestService service = ExtensionLoader.loadSingleton(ServiceLoader.load(TestService.class, loader.classloader())) + TestService service = ExtensionLoader.loadSingleton(ServiceLoader.load(TestService.class, loader)) .orElseThrow(AssertionError::new); assertThat(service, not(nullValue())); assertThat(service.getValue(), equalTo(1)); @@ -96,7 +95,7 @@ public class ExtensionLoaderTests extends ESTestCase { try (var loader = buildProviderJar(sources)) { var e = expectThrows( IllegalStateException.class, - () -> ExtensionLoader.loadSingleton(ServiceLoader.load(TestService.class, loader.classloader())) + () -> ExtensionLoader.loadSingleton(ServiceLoader.load(TestService.class, loader)) ); assertThat(e.getMessage(), containsString("More than one extension found")); assertThat(e.getMessage(), containsString("TestService")); diff --git a/server/src/test/java/org/elasticsearch/plugins/PluginIntrospectorTests.java b/server/src/test/java/org/elasticsearch/plugins/PluginIntrospectorTests.java index df7a72cfd59e..f1d77083228a 100644 --- a/server/src/test/java/org/elasticsearch/plugins/PluginIntrospectorTests.java +++ b/server/src/test/java/org/elasticsearch/plugins/PluginIntrospectorTests.java @@ -24,7 +24,6 @@ import org.elasticsearch.indices.recovery.plan.RecoveryPlannerService; import org.elasticsearch.indices.recovery.plan.ShardSnapshotsService; import org.elasticsearch.ingest.Processor; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.test.PrivilegedOperations; import org.elasticsearch.test.compiler.InMemoryJavaCompiler; import org.elasticsearch.test.jar.JarUtils; @@ -233,11 +232,8 @@ public class PluginIntrospectorTests extends ESTestCase { JarUtils.createJarWithEntries(jar, jarEntries); URL[] urls = new URL[] { jar.toUri().toURL() }; - URLClassLoader loader = URLClassLoader.newInstance(urls, PluginIntrospectorTests.class.getClassLoader()); - try { + try (URLClassLoader loader = URLClassLoader.newInstance(urls, PluginIntrospectorTests.class.getClassLoader())) { assertThat(pluginIntrospector.interfaces(loader.loadClass("r.FooPlugin")), contains("ActionPlugin")); - } finally { - PrivilegedOperations.closeURLClassLoader(loader); } } diff --git a/server/src/test/java/org/elasticsearch/plugins/PluginsLoaderTests.java b/server/src/test/java/org/elasticsearch/plugins/PluginsLoaderTests.java index f17132a02839..efc3c069b4ab 100644 --- a/server/src/test/java/org/elasticsearch/plugins/PluginsLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/plugins/PluginsLoaderTests.java @@ -19,7 +19,6 @@ import org.elasticsearch.logging.Logger; import org.elasticsearch.nativeaccess.NativeAccessUtil; import org.elasticsearch.plugin.analysis.CharFilterFactory; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.test.PrivilegedOperations; import org.elasticsearch.test.compiler.InMemoryJavaCompiler; import org.elasticsearch.test.jar.JarUtils; @@ -351,13 +350,13 @@ public class PluginsLoaderTests extends ESTestCase { pluginsLoader.pluginLayers().forEach(lp -> { if (lp.pluginClassLoader() instanceof URLClassLoader urlClassLoader) { try { - PrivilegedOperations.closeURLClassLoader(urlClassLoader); + urlClassLoader.close(); } catch (IOException unexpected) { throw new UncheckedIOException(unexpected); } } else if (lp.pluginClassLoader() instanceof UberModuleClassLoader loader) { try { - PrivilegedOperations.closeURLClassLoader(loader.getInternalLoader()); + loader.getInternalLoader().close(); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/server/src/test/java/org/elasticsearch/plugins/PluginsServiceTests.java b/server/src/test/java/org/elasticsearch/plugins/PluginsServiceTests.java index fa2c800cfbe2..d18b7f52b8d0 100644 --- a/server/src/test/java/org/elasticsearch/plugins/PluginsServiceTests.java +++ b/server/src/test/java/org/elasticsearch/plugins/PluginsServiceTests.java @@ -24,7 +24,6 @@ import org.elasticsearch.plugins.spi.BarPlugin; import org.elasticsearch.plugins.spi.BarTestService; import org.elasticsearch.plugins.spi.TestService; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.test.PrivilegedOperations; import org.elasticsearch.test.compiler.InMemoryJavaCompiler; import org.elasticsearch.test.jar.JarUtils; @@ -671,9 +670,11 @@ public class PluginsServiceTests extends ESTestCase { } public void testLoadServiceProviders() throws Exception { - URLClassLoader fakeClassLoader = buildTestProviderPlugin("integer"); - URLClassLoader fakeClassLoader1 = buildTestProviderPlugin("string"); - try { + + try ( + URLClassLoader fakeClassLoader = buildTestProviderPlugin("integer"); + URLClassLoader fakeClassLoader1 = buildTestProviderPlugin("string") + ) { @SuppressWarnings("unchecked") Class fakePluginClass = (Class) fakeClassLoader.loadClass("r.FooPlugin"); @SuppressWarnings("unchecked") @@ -699,9 +700,6 @@ public class PluginsServiceTests extends ESTestCase { providers = service.loadServiceProviders(TestService.class); assertEquals(0, providers.size()); - } finally { - PrivilegedOperations.closeURLClassLoader(fakeClassLoader); - PrivilegedOperations.closeURLClassLoader(fakeClassLoader1); } } @@ -877,13 +875,13 @@ public class PluginsServiceTests extends ESTestCase { for (var lp : pluginService.plugins()) { if (lp.classLoader() instanceof URLClassLoader urlClassLoader) { try { - PrivilegedOperations.closeURLClassLoader(urlClassLoader); + urlClassLoader.close(); } catch (IOException unexpected) { throw new UncheckedIOException(unexpected); } } else if (lp.classLoader() instanceof UberModuleClassLoader loader) { try { - PrivilegedOperations.closeURLClassLoader(loader.getInternalLoader()); + loader.getInternalLoader().close(); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/test/framework/src/main/java/org/elasticsearch/bootstrap/BootstrapForTesting.java b/test/framework/src/main/java/org/elasticsearch/bootstrap/BootstrapForTesting.java index 98cc8ea7f777..4776eaf1dc1b 100644 --- a/test/framework/src/main/java/org/elasticsearch/bootstrap/BootstrapForTesting.java +++ b/test/framework/src/main/java/org/elasticsearch/bootstrap/BootstrapForTesting.java @@ -16,11 +16,9 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.core.Booleans; import org.elasticsearch.core.PathUtils; import org.elasticsearch.jdk.JarHell; -import org.elasticsearch.test.PrivilegedOperations; import org.elasticsearch.test.mockito.SecureMockMaker; import java.io.IOException; -import java.lang.invoke.MethodHandles; import java.nio.file.Files; import java.nio.file.Path; import java.util.Objects; @@ -75,13 +73,6 @@ public class BootstrapForTesting { // init mockito SecureMockMaker.init(); - // init the privileged operation - try { - MethodHandles.publicLookup().ensureInitialized(PrivilegedOperations.class); - } catch (IllegalAccessException unexpected) { - throw new AssertionError(unexpected); - } - // Log ifconfig output before SecurityManager is installed IfConfig.logIfNecessary(); } diff --git a/test/framework/src/main/java/org/elasticsearch/test/PrivilegedOperations.java b/test/framework/src/main/java/org/elasticsearch/test/PrivilegedOperations.java deleted file mode 100644 index 275adf47d363..000000000000 --- a/test/framework/src/main/java/org/elasticsearch/test/PrivilegedOperations.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -package org.elasticsearch.test; - -import org.elasticsearch.core.SuppressForbidden; - -import java.io.FilePermission; -import java.io.IOException; -import java.net.URLClassLoader; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.CodeSigner; -import java.security.CodeSource; -import java.security.DomainCombiner; -import java.security.Permission; -import java.security.PermissionCollection; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.security.ProtectionDomain; -import java.util.Enumeration; - -import javax.tools.JavaCompiler; - -/** - * A small set of privileged operations that can be executed by unprivileged test code. - * The set of operations is deliberately small, and the permissions narrow. - */ -public final class PrivilegedOperations { - - private PrivilegedOperations() {} - - public static void closeURLClassLoader(URLClassLoader loader) throws IOException { - try { - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - loader.close(); - return null; - }, context, new RuntimePermission("closeClassLoader")); - } catch (PrivilegedActionException pae) { - Exception e = pae.getException(); - if (e instanceof IOException ioe) { - throw ioe; - } else { - throw new IOException(e); - } - } - } - - public record ClosableURLClassLoader(URLClassLoader classloader) implements AutoCloseable { - @Override - public void close() throws Exception { - closeURLClassLoader(classloader); - } - } - - public static Boolean compilationTaskCall(JavaCompiler.CompilationTask compilationTask) { - return AccessController.doPrivileged( - (PrivilegedAction) () -> compilationTask.call(), - context, - new RuntimePermission("createClassLoader"), - new RuntimePermission("closeClassLoader"), - new RuntimePermission("accessSystemModules"), - newAllFilesReadPermission() - ); - } - - @SuppressForbidden(reason = "need to create file permission") - private static FilePermission newAllFilesReadPermission() { - return new FilePermission("<>", "read"); - } - - // -- security manager related stuff, to facilitate asserting permissions for test operations. - - @SuppressWarnings("removal") - private static AccessControlContext getContext() { - ProtectionDomain[] pda = new ProtectionDomain[] { - new ProtectionDomain(new CodeSource(null, (CodeSigner[]) null), new PermissivePermissionCollection()) }; - DomainCombiner combiner = (ignoreCurrent, ignoreAssigned) -> pda; - AccessControlContext acc = new AccessControlContext(AccessController.getContext(), combiner); - // getContext must be called with the new acc so that a combined context will be created - return AccessController.doPrivileged((PrivilegedAction) AccessController::getContext, acc); - } - - // An all-powerful context for wrapping calls - @SuppressWarnings("removal") - private static final AccessControlContext context = getContext(); - - // A permissive permission collection - implies all permissions. - private static final class PermissivePermissionCollection extends PermissionCollection { - - private PermissivePermissionCollection() {} - - @Override - public void add(Permission permission) {} - - @Override - public boolean implies(Permission permission) { - return true; - } - - @Override - public Enumeration elements() { - return null; - } - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/test/compiler/InMemoryJavaCompiler.java b/test/framework/src/main/java/org/elasticsearch/test/compiler/InMemoryJavaCompiler.java index 185fe32ec3bc..106b27a9172a 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/compiler/InMemoryJavaCompiler.java +++ b/test/framework/src/main/java/org/elasticsearch/test/compiler/InMemoryJavaCompiler.java @@ -9,8 +9,6 @@ package org.elasticsearch.test.compiler; -import org.elasticsearch.test.PrivilegedOperations; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -137,7 +135,7 @@ public class InMemoryJavaCompiler { try (FileManagerWrapper wrapper = new FileManagerWrapper(files)) { CompilationTask task = getCompilationTask(wrapper, options); - boolean result = PrivilegedOperations.compilationTaskCall(task); + boolean result = task.call(); if (result == false) { throw new RuntimeException("Could not compile " + sources.entrySet().stream().toList()); } @@ -162,7 +160,7 @@ public class InMemoryJavaCompiler { try (FileManagerWrapper wrapper = new FileManagerWrapper(file)) { CompilationTask task = getCompilationTask(wrapper, options); - boolean result = PrivilegedOperations.compilationTaskCall(task); + boolean result = task.call(); if (result == false) { throw new RuntimeException("Could not compile " + className + " with source code " + sourceCode); } diff --git a/test/framework/src/main/java/org/elasticsearch/test/jar/JarUtils.java b/test/framework/src/main/java/org/elasticsearch/test/jar/JarUtils.java index 0da392cb7fb0..98ccd0c16e88 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/jar/JarUtils.java +++ b/test/framework/src/main/java/org/elasticsearch/test/jar/JarUtils.java @@ -9,8 +9,6 @@ package org.elasticsearch.test.jar; -import org.elasticsearch.test.PrivilegedOperations.ClosableURLClassLoader; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; @@ -101,10 +99,10 @@ public final class JarUtils { * @param path Path to the jar file to load * @return A URLClassLoader that will load classes from the jar. It should be closed when no longer needed. */ - public static ClosableURLClassLoader loadJar(Path path) { + public static URLClassLoader loadJar(Path path) { try { URL[] urls = new URL[] { path.toUri().toURL() }; - return new ClosableURLClassLoader(URLClassLoader.newInstance(urls, JarUtils.class.getClassLoader())); + return URLClassLoader.newInstance(urls, JarUtils.class.getClassLoader()); } catch (MalformedURLException e) { throw new RuntimeException(e); }