This is an automated email from the ASF dual-hosted git repository. jaikiran pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ant.git
The following commit(s) were added to refs/heads/master by this push: new 2821ba0d1 Throw BuildException when <permissions> is in use on Java 18 and higher 2821ba0d1 is described below commit 2821ba0d14f932df056e89afa7217e09d5eab270 Author: Jaikiran Pai <jaiki...@apache.org> AuthorDate: Wed Aug 16 15:39:27 2023 +0530 Throw BuildException when <permissions> is in use on Java 18 and higher --- manual/Types/permissions.html | 16 ++++++--- src/main/org/apache/tools/ant/MagicNames.java | 11 ++++++ .../org/apache/tools/ant/taskdefs/ExecuteJava.java | 4 ++- .../org/apache/tools/ant/types/Permissions.java | 41 ++++++++++++++++++---- .../apache/tools/ant/util/SecurityManagerUtil.java | 27 ++++++++++++++ .../ant/util/optional/NoExitSecurityManager.java | 2 ++ 6 files changed, 89 insertions(+), 12 deletions(-) diff --git a/manual/Types/permissions.html b/manual/Types/permissions.html index d0db0e327..b0c7e892d 100644 --- a/manual/Types/permissions.html +++ b/manual/Types/permissions.html @@ -25,11 +25,17 @@ <body> <h2 id="permissions">Permissions</h2> -<p><b>Note</b> <code>Permissions</code> requires the use of Java SecurityManager. - Java version 17 deprecated SecurityManager for removal and Java 18 by default disallowed - setting SecurityManager at runtime. <code>Permissions</code> is thus no longer supported - when used in Java 18 or higher versions. Using it in such Java runtime versions won't provide the - functionality that it originally provided.</p> +<p><b>Note:</b> <code>Permissions</code> requires the use of Java SecurityManager. + Java version 17 deprecated SecurityManager for removal and Java 18 and higher versions, by + default, disallow setting SecurityManager at runtime. <code>Permissions</code> is thus no longer + supported when used in Java 18 or higher versions. Using it in those Java runtime versions + will throw a <code>org.apache.tools.ant.BuildException</code>. Throwing of + <code>BuildException</code> can be relaxed by setting the + <code>ant.securitymanager.usage.warn</code> system or Ant property to <code>true</code>, + which will then cause a warning to be logged instead of the exception being thrown. Even when + <code>ant.securitymanager.usage.warn</code> is set to <code>true</code>, + SecurityManager usage will still be disabled and no security checks will be performed. + It is recommended to no longer use <code><permissions></code></p> <p>Permissions represents a set of security permissions granted or revoked to a specific part code executed in the JVM where Apache Ant is running in. The actual Permissions are specified diff --git a/src/main/org/apache/tools/ant/MagicNames.java b/src/main/org/apache/tools/ant/MagicNames.java index 12fbcf731..4e3b8735e 100644 --- a/src/main/org/apache/tools/ant/MagicNames.java +++ b/src/main/org/apache/tools/ant/MagicNames.java @@ -359,5 +359,16 @@ public final class MagicNames { */ public static final String DISABLE_NASHORN_COMPAT = "ant.disable.graal.nashorn.compat"; + /** + * When running on Java 18 or higher runtime, Ant will throw a {@link BuildException} + * if the {@linkplain org.apache.tools.ant.types.Permissions <permissions>} type is used. + * Set this property to {@code true} to disable throwing an exception and instead just log a + * warning message. + * + * Value: {@value} + * @since Ant 1.10.14 + */ + public static final String WARN_SECURITY_MANAGER_USAGE = "ant.securitymanager.usage.warn"; + } diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java b/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java index 0964c9132..cb0d1250f 100644 --- a/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java +++ b/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java @@ -211,9 +211,11 @@ public class ExecuteJava implements Runnable, TimeoutObserver { @Override public void run() { final Object[] argument = {javaCommand.getArguments()}; + boolean restoreSecMgr = false; try { if (perm != null) { perm.setSecurityManager(); + restoreSecMgr = true; } main.invoke(null, argument); } catch (InvocationTargetException e) { @@ -224,7 +226,7 @@ public class ExecuteJava implements Runnable, TimeoutObserver { } catch (Throwable t) { caught = t; } finally { - if (perm != null) { + if (perm != null && restoreSecMgr) { perm.restoreSecurityManager(); } synchronized (this) { diff --git a/src/main/org/apache/tools/ant/types/Permissions.java b/src/main/org/apache/tools/ant/types/Permissions.java index 703c8acc8..35144acf1 100644 --- a/src/main/org/apache/tools/ant/types/Permissions.java +++ b/src/main/org/apache/tools/ant/types/Permissions.java @@ -30,13 +30,13 @@ import java.util.StringTokenizer; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.ExitException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectComponent; import org.apache.tools.ant.util.SecurityManagerUtil; /** * This class implements a security manager meant for usage by tasks that run inside the * Ant VM. An examples are the Java Task and JUnitTask. - * <p> - * Note: This class doesn't provide any functionality for Java 18 and higher * * <p> * The basic functionality is that nothing (except for a base set of permissions) is allowed, unless @@ -46,9 +46,13 @@ import org.apache.tools.ant.util.SecurityManagerUtil; * It is not permissible to add permissions (either granted or revoked) while the Security Manager * is active (after calling setSecurityManager() but before calling restoreSecurityManager()). * + * <p> + * Note: This class isn't supported in Java 18 and higher where {@link SecurityManager} has been + * deprecated for removal. + * * @since Ant 1.6 */ -public class Permissions { +public class Permissions extends ProjectComponent { private final List<Permission> grantedPermissions = new LinkedList<>(); private final List<Permission> revokedPermissions = new LinkedList<>(); @@ -99,11 +103,24 @@ public class Permissions { * subject to these Permissions. Note that setting the SecurityManager too early may * prevent your part from starting, as for instance changing classloaders may be prohibited. * The classloader for the new situation is supposed to be present. + * <p> + * This method is no longer supported in Java 18 and higher versions and throws a + * {@link BuildException}. {@link org.apache.tools.ant.MagicNames#WARN_SECURITY_MANAGER_USAGE} + * property can be set to {@code true} to log a warning message instead of throwing the exception. + * * @throws BuildException on error */ public synchronized void setSecurityManager() throws BuildException { if (!SecurityManagerUtil.isSetSecurityManagerAllowed()) { - return; + final String msg = "Use of <permissions> or " + Permissions.class.getName() + + " is disallowed in current Java runtime version"; + if (SecurityManagerUtil.warnOnSecurityManagerUsage(getProject())) { + // just log a warning + log("Security checks are disabled - " + msg, Project.MSG_WARN); + return; + } else { + throw new BuildException(msg); + } } origSm = System.getSecurityManager(); init(); @@ -174,10 +191,22 @@ public class Permissions { /** * To be used by tasks that just finished executing the parts subject to these permissions. + * <p> + * This method is no longer supported in Java 18 and higher versions and throws a + * {@link BuildException}. {@link org.apache.tools.ant.MagicNames#WARN_SECURITY_MANAGER_USAGE} + * property can be set to {@code true} to log a warning message instead of throwing the exception. */ - public synchronized void restoreSecurityManager() { + public synchronized void restoreSecurityManager() throws BuildException { if (!SecurityManagerUtil.isSetSecurityManagerAllowed()) { - return; + final String msg = "Use of <permissions> or " + Permissions.class.getName() + + " is disallowed in current Java runtime version"; + if (SecurityManagerUtil.warnOnSecurityManagerUsage(getProject())) { + // just log a warning + log("Security checks are disabled - " + msg, Project.MSG_WARN); + return; + } else { + throw new BuildException(msg); + } } active = false; System.setSecurityManager(origSm); diff --git a/src/main/org/apache/tools/ant/util/SecurityManagerUtil.java b/src/main/org/apache/tools/ant/util/SecurityManagerUtil.java index e27b14efb..836a7b872 100644 --- a/src/main/org/apache/tools/ant/util/SecurityManagerUtil.java +++ b/src/main/org/apache/tools/ant/util/SecurityManagerUtil.java @@ -17,14 +17,41 @@ */ package org.apache.tools.ant.util; +import org.apache.tools.ant.MagicNames; +import org.apache.tools.ant.Project; + +/** + * @since Ant 1.10.14 + */ public final class SecurityManagerUtil { private static final boolean isJava18OrHigher = JavaEnvUtils.isAtLeastJavaVersion("18"); + private static final boolean sysPropWarnOnSecMgrUsage = + Boolean.getBoolean(MagicNames.WARN_SECURITY_MANAGER_USAGE); + /** + * {@return true if {@code SecurityManager} usage is allowed in current Java runtime. false + * otherwise} + */ public static boolean isSetSecurityManagerAllowed() { if (isJava18OrHigher) { return false; } return true; } + + /** + * {@return true if {@code SecurityManager} usage should only be logged as a warning. false + * otherwise} + */ + public static boolean warnOnSecurityManagerUsage(final Project project) { + if (project == null) { + return sysPropWarnOnSecMgrUsage; + } + final String val = project.getProperty(MagicNames.WARN_SECURITY_MANAGER_USAGE); + if (val == null) { + return sysPropWarnOnSecMgrUsage; + } + return Boolean.parseBoolean(val); + } } diff --git a/src/main/org/apache/tools/ant/util/optional/NoExitSecurityManager.java b/src/main/org/apache/tools/ant/util/optional/NoExitSecurityManager.java index 4df8ef099..f1559e9ab 100644 --- a/src/main/org/apache/tools/ant/util/optional/NoExitSecurityManager.java +++ b/src/main/org/apache/tools/ant/util/optional/NoExitSecurityManager.java @@ -26,6 +26,8 @@ import org.apache.tools.ant.ExitException; * The goal is to intercept System.exit calls and make it throw an * exception instead so that a System.exit in a task does not * fully terminate Ant. + * <p> + * This class is no longer supported in Java runtime versions 18 and higher. * * @see ExitException */