diff --git a/docs/changelog/133671.yaml b/docs/changelog/133671.yaml new file mode 100644 index 0000000000000..ee16f659e9b27 --- /dev/null +++ b/docs/changelog/133671.yaml @@ -0,0 +1,5 @@ +pr: 133671 +summary: Remove `java.xml` from system modules +area: Infra/Core +type: bug +issues: [] diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileCheckActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileCheckActions.java index 0adfbf66c6a23..3ded3e3ac8924 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileCheckActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileCheckActions.java @@ -13,6 +13,7 @@ import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.entitlement.qa.entitled.EntitledActions; import org.elasticsearch.env.Environment; +import org.xml.sax.helpers.DefaultHandler; import java.io.File; import java.io.FileDescriptor; @@ -39,6 +40,7 @@ import java.util.zip.ZipFile; import javax.imageio.stream.FileImageInputStream; +import javax.xml.parsers.SAXParserFactory; import static java.nio.charset.Charset.defaultCharset; import static java.nio.file.StandardOpenOption.CREATE; @@ -610,5 +612,12 @@ static void javaDesktopFileAccess() throws Exception { new FileImageInputStream(file.toFile()).close(); } + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void javaXmlFileRequest() throws Exception { + // java.xml is part of the jdk, but not a system module. this checks it can't access files + var saxParser = SAXParserFactory.newInstance().newSAXParser(); + saxParser.parse(readFile().toFile(), new DefaultHandler()); + } + private FileCheckActions() {} } diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/JvmActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/JvmActions.java index 29e4ffccce0b3..8fa250c886572 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/JvmActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/JvmActions.java @@ -18,6 +18,9 @@ import java.util.Locale; import java.util.TimeZone; +import javax.xml.parsers.SAXParserFactory; + +import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_ALLOWED; import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_DENIED; import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS; @@ -80,5 +83,12 @@ static void createLogManager() { Thread.setDefaultUncaughtExceptionHandler(Thread.getDefaultUncaughtExceptionHandler()); } + @EntitlementTest(expectedAccess = ALWAYS_ALLOWED) + static void useJavaXmlParser() { + // java.xml is part of the jdk, but not a system module. this checks it's actually usable + // as it needs to read classes from the jdk which is not generally allowed + SAXParserFactory.newInstance(); + } + private JvmActions() {} } diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NetworkAccessCheckActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NetworkAccessCheckActions.java index 7b99aab0a19e4..af82a29c750e9 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NetworkAccessCheckActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NetworkAccessCheckActions.java @@ -10,6 +10,7 @@ package org.elasticsearch.entitlement.qa.test; import org.elasticsearch.core.SuppressForbidden; +import org.xml.sax.helpers.DefaultHandler; import java.io.IOException; import java.net.DatagramPacket; @@ -46,6 +47,7 @@ import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; +import javax.xml.parsers.SAXParserFactory; import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_DENIED; import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS; @@ -434,5 +436,12 @@ static void receiveDatagramSocket() throws IOException { } } + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void javaXmlNetworkRequest() throws Exception { + // java.xml is part of the jdk, but not a system module. this checks it can't access the network + var saxParser = SAXParserFactory.newInstance().newSAXParser(); + saxParser.parse("http://127.0.0.1/foo.json", new DefaultHandler()); + } + private NetworkAccessCheckActions() {} } diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/HardcodedEntitlements.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/HardcodedEntitlements.java index 01e1092f53d00..bdc4c92b404aa 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/HardcodedEntitlements.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/HardcodedEntitlements.java @@ -21,6 +21,7 @@ import org.elasticsearch.entitlement.runtime.policy.entitlements.LoadNativeLibrariesEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.ManageThreadsEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.OutboundNetworkEntitlement; +import org.elasticsearch.entitlement.runtime.policy.entitlements.ReadJdkImageEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.ReadStoreAttributesEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.SetHttpsConnectionPropertiesEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.WriteSystemPropertiesEntitlement; @@ -114,6 +115,21 @@ private static List createServerEntitlements(Path pidFile) { ) ), new Scope("java.desktop", List.of(new LoadNativeLibrariesEntitlement())), + new Scope( + "java.xml", + List.of( + new ReadJdkImageEntitlement(), + // java.xml does some reflective stuff that reads calling jars, so allow reading the codebases + // of any code in the system so that they can all use java.xml + new FilesEntitlement( + List.of( + FilesEntitlement.FileData.ofBaseDirPath(LIB, READ), + FilesEntitlement.FileData.ofBaseDirPath(MODULES, READ), + FilesEntitlement.FileData.ofBaseDirPath(PLUGINS, READ) + ) + ) + ) + ), new Scope("org.apache.httpcomponents.httpclient", List.of(new OutboundNetworkEntitlement())), new Scope( "org.apache.lucene.core", diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyCheckerImpl.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyCheckerImpl.java index acfdbb0caded7..e4dcd4758d544 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyCheckerImpl.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyCheckerImpl.java @@ -21,6 +21,7 @@ import org.elasticsearch.entitlement.runtime.policy.entitlements.LoadNativeLibrariesEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.ManageThreadsEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.OutboundNetworkEntitlement; +import org.elasticsearch.entitlement.runtime.policy.entitlements.ReadJdkImageEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.ReadStoreAttributesEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.SetHttpsConnectionPropertiesEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.WriteSystemPropertiesEntitlement; @@ -490,6 +491,8 @@ public void checkEntitlementForUrl(Class callerClass, URL url) { if (jarFileUrl == null || handleNetworkOrFileUrlCheck(callerClass, jarFileUrl) == false) { checkUnsupportedURLProtocolConnection(callerClass, "jar with unsupported inner protocol"); } + } else if (isJrtUrl(url)) { + checkEntitlementPresent(callerClass, ReadJdkImageEntitlement.class); } else { checkUnsupportedURLProtocolConnection(callerClass, url.getProtocol()); } @@ -560,6 +563,10 @@ private static boolean isJarUrl(java.net.URL url) { return "jar".equals(url.getProtocol()); } + private static boolean isJrtUrl(java.net.URL url) { + return "jrt".equals(url.getProtocol()); + } + // We have to use class names for sun.net.www classes as java.base does not export them private static final List ADDITIONAL_NETWORK_URL_CONNECT_CLASS_NAMES = List.of( "sun.net.www.protocol.ftp.FtpURLConnection", diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java index df68da2e251ac..3c5948d7824b7 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java @@ -54,7 +54,7 @@ public class PolicyManager { */ static final Logger generalLogger = LogManager.getLogger(PolicyManager.class); - static final Set MODULES_EXCLUDED_FROM_SYSTEM_MODULES = Set.of("java.desktop"); + static final Set MODULES_EXCLUDED_FROM_SYSTEM_MODULES = Set.of("java.desktop", "java.xml"); /** * Identifies a particular entitlement {@link Scope} within a {@link Policy}. diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/ReadJdkImageEntitlement.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/ReadJdkImageEntitlement.java new file mode 100644 index 0000000000000..fa13203204c30 --- /dev/null +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/ReadJdkImageEntitlement.java @@ -0,0 +1,19 @@ +/* + * 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.entitlement.runtime.policy.entitlements; + +/** + * Internal entitlement to read code from the jdk. + * + * Concretely this means the code can open jrt urls. Since the java + * runtime images (jrt) are read only, this implicitly only allows + * reading those urls. + */ +public class ReadJdkImageEntitlement implements Entitlement {}