mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-28 09:28:55 -04:00
Remove PrivilegedOperations (#127726)
With the SecurityManager gone, the PrivilegedOperations class is no longer needed, these operations can be called directly.
This commit is contained in:
parent
8bb7dc4058
commit
b78ac7c94c
11 changed files with 40 additions and 203 deletions
|
@ -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<String> 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 {
|
||||
|
|
|
@ -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<IntSupplier> 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<LongSupplier> 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<IntSupplier> 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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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<String, CharSequence> sources) throws Exception {
|
||||
private URLClassLoader buildProviderJar(Map<String, CharSequence> sources) throws Exception {
|
||||
var classToBytes = InMemoryJavaCompiler.compile(sources);
|
||||
|
||||
Map<String, byte[]> 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<String, CharSequence> 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"));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
try (
|
||||
URLClassLoader fakeClassLoader = buildTestProviderPlugin("integer");
|
||||
URLClassLoader fakeClassLoader1 = buildTestProviderPlugin("string");
|
||||
try {
|
||||
URLClassLoader fakeClassLoader1 = buildTestProviderPlugin("string")
|
||||
) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Plugin> fakePluginClass = (Class<? extends Plugin>) 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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<Void>) () -> {
|
||||
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<Boolean>) () -> 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("<<ALL FILES>>", "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<AccessControlContext>) 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<Permission> elements() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue