Skip to content

Commit 7b35d33

Browse files
committed
Initial thread-related entitlements
1 parent 1344320 commit 7b35d33

File tree

14 files changed

+249
-43
lines changed

14 files changed

+249
-43
lines changed

libs/entitlement/asm-provider/src/main/java/org/elasticsearch/entitlement/instrumentation/impl/InstrumenterImpl.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,13 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str
152152
if (isAnnotationPresent == false) {
153153
boolean isStatic = (access & ACC_STATIC) != 0;
154154
boolean isCtor = "<init>".equals(name);
155-
boolean hasReceiver = (isStatic || isCtor) == false;
156155
var key = new MethodKey(className, name, Stream.of(Type.getArgumentTypes(descriptor)).map(Type::getInternalName).toList());
157156
var instrumentationMethod = checkMethods.get(key);
158157
if (instrumentationMethod != null) {
159-
// LOGGER.debug("Will instrument method {}", key);
158+
// System.out.println("Will instrument method " + key);
160159
return new EntitlementMethodVisitor(Opcodes.ASM9, mv, isStatic, isCtor, descriptor, instrumentationMethod);
161160
} else {
162-
// LOGGER.trace("Will not instrument method {}", key);
161+
// System.out.println("Will not instrument method " + key);
163162
}
164163
}
165164
return mv;

libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import java.util.Locale;
6161
import java.util.Properties;
6262
import java.util.TimeZone;
63+
import java.util.concurrent.ForkJoinPool;
6364
import java.util.function.Consumer;
6465

6566
import javax.net.ssl.HostnameVerifier;
@@ -523,4 +524,26 @@ public interface EntitlementChecker {
523524

524525
// file system providers
525526
void checkNewInputStream(Class<?> callerClass, FileSystemProvider that, Path path, OpenOption... options);
527+
528+
////////////////////
529+
//
530+
// Thread management
531+
//
532+
533+
void check$java_lang_Thread$start(Class<?> callerClass, Thread thread);
534+
535+
void check$java_lang_Thread$setDaemon(Class<?> callerClass, Thread thread, boolean on);
536+
537+
void check$java_lang_ThreadGroup$setDaemon(Class<?> callerClass, ThreadGroup threadGroup, boolean daemon);
538+
539+
void check$java_util_concurrent_ForkJoinPool$setParallelism(Class<?> callerClass, ForkJoinPool forkJoinPool, int size);
540+
541+
void check$java_lang_Thread$setName(Class<?> callerClass, Thread thread, String name);
542+
543+
void check$java_lang_Thread$setPriority(Class<?> callerClass, Thread thread, int newPriority);
544+
545+
void check$java_lang_Thread$setUncaughtExceptionHandler(Class<?> callerClass, Thread thread, Thread.UncaughtExceptionHandler ueh);
546+
547+
void check$java_lang_ThreadGroup$setMaxPriority(Class<?> callerClass, ThreadGroup threadGroup, int pri);
548+
526549
}

libs/entitlement/qa/entitled-plugin/src/main/java/org/elasticsearch/entitlement/qa/entitled/EntitledActions.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99

1010
package org.elasticsearch.entitlement.qa.entitled;
1111

12-
import org.elasticsearch.core.SuppressForbidden;
13-
1412
import java.io.IOException;
1513
import java.nio.file.Files;
1614
import java.nio.file.Path;
@@ -19,9 +17,8 @@
1917
public final class EntitledActions {
2018
private EntitledActions() {}
2119

22-
@SuppressForbidden(reason = "Exposes forbidden APIs for testing purposes")
23-
static void System_clearProperty(String key) {
24-
System.clearProperty(key);
20+
public static Thread newThread(Runnable runnable, String name) {
21+
return new Thread(runnable, name);
2522
}
2623

2724
public static UserPrincipal getFileOwner(Path path) throws IOException {

libs/entitlement/qa/entitled-plugin/src/main/java/org/elasticsearch/entitlement/qa/entitled/EntitledPlugin.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
import org.elasticsearch.plugins.ExtensiblePlugin;
1616
import org.elasticsearch.plugins.Plugin;
1717

18-
import static org.elasticsearch.entitlement.qa.entitled.EntitledActions.System_clearProperty;
18+
import java.util.concurrent.atomic.AtomicBoolean;
19+
20+
import static org.elasticsearch.entitlement.qa.entitled.EntitledActions.newThread;
1921

2022
public class EntitledPlugin extends Plugin implements ExtensiblePlugin {
2123

@@ -28,11 +30,19 @@ public static void selfTest() {
2830
selfTestNotEntitled();
2931
}
3032

31-
private static final String SELF_TEST_PROPERTY = "org.elasticsearch.entitlement.qa.selfTest";
32-
3333
private static void selfTestEntitled() {
3434
logger.debug("selfTestEntitled");
35-
System_clearProperty(SELF_TEST_PROPERTY);
35+
AtomicBoolean threadRan = new AtomicBoolean(false);
36+
try {
37+
Thread testThread = newThread(() -> threadRan.set(true), "testThread");
38+
testThread.start();
39+
testThread.join();
40+
} catch (InterruptedException e) {
41+
throw new AssertionError(e);
42+
}
43+
if (threadRan.get() == false) {
44+
throw new AssertionError("Self-test thread did not run");
45+
}
3646
}
3747

3848
private static void selfTestNotEntitled() {

libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/RestEntitlementsCheckAction.java

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.common.Strings;
1414
import org.elasticsearch.core.CheckedRunnable;
1515
import org.elasticsearch.core.SuppressForbidden;
16+
import org.elasticsearch.entitlement.qa.entitled.EntitledActions;
1617
import org.elasticsearch.logging.LogManager;
1718
import org.elasticsearch.logging.Logger;
1819
import org.elasticsearch.rest.BaseRestHandler;
@@ -47,13 +48,16 @@
4748
import java.util.Map;
4849
import java.util.Map.Entry;
4950
import java.util.Set;
51+
import java.util.concurrent.ForkJoinPool;
52+
import java.util.concurrent.atomic.AtomicBoolean;
5053
import java.util.function.Function;
5154
import java.util.stream.Collectors;
5255
import java.util.stream.Stream;
5356

5457
import javax.net.ssl.HttpsURLConnection;
5558
import javax.net.ssl.SSLContext;
5659

60+
import static java.lang.Thread.currentThread;
5761
import static java.util.Map.entry;
5862
import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS;
5963
import static org.elasticsearch.entitlement.qa.test.RestEntitlementsCheckAction.CheckAction.alwaysDenied;
@@ -180,7 +184,25 @@ static CheckAction alwaysDenied(CheckedRunnable<Exception> action) {
180184
entry("runtime_load", forPlugins(LoadNativeLibrariesCheckActions::runtimeLoad)),
181185
entry("runtime_load_library", forPlugins(LoadNativeLibrariesCheckActions::runtimeLoadLibrary)),
182186
entry("system_load", forPlugins(LoadNativeLibrariesCheckActions::systemLoad)),
183-
entry("system_load_library", forPlugins(LoadNativeLibrariesCheckActions::systemLoadLibrary))
187+
entry("system_load_library", forPlugins(LoadNativeLibrariesCheckActions::systemLoadLibrary)),
188+
189+
entry("java_lang_Thread$start", forPlugins(RestEntitlementsCheckAction::java_lang_Thread$start)),
190+
entry("java_lang_Thread$setDaemon", deniedToPlugins(RestEntitlementsCheckAction::java_lang_Thread$setDaemon)),
191+
entry("java_lang_ThreadGroup$setDaemon", deniedToPlugins(RestEntitlementsCheckAction::java_lang_ThreadGroup$setDaemon)),
192+
entry(
193+
"java_util_concurrent_ForkJoinPool$setParallelism",
194+
deniedToPlugins(RestEntitlementsCheckAction::java_util_concurrent_ForkJoinPool$setParallelism)
195+
),
196+
entry("java_lang_Thread$setName", deniedToPlugins(RestEntitlementsCheckAction::java_lang_Thread$setName)),
197+
entry("java_lang_Thread$setPriority", deniedToPlugins(RestEntitlementsCheckAction::java_lang_Thread$setPriority)),
198+
entry(
199+
"java_lang_Thread$setUncaughtExceptionHandler",
200+
deniedToPlugins(RestEntitlementsCheckAction::java_lang_Thread$setUncaughtExceptionHandler)
201+
),
202+
entry(
203+
"java_lang_ThreadGroup$setMaxPriority",
204+
deniedToPlugins(RestEntitlementsCheckAction::java_lang_ThreadGroup$setMaxPriority)
205+
)
184206
),
185207
getTestEntries(FileCheckActions.class),
186208
getTestEntries(SpiActions.class),
@@ -422,7 +444,45 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli
422444
return channel -> {
423445
logger.info("Calling check action [{}]", actionName);
424446
checkAction.action().run();
447+
logger.debug("Check action [{}] returned", actionName);
425448
channel.sendResponse(new RestResponse(RestStatus.OK, Strings.format("Succesfully executed action [%s]", actionName)));
426449
};
427450
}
451+
452+
static void java_lang_Thread$start() throws InterruptedException {
453+
AtomicBoolean threadRan = new AtomicBoolean(false);
454+
Thread thread = EntitledActions.newThread(() -> threadRan.set(true), "test");
455+
thread.start();
456+
thread.join();
457+
assert threadRan.get();
458+
}
459+
460+
static void java_lang_Thread$setDaemon() {
461+
currentThread().setDaemon(currentThread().isDaemon());
462+
}
463+
464+
static void java_lang_ThreadGroup$setDaemon() {
465+
currentThread().getThreadGroup().setDaemon(currentThread().getThreadGroup().isDaemon());
466+
}
467+
468+
static void java_util_concurrent_ForkJoinPool$setParallelism() {
469+
ForkJoinPool.commonPool().setParallelism(ForkJoinPool.commonPool().getParallelism());
470+
}
471+
472+
static void java_lang_Thread$setName() {
473+
currentThread().setName(currentThread().getName());
474+
}
475+
476+
static void java_lang_Thread$setPriority() {
477+
currentThread().setPriority(currentThread().getPriority());
478+
}
479+
480+
static void java_lang_Thread$setUncaughtExceptionHandler() {
481+
currentThread().setUncaughtExceptionHandler(currentThread().getUncaughtExceptionHandler());
482+
}
483+
484+
static void java_lang_ThreadGroup$setMaxPriority() {
485+
currentThread().getThreadGroup().setMaxPriority(currentThread().getThreadGroup().getMaxPriority());
486+
}
487+
428488
}

libs/entitlement/qa/src/javaRestTest/java/org/elasticsearch/entitlement/qa/AbstractEntitlementsIT.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public abstract class AbstractEntitlementsIT extends ESRestTestCase {
2929
builder.value("inbound_network");
3030
builder.value("outbound_network");
3131
builder.value("load_native_libraries");
32+
builder.value("manage_threads");
3233
builder.value(
3334
Map.of(
3435
"write_system_properties",

libs/entitlement/qa/src/javaRestTest/java/org/elasticsearch/entitlement/qa/EntitlementsTestRule.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class EntitlementsTestRule implements TestRule {
3333

3434
// entitlements that test methods may use, see EntitledActions
3535
private static final PolicyBuilder ENTITLED_POLICY = (builder, tempDir) -> {
36-
builder.value(Map.of("write_system_properties", Map.of("properties", List.of("org.elasticsearch.entitlement.qa.selfTest"))));
36+
builder.value("manage_threads");
3737
builder.value(
3838
Map.of(
3939
"files",
@@ -74,6 +74,8 @@ protected void before() throws Throwable {
7474
.systemProperty("es.entitlements.enabled", "true")
7575
.systemProperty("es.entitlements.testdir", () -> testDir.getRoot().getAbsolutePath())
7676
.setting("xpack.security.enabled", "false")
77+
// Logs in libs/entitlement/qa/build/test-results/javaRestTest/TEST-org.elasticsearch.entitlement.qa.EntitlementsXXX.xml
78+
.setting("logger.org.elasticsearch.entitlement", "DEBUG")
7779
.build();
7880
ruleChain = RuleChain.outerRule(testDir).around(tempDirSetup).around(cluster);
7981
}

libs/entitlement/src/main/java/module-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919

2020
exports org.elasticsearch.entitlement.runtime.api;
2121
exports org.elasticsearch.entitlement.runtime.policy;
22-
exports org.elasticsearch.entitlement.runtime.policy.entitlements to org.elasticsearch.server;
2322
exports org.elasticsearch.entitlement.instrumentation;
2423
exports org.elasticsearch.entitlement.bootstrap to org.elasticsearch.server;
2524
exports org.elasticsearch.entitlement.initialization to java.base;
25+
exports org.elasticsearch.entitlement.runtime.policy.entitlements to org.elasticsearch.server;
2626

2727
uses org.elasticsearch.entitlement.instrumentation.InstrumentationService;
2828
}

libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.elasticsearch.entitlement.runtime.policy.entitlements.ExitVMEntitlement;
2727
import org.elasticsearch.entitlement.runtime.policy.entitlements.InboundNetworkEntitlement;
2828
import org.elasticsearch.entitlement.runtime.policy.entitlements.LoadNativeLibrariesEntitlement;
29+
import org.elasticsearch.entitlement.runtime.policy.entitlements.ManageThreadsEntitlement;
2930
import org.elasticsearch.entitlement.runtime.policy.entitlements.OutboundNetworkEntitlement;
3031

3132
import java.lang.instrument.Instrumentation;
@@ -123,7 +124,8 @@ private static PolicyManager createPolicyManager() {
123124
new CreateClassLoaderEntitlement(),
124125
new InboundNetworkEntitlement(),
125126
new OutboundNetworkEntitlement(),
126-
new LoadNativeLibrariesEntitlement()
127+
new LoadNativeLibrariesEntitlement(),
128+
new ManageThreadsEntitlement()
127129
)
128130
),
129131
new Scope("org.apache.httpcomponents.httpclient", List.of(new OutboundNetworkEntitlement())),

libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import java.util.Locale;
6666
import java.util.Properties;
6767
import java.util.TimeZone;
68+
import java.util.concurrent.ForkJoinPool;
6869
import java.util.function.Consumer;
6970

7071
import javax.net.ssl.HostnameVerifier;
@@ -998,4 +999,50 @@ public void checkSelectorProviderInheritedChannel(Class<?> callerClass, Selector
998999
public void checkNewInputStream(Class<?> callerClass, FileSystemProvider that, Path path, OpenOption... options) {
9991000
// TODO: policyManger.checkFileSystemRead(path);
10001001
}
1002+
1003+
// Thread management
1004+
1005+
@Override
1006+
public void check$java_lang_Thread$start(Class<?> callerClass, Thread thread) {
1007+
policyManager.checkManageThreadsEntitlement(callerClass);
1008+
}
1009+
1010+
@Override
1011+
public void check$java_lang_Thread$setDaemon(Class<?> callerClass, Thread thread, boolean on) {
1012+
policyManager.checkManageThreadsEntitlement(callerClass);
1013+
}
1014+
1015+
@Override
1016+
public void check$java_lang_ThreadGroup$setDaemon(Class<?> callerClass, ThreadGroup threadGroup, boolean daemon) {
1017+
policyManager.checkManageThreadsEntitlement(callerClass);
1018+
}
1019+
1020+
@Override
1021+
public void check$java_util_concurrent_ForkJoinPool$setParallelism(Class<?> callerClass, ForkJoinPool forkJoinPool, int size) {
1022+
policyManager.checkManageThreadsEntitlement(callerClass);
1023+
}
1024+
1025+
@Override
1026+
public void check$java_lang_Thread$setName(Class<?> callerClass, Thread thread, String name) {
1027+
policyManager.checkManageThreadsEntitlement(callerClass);
1028+
}
1029+
1030+
@Override
1031+
public void check$java_lang_Thread$setPriority(Class<?> callerClass, Thread thread, int newPriority) {
1032+
policyManager.checkManageThreadsEntitlement(callerClass);
1033+
}
1034+
1035+
@Override
1036+
public void check$java_lang_Thread$setUncaughtExceptionHandler(
1037+
Class<?> callerClass,
1038+
Thread thread,
1039+
Thread.UncaughtExceptionHandler ueh
1040+
) {
1041+
policyManager.checkManageThreadsEntitlement(callerClass);
1042+
}
1043+
1044+
@Override
1045+
public void check$java_lang_ThreadGroup$setMaxPriority(Class<?> callerClass, ThreadGroup threadGroup, int pri) {
1046+
policyManager.checkManageThreadsEntitlement(callerClass);
1047+
}
10011048
}

0 commit comments

Comments
 (0)