Skip to content

Commit ba9e0ce

Browse files
authored
Do not try to enable SecurityManager on JDK 24 (#117999)
1 parent 8aa49d9 commit ba9e0ce

File tree

13 files changed

+111
-28
lines changed

13 files changed

+111
-28
lines changed

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchTestBasePlugin.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.elasticsearch.gradle.test.GradleTestPolicySetupPlugin;
2121
import org.elasticsearch.gradle.test.SystemPropertyCommandLineArgumentProvider;
2222
import org.gradle.api.Action;
23+
import org.gradle.api.JavaVersion;
2324
import org.gradle.api.Plugin;
2425
import org.gradle.api.Project;
2526
import org.gradle.api.Task;
@@ -112,7 +113,6 @@ public void execute(Task t) {
112113
test.jvmArgs(
113114
"-Xmx" + System.getProperty("tests.heap.size", "512m"),
114115
"-Xms" + System.getProperty("tests.heap.size", "512m"),
115-
"-Djava.security.manager=allow",
116116
"-Dtests.testfeatures.enabled=true",
117117
"--add-opens=java.base/java.util=ALL-UNNAMED",
118118
// TODO: only open these for mockito when it is modularized
@@ -127,6 +127,13 @@ public void execute(Task t) {
127127
);
128128

129129
test.getJvmArgumentProviders().add(new SimpleCommandLineArgumentProvider("-XX:HeapDumpPath=" + heapdumpDir));
130+
test.getJvmArgumentProviders().add(() -> {
131+
if (test.getJavaVersion().compareTo(JavaVersion.VERSION_23) <= 0) {
132+
return List.of("-Djava.security.manager=allow");
133+
} else {
134+
return List.of();
135+
}
136+
});
130137

131138
String argline = System.getProperty("tests.jvm.argline");
132139
if (argline != null) {

build-tools/src/main/java/org/elasticsearch/gradle/test/GradleTestPolicySetupPlugin.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99

1010
package org.elasticsearch.gradle.test;
1111

12+
import org.gradle.api.JavaVersion;
1213
import org.gradle.api.Plugin;
1314
import org.gradle.api.Project;
1415
import org.gradle.api.invocation.Gradle;
1516
import org.gradle.api.tasks.testing.Test;
1617

18+
import java.util.List;
19+
1720
public class GradleTestPolicySetupPlugin implements Plugin<Project> {
1821

1922
@Override
@@ -23,8 +26,13 @@ public void apply(Project project) {
2326
test.systemProperty("tests.gradle", true);
2427
test.systemProperty("tests.task", test.getPath());
2528

26-
// Flag is required for later Java versions since our tests use a custom security manager
27-
test.jvmArgs("-Djava.security.manager=allow");
29+
test.getJvmArgumentProviders().add(() -> {
30+
if (test.getJavaVersion().compareTo(JavaVersion.VERSION_23) <= 0) {
31+
return List.of("-Djava.security.manager=allow");
32+
} else {
33+
return List.of();
34+
}
35+
});
2836

2937
SystemPropertyCommandLineArgumentProvider nonInputProperties = new SystemPropertyCommandLineArgumentProvider();
3038
// don't track these as inputs since they contain absolute paths and break cache relocatability

distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/SystemJvmOptions.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
import org.elasticsearch.common.settings.Settings;
1313
import org.elasticsearch.common.util.concurrent.EsExecutors;
14+
import org.elasticsearch.core.UpdateForV9;
15+
import org.elasticsearch.jdk.RuntimeVersionFeature;
1416

1517
import java.io.IOException;
1618
import java.nio.file.Files;
@@ -137,9 +139,13 @@ private static Stream<String> maybeWorkaroundG1Bug() {
137139
return Stream.of();
138140
}
139141

142+
@UpdateForV9(owner = UpdateForV9.Owner.CORE_INFRA)
140143
private static Stream<String> maybeAllowSecurityManager() {
141-
// Will become conditional on useEntitlements once entitlements can run without SM
142-
return Stream.of("-Djava.security.manager=allow");
144+
if (RuntimeVersionFeature.isSecurityManagerAvailable()) {
145+
// Will become conditional on useEntitlements once entitlements can run without SM
146+
return Stream.of("-Djava.security.manager=allow");
147+
}
148+
return Stream.of();
143149
}
144150

145151
private static Stream<String> maybeAttachEntitlementAgent(boolean useEntitlements) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.jdk;
11+
12+
import org.elasticsearch.core.UpdateForV9;
13+
14+
public class RuntimeVersionFeature {
15+
private RuntimeVersionFeature() {}
16+
17+
@UpdateForV9(owner = UpdateForV9.Owner.CORE_INFRA) // Remove once we removed all references to SecurityManager in code
18+
public static boolean isSecurityManagerAvailable() {
19+
return Runtime.version().feature() < 24;
20+
}
21+
}

libs/secure-sm/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@ tasks.named('forbiddenApisMain').configure {
2828
tasks.named("jarHell").configure { enabled = false }
2929
tasks.named("testTestingConventions").configure {
3030
baseClass 'junit.framework.TestCase'
31+
baseClass 'org.junit.Assert'
3132
}

libs/secure-sm/src/test/java/org/elasticsearch/secure_sm/SecureSMTests.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,43 @@
99

1010
package org.elasticsearch.secure_sm;
1111

12-
import junit.framework.TestCase;
12+
import com.carrotsearch.randomizedtesting.JUnit3MethodProvider;
13+
import com.carrotsearch.randomizedtesting.RandomizedRunner;
14+
import com.carrotsearch.randomizedtesting.RandomizedTest;
15+
import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders;
16+
17+
import org.elasticsearch.jdk.RuntimeVersionFeature;
18+
import org.junit.BeforeClass;
19+
import org.junit.runner.RunWith;
1320

1421
import java.security.Permission;
1522
import java.security.Policy;
1623
import java.security.ProtectionDomain;
1724
import java.util.ArrayList;
1825
import java.util.List;
26+
import java.util.Set;
1927
import java.util.concurrent.atomic.AtomicBoolean;
2028
import java.util.stream.Collectors;
2129

2230
/** Simple tests for SecureSM */
23-
public class SecureSMTests extends TestCase {
24-
static {
31+
@TestMethodProviders({ JUnit3MethodProvider.class })
32+
@RunWith(RandomizedRunner.class)
33+
public class SecureSMTests extends org.junit.Assert {
34+
35+
@BeforeClass
36+
public static void initialize() {
37+
RandomizedTest.assumeFalse(
38+
"SecurityManager has been permanently removed in JDK 24",
39+
RuntimeVersionFeature.isSecurityManagerAvailable() == false
40+
);
2541
// install a mock security policy:
2642
// AllPermission to source code
2743
// ThreadPermission not granted anywhere else
28-
final ProtectionDomain sourceCode = SecureSM.class.getProtectionDomain();
44+
final var sourceCode = Set.of(SecureSM.class.getProtectionDomain(), RandomizedRunner.class.getProtectionDomain());
2945
Policy.setPolicy(new Policy() {
3046
@Override
3147
public boolean implies(ProtectionDomain domain, Permission permission) {
32-
if (domain == sourceCode) {
48+
if (sourceCode.contains(domain)) {
3349
return true;
3450
} else if (permission instanceof ThreadPermission) {
3551
return false;

server/src/main/java/org/elasticsearch/bootstrap/BootstrapChecks.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.elasticsearch.core.SuppressForbidden;
2222
import org.elasticsearch.discovery.DiscoveryModule;
2323
import org.elasticsearch.index.IndexModule;
24+
import org.elasticsearch.jdk.RuntimeVersionFeature;
2425
import org.elasticsearch.monitor.jvm.JvmInfo;
2526
import org.elasticsearch.monitor.process.ProcessProbe;
2627
import org.elasticsearch.nativeaccess.NativeAccess;
@@ -722,6 +723,9 @@ public final BootstrapCheckResult check(BootstrapContext context) {
722723
}
723724

724725
boolean isAllPermissionGranted() {
726+
if (RuntimeVersionFeature.isSecurityManagerAvailable() == false) {
727+
return false;
728+
}
725729
final SecurityManager sm = System.getSecurityManager();
726730
assert sm != null;
727731
try {

server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.elasticsearch.env.Environment;
3636
import org.elasticsearch.index.IndexVersion;
3737
import org.elasticsearch.jdk.JarHell;
38+
import org.elasticsearch.jdk.RuntimeVersionFeature;
3839
import org.elasticsearch.monitor.jvm.HotThreads;
3940
import org.elasticsearch.monitor.jvm.JvmInfo;
4041
import org.elasticsearch.monitor.os.OsProbe;
@@ -113,12 +114,14 @@ private static Bootstrap initPhase1() {
113114
* the presence of a security manager or lack thereof act as if there is a security manager present (e.g., DNS cache policy).
114115
* This forces such policies to take effect immediately.
115116
*/
116-
org.elasticsearch.bootstrap.Security.setSecurityManager(new SecurityManager() {
117-
@Override
118-
public void checkPermission(Permission perm) {
119-
// grant all permissions so that we can later set the security manager to the one that we want
120-
}
121-
});
117+
if (RuntimeVersionFeature.isSecurityManagerAvailable()) {
118+
org.elasticsearch.bootstrap.Security.setSecurityManager(new SecurityManager() {
119+
@Override
120+
public void checkPermission(Permission perm) {
121+
// grant all permissions so that we can later set the security manager to the one that we want
122+
}
123+
});
124+
}
122125
LogConfigurator.registerErrorListener();
123126

124127
BootstrapInfo.init();
@@ -215,14 +218,16 @@ private static void initPhase2(Bootstrap bootstrap) throws IOException {
215218
.toList();
216219

217220
EntitlementBootstrap.bootstrap(pluginData, pluginsResolver::resolveClassToPluginName);
218-
} else {
221+
} else if (RuntimeVersionFeature.isSecurityManagerAvailable()) {
219222
// install SM after natives, shutdown hooks, etc.
220223
LogManager.getLogger(Elasticsearch.class).info("Bootstrapping java SecurityManager");
221224
org.elasticsearch.bootstrap.Security.configure(
222225
nodeEnv,
223226
SECURITY_FILTER_BAD_DEFAULTS_SETTING.get(args.nodeSettings()),
224227
args.pidFile()
225228
);
229+
} else {
230+
LogManager.getLogger(Elasticsearch.class).warn("Bootstrapping without any protection");
226231
}
227232
}
228233

server/src/test/java/org/elasticsearch/bootstrap/ESPolicyTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
package org.elasticsearch.bootstrap;
1111

12+
import org.elasticsearch.jdk.RuntimeVersionFeature;
1213
import org.elasticsearch.test.ESTestCase;
1314

1415
import java.security.AccessControlContext;
@@ -27,7 +28,10 @@ public class ESPolicyTests extends ESTestCase {
2728
* test restricting privileges to no permissions actually works
2829
*/
2930
public void testRestrictPrivileges() {
30-
assumeTrue("test requires security manager", System.getSecurityManager() != null);
31+
assumeTrue(
32+
"test requires security manager",
33+
RuntimeVersionFeature.isSecurityManagerAvailable() && System.getSecurityManager() != null
34+
);
3135
try {
3236
System.getProperty("user.home");
3337
} catch (SecurityException e) {

server/src/test/java/org/elasticsearch/bootstrap/SecurityTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
package org.elasticsearch.bootstrap;
1111

12+
import org.elasticsearch.jdk.RuntimeVersionFeature;
1213
import org.elasticsearch.test.ESTestCase;
1314

1415
import java.io.IOException;
@@ -50,7 +51,10 @@ public void testEnsureRegularFile() throws IOException {
5051

5152
/** can't execute processes */
5253
public void testProcessExecution() throws Exception {
53-
assumeTrue("test requires security manager", System.getSecurityManager() != null);
54+
assumeTrue(
55+
"test requires security manager",
56+
RuntimeVersionFeature.isSecurityManagerAvailable() && System.getSecurityManager() != null
57+
);
5458
try {
5559
Runtime.getRuntime().exec("ls");
5660
fail("didn't get expected exception");

0 commit comments

Comments
 (0)