summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaikiran Pai <jaikiran@apache.org>2022-12-11 08:16:41 +0530
committerJaikiran Pai <jaikiran@apache.org>2022-12-11 13:43:58 +0530
commit82c70f3202d5aec4d99fa3b6314ba4a6c338cd94 (patch)
tree2cfb83174fb7255f7b16bd3419f1f892bc8eac55
parent7601bf1767a0c191ff22f661c8fde97302d0cd3a (diff)
downloadant-82c70f3202d5aec4d99fa3b6314ba4a6c338cd94.tar.gz
redo security manager setting to allow calling System.setSecurityManager at runtime
- Reverts the changes done to launch scripts which were checking for the Java runtime version to decide whether or not to set java.security.manager=allow - Introduces a new "allow" Java class (in unnamed package) as a workaround to allow setting java.security.manager=allow on (older) versions of Java which don't recognize "allow" as a predefined text for that property - Packages the "allow" Java class into ant-launcher.jar, which is the same jar file containing the org.apache.tools.ant.launch.Launcher class that gets launched from the Ant startup scripts - Sets java.security.manager=allow explicitly in Ant launch scripts, irrespective of which Java runtime version is being used
-rw-r--r--build.xml5
-rw-r--r--src/main/allow.java247
-rw-r--r--src/script/ant15
-rwxr-xr-xsrc/script/ant.bat21
4 files changed, 258 insertions, 30 deletions
diff --git a/build.xml b/build.xml
index 48378b078..10edf9de9 100644
--- a/build.xml
+++ b/build.xml
@@ -347,7 +347,10 @@
</selector>
<selector id="ant.launcher">
- <filename name="${ant.package}/launch/"/>
+ <or>
+ <filename name="${ant.package}/launch/"/>
+ <filename name="allow.*"/>
+ </or>
</selector>
<selector id="ant.core">
diff --git a/src/main/allow.java b/src/main/allow.java
new file mode 100644
index 000000000..3e88cd1b9
--- /dev/null
+++ b/src/main/allow.java
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+//
+// THIS CLASS IS INTENTIONALLY IN AN UNNAMED PACKAGE
+// (see the class level javadoc of this class for more details)
+//
+
+import java.io.FileDescriptor;
+import java.net.InetAddress;
+import java.security.Permission;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * This class is only here to allow setting the {@code java.security.manager} system property
+ * to a value of {@code allow}.
+ * <p>
+ * Certain versions of Java (like Java 8) do not recognize {@code allow}
+ * as a valid textual value for the {@code java.security.manager}, but some higher versions of
+ * Java do recognize this value. While launching Ant (from scripts for example), it isn't straightforward
+ * to identify which runtime version of Java is used to launch Ant. That then causes additional and
+ * complex scripting logic (that works across all supported OS platforms) to first identify the Java
+ * runtime version being used and then deciding whether or not to set {@code allow} as a value for
+ * that system property.
+ * </p>
+ * <p>
+ * The system property value for this {@code java.security.manager} is considered some predefined
+ * text or if it doesn't match that predefined text then is considered a fully qualified classname
+ * of a class which extends the {@link SecurityManager} class. We use that knowledge to workaround
+ * the problem we have with setting {@code allow} as the value for Java runtime which don't understand
+ * that value. This {@code allow} class belongs to an unnamed package and is packaged within a jar
+ * file {@code ant-launcher.jar} which Ant always adds to the classpath for launching Ant. That
+ * way, this class is available in the classpath and any Java versions that don't recognize
+ * {@code allow} as a predefined value will end up instantiating this class.
+ * </p>
+ * <p>
+ * The implementation in this class doesn't really provide any {@code SecurityManager} expected
+ * semantics. So this really isn't a {@code SecurityManager} implementation and shouldn't be used
+ * as one. If/when this class gets instantiated and is set as a {@code SecurityManager}, it will
+ * uninstall itself, on first use, by calling
+ * {@link System#setSecurityManager(SecurityManager) System.setSecurityManager(null)}. First use is
+ * defined as any call on a public method of this instance.
+ * This class intentionally uninstalls itself on first use to preserve the semantics of {@code allow}
+ * which merely implies that setting a security manager instance by the application code through the
+ * use of {@link System#setSecurityManager(SecurityManager)} is allowed.
+ * </p>
+ *
+ * @deprecated This isn't for public consumption and is an internal detail of Ant
+ */
+// This class has been copied over from the Apache NetBeans project
+@Deprecated
+public class allow extends SecurityManager {
+
+ private final AtomicBoolean uninstalling = new AtomicBoolean();
+
+ private void uninstall() {
+ if (uninstalling.compareAndSet(false, true)) {
+ // we set the security manager to null only when we ascertain that this class
+ // instance is the current installed security manager. We do this to avoid any race
+ // conditions where some other thread/caller had concurrently called
+ // System.setSecurityManager and we end up "null"ing that set instance.
+ // We rely on the (internal) detail that System.setSecurityManager is synchronized
+ // on the System.class
+ synchronized (System.class) {
+ final SecurityManager currentSecManager = System.getSecurityManager();
+ if (currentSecManager != this) {
+ return;
+ }
+ System.setSecurityManager(null);
+ }
+ }
+ }
+
+ @Override
+ public void checkAccept(String host, int port) {
+ uninstall();
+ }
+
+ @Override
+ public void checkAccess(Thread t) {
+ uninstall();
+ }
+
+ @Override
+ public void checkAccess(ThreadGroup g) {
+ uninstall();
+ }
+
+ @Override
+ public void checkAwtEventQueueAccess() {
+ uninstall();
+ }
+
+ @Override
+ public void checkConnect(String host, int port) {
+ uninstall();
+ }
+
+ @Override
+ public void checkConnect(String host, int port, Object context) {
+ uninstall();
+ }
+
+ @Override
+ public void checkCreateClassLoader() {
+ uninstall();
+ }
+
+ @Override
+ public void checkDelete(String file) {
+ uninstall();
+ }
+
+ @Override
+ public void checkExec(String cmd) {
+ uninstall();
+ }
+
+ @Override
+ public void checkExit(int status) {
+ uninstall();
+ }
+
+ @Override
+ public void checkLink(String lib) {
+ uninstall();
+ }
+
+ @Override
+ public void checkListen(int port) {
+ uninstall();
+ }
+
+ @Override
+ public void checkMemberAccess(Class<?> clazz, int which) {
+ uninstall();
+ }
+
+ @Override
+ public void checkMulticast(InetAddress maddr) {
+ uninstall();
+ }
+
+ @Override
+ public void checkMulticast(InetAddress maddr, byte ttl) {
+ uninstall();
+ }
+
+ @Override
+ public void checkPackageAccess(String pkg) {
+ uninstall();
+ }
+
+ @Override
+ public void checkPackageDefinition(String pkg) {
+ uninstall();
+ }
+
+ @Override
+ public void checkPermission(Permission perm) {
+ uninstall();
+ }
+
+ @Override
+ public void checkPermission(Permission perm, Object context) {
+ uninstall();
+ }
+
+ @Override
+ public void checkPrintJobAccess() {
+ uninstall();
+ }
+
+ @Override
+ public void checkPropertiesAccess() {
+ uninstall();
+ }
+
+ @Override
+ public void checkPropertyAccess(String key) {
+ uninstall();
+ }
+
+ @Override
+ public void checkRead(FileDescriptor fd) {
+ uninstall();
+ }
+
+ @Override
+ public void checkRead(String file) {
+ uninstall();
+ }
+
+ @Override
+ public void checkRead(String file, Object context) {
+ uninstall();
+ }
+
+ @Override
+ public void checkSecurityAccess(String target) {
+ uninstall();
+ }
+
+ @Override
+ public void checkSetFactory() {
+ uninstall();
+ }
+
+ @Override
+ public void checkSystemClipboardAccess() {
+ uninstall();
+ }
+
+ @Override
+ public boolean checkTopLevelWindow(Object window) {
+ uninstall();
+ // we return false because we don't know what thread would be calling this permission
+ // check method
+ return false;
+ }
+
+ @Override
+ public void checkWrite(FileDescriptor fd) {
+ uninstall();
+ }
+
+ @Override
+ public void checkWrite(String file) {
+ uninstall();
+ }
+}
+
diff --git a/src/script/ant b/src/script/ant
index ebc5e95ef..0507ff166 100644
--- a/src/script/ant
+++ b/src/script/ant
@@ -368,19 +368,8 @@ else
ant_sys_opts="-Djikes.class.path=\"$JIKESPATH\""
fi
fi
-# Run "java -XshowSettings:properties" and check the output for "java.specification.version" value
-JAVA_SPEC_VERSION=$("$JAVACMD" -XshowSettings:properties 2>&1 | sed -n -e 's/[[:space:]]//g' -e 's/^java\.specification\.version=//p')
-case "$JAVA_SPEC_VERSION" in
- 1.*)
- # Up to and including Java 8, versions are reported as 1.N.
- ;;
- *)
- if [ "$JAVA_SPEC_VERSION" -ge 18 ]; then
- # set security manager property to allow calls to System.setSecurityManager() at runtime
- ANT_OPTS="$ANT_OPTS -Djava.security.manager=allow"
- fi
- ;;
-esac
+# allow calling System.setSecurityManager at runtime
+ant_sys_opts="$ant_sys_opts -Djava.security.manager=allow"
ant_exec_command="exec \"\$JAVACMD\" $ANT_OPTS -classpath \"\$LOCALCLASSPATH\" -Dant.home=\"\$ANT_HOME\" -Dant.library.dir=\"\$ANT_LIB\" $ant_sys_opts org.apache.tools.ant.launch.Launcher $ANT_ARGS -cp \"\$CLASSPATH\""
if $ant_exec_debug; then
# using printf to avoid echo line continuation and escape interpretation confusion
diff --git a/src/script/ant.bat b/src/script/ant.bat
index 58dc3db86..574d8813d 100755
--- a/src/script/ant.bat
+++ b/src/script/ant.bat
@@ -57,6 +57,10 @@ rem CLASSPATH must not be used if it is equal to ""
if "%CLASSPATH%"=="""" set _USE_CLASSPATH=no
if "%CLASSPATH%"=="" set _USE_CLASSPATH=no
+rem allow calling System.setSecurityManager at runtime
+set "ANT_OPTS=%ANT_OPTS% -Djava.security.manager=allow"
+echo ANT_OPTS is set to %ANT_OPTS%
+
rem Slurp the command line arguments. This loop allows for an unlimited number
rem of arguments (up to the command line limit, anyway).
set ANT_CMD_LINE_ARGS=
@@ -117,26 +121,11 @@ set _JAVACMD=%JAVACMD%
if "%JAVA_HOME%" == "" goto noJavaHome
if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
if "%_JAVACMD%" == "" set _JAVACMD=%JAVA_HOME%\bin\java.exe
-goto setSecurityManagerOpt
+goto checkJikes
:noJavaHome
if "%_JAVACMD%" == "" set _JAVACMD=java.exe
-:setSecurityManagerOpt
-setlocal EnableDelayedExpansion
-"!_JAVACMD!" -XshowSettings:properties 2>&1 | find "java.specification.version = 18" >nul 2>&1
-if !errorlevel! EQU 0 (
- rem This is Java 18, so set -Djava.security.manager=allow
- set JAVA_SECMGR_OPT=-Djava.security.manager=allow
-) else (
- "!_JAVACMD!" -XshowSettings:properties 2>&1 | find "java.specification.version = 19" >nul 2>&1
- if !errorlevel! EQU 0 (
- rem This is Java 19, so set -Djava.security.manager=allow
- set JAVA_SECMGR_OPT=-Djava.security.manager=allow
- )
-)
-endlocal & set "ANT_OPTS=%ANT_OPTS% %JAVA_SECMGR_OPT%"
-
:checkJikes
if not "%JIKESPATH%"=="" goto runAntWithJikes