Skip to content

Commit efa051f

Browse files
rjernstsarog
authored andcommitted
Remove java.xml from system modules (elastic#133671) (elastic#133869)
java.xml is part of the jdk, but it's really a utility module that shouldn't have direct access to network or files. This commit excludes java.xml from system modules. Note that since it is part of the jdk, it does need access to read jdk classes, so a new internal entitlement is also added to allow reading jrt urls.
1 parent 0257ef5 commit efa051f

File tree

8 files changed

+76
-1
lines changed

8 files changed

+76
-1
lines changed

docs/changelog/133671.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 133671
2+
summary: Remove `java.xml` from system modules
3+
area: Infra/Core
4+
type: bug
5+
issues: []

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.core.SuppressForbidden;
1414
import org.elasticsearch.entitlement.qa.entitled.EntitledActions;
1515
import org.elasticsearch.env.Environment;
16+
import org.xml.sax.helpers.DefaultHandler;
1617

1718
import java.io.File;
1819
import java.io.FileDescriptor;
@@ -39,6 +40,7 @@
3940
import java.util.zip.ZipFile;
4041

4142
import javax.imageio.stream.FileImageInputStream;
43+
import javax.xml.parsers.SAXParserFactory;
4244

4345
import static java.nio.charset.Charset.defaultCharset;
4446
import static java.nio.file.StandardOpenOption.CREATE;
@@ -610,5 +612,12 @@ static void javaDesktopFileAccess() throws Exception {
610612
new FileImageInputStream(file.toFile()).close();
611613
}
612614

615+
@EntitlementTest(expectedAccess = ALWAYS_DENIED)
616+
static void javaXmlFileRequest() throws Exception {
617+
// java.xml is part of the jdk, but not a system module. this checks it can't access files
618+
var saxParser = SAXParserFactory.newInstance().newSAXParser();
619+
saxParser.parse(readFile().toFile(), new DefaultHandler());
620+
}
621+
613622
private FileCheckActions() {}
614623
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
import java.util.Locale;
1919
import java.util.TimeZone;
2020

21+
import javax.xml.parsers.SAXParserFactory;
22+
23+
import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_ALLOWED;
2124
import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_DENIED;
2225
import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS;
2326

@@ -80,5 +83,12 @@ static void createLogManager() {
8083
Thread.setDefaultUncaughtExceptionHandler(Thread.getDefaultUncaughtExceptionHandler());
8184
}
8285

86+
@EntitlementTest(expectedAccess = ALWAYS_ALLOWED)
87+
static void useJavaXmlParser() {
88+
// java.xml is part of the jdk, but not a system module. this checks it's actually usable
89+
// as it needs to read classes from the jdk which is not generally allowed
90+
SAXParserFactory.newInstance();
91+
}
92+
8393
private JvmActions() {}
8494
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package org.elasticsearch.entitlement.qa.test;
1111

1212
import org.elasticsearch.core.SuppressForbidden;
13+
import org.xml.sax.helpers.DefaultHandler;
1314

1415
import java.io.IOException;
1516
import java.net.DatagramPacket;
@@ -46,6 +47,7 @@
4647

4748
import javax.net.ssl.HttpsURLConnection;
4849
import javax.net.ssl.SSLContext;
50+
import javax.xml.parsers.SAXParserFactory;
4951

5052
import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_DENIED;
5153
import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS;
@@ -434,5 +436,12 @@ static void receiveDatagramSocket() throws IOException {
434436
}
435437
}
436438

439+
@EntitlementTest(expectedAccess = ALWAYS_DENIED)
440+
static void javaXmlNetworkRequest() throws Exception {
441+
// java.xml is part of the jdk, but not a system module. this checks it can't access the network
442+
var saxParser = SAXParserFactory.newInstance().newSAXParser();
443+
saxParser.parse("http://127.0.0.1/foo.json", new DefaultHandler());
444+
}
445+
437446
private NetworkAccessCheckActions() {}
438447
}

libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/HardcodedEntitlements.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.elasticsearch.entitlement.runtime.policy.entitlements.LoadNativeLibrariesEntitlement;
2222
import org.elasticsearch.entitlement.runtime.policy.entitlements.ManageThreadsEntitlement;
2323
import org.elasticsearch.entitlement.runtime.policy.entitlements.OutboundNetworkEntitlement;
24+
import org.elasticsearch.entitlement.runtime.policy.entitlements.ReadJdkImageEntitlement;
2425
import org.elasticsearch.entitlement.runtime.policy.entitlements.ReadStoreAttributesEntitlement;
2526
import org.elasticsearch.entitlement.runtime.policy.entitlements.SetHttpsConnectionPropertiesEntitlement;
2627
import org.elasticsearch.entitlement.runtime.policy.entitlements.WriteSystemPropertiesEntitlement;
@@ -114,6 +115,21 @@ private static List<Scope> createServerEntitlements(Path pidFile) {
114115
)
115116
),
116117
new Scope("java.desktop", List.of(new LoadNativeLibrariesEntitlement())),
118+
new Scope(
119+
"java.xml",
120+
List.of(
121+
new ReadJdkImageEntitlement(),
122+
// java.xml does some reflective stuff that reads calling jars, so allow reading the codebases
123+
// of any code in the system so that they can all use java.xml
124+
new FilesEntitlement(
125+
List.of(
126+
FilesEntitlement.FileData.ofBaseDirPath(LIB, READ),
127+
FilesEntitlement.FileData.ofBaseDirPath(MODULES, READ),
128+
FilesEntitlement.FileData.ofBaseDirPath(PLUGINS, READ)
129+
)
130+
)
131+
)
132+
),
117133
new Scope("org.apache.httpcomponents.httpclient", List.of(new OutboundNetworkEntitlement())),
118134
new Scope(
119135
"org.apache.lucene.core",

libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyCheckerImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.elasticsearch.entitlement.runtime.policy.entitlements.LoadNativeLibrariesEntitlement;
2222
import org.elasticsearch.entitlement.runtime.policy.entitlements.ManageThreadsEntitlement;
2323
import org.elasticsearch.entitlement.runtime.policy.entitlements.OutboundNetworkEntitlement;
24+
import org.elasticsearch.entitlement.runtime.policy.entitlements.ReadJdkImageEntitlement;
2425
import org.elasticsearch.entitlement.runtime.policy.entitlements.ReadStoreAttributesEntitlement;
2526
import org.elasticsearch.entitlement.runtime.policy.entitlements.SetHttpsConnectionPropertiesEntitlement;
2627
import org.elasticsearch.entitlement.runtime.policy.entitlements.WriteSystemPropertiesEntitlement;
@@ -490,6 +491,8 @@ public void checkEntitlementForUrl(Class<?> callerClass, URL url) {
490491
if (jarFileUrl == null || handleNetworkOrFileUrlCheck(callerClass, jarFileUrl) == false) {
491492
checkUnsupportedURLProtocolConnection(callerClass, "jar with unsupported inner protocol");
492493
}
494+
} else if (isJrtUrl(url)) {
495+
checkEntitlementPresent(callerClass, ReadJdkImageEntitlement.class);
493496
} else {
494497
checkUnsupportedURLProtocolConnection(callerClass, url.getProtocol());
495498
}
@@ -560,6 +563,10 @@ private static boolean isJarUrl(java.net.URL url) {
560563
return "jar".equals(url.getProtocol());
561564
}
562565

566+
private static boolean isJrtUrl(java.net.URL url) {
567+
return "jrt".equals(url.getProtocol());
568+
}
569+
563570
// We have to use class names for sun.net.www classes as java.base does not export them
564571
private static final List<String> ADDITIONAL_NETWORK_URL_CONNECT_CLASS_NAMES = List.of(
565572
"sun.net.www.protocol.ftp.FtpURLConnection",

libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public class PolicyManager {
5454
*/
5555
static final Logger generalLogger = LogManager.getLogger(PolicyManager.class);
5656

57-
static final Set<String> MODULES_EXCLUDED_FROM_SYSTEM_MODULES = Set.of("java.desktop");
57+
static final Set<String> MODULES_EXCLUDED_FROM_SYSTEM_MODULES = Set.of("java.desktop", "java.xml");
5858

5959
/**
6060
* Identifies a particular entitlement {@link Scope} within a {@link Policy}.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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.entitlement.runtime.policy.entitlements;
11+
12+
/**
13+
* Internal entitlement to read code from the jdk.
14+
*
15+
* Concretely this means the code can open jrt urls. Since the java
16+
* runtime images (jrt) are read only, this implicitly only allows
17+
* reading those urls.
18+
*/
19+
public class ReadJdkImageEntitlement implements Entitlement {}

0 commit comments

Comments
 (0)