diff --git a/manual/Types/permissions.html b/manual/Types/permissions.html index d0db0e3272..b0c7e892de 100644 --- a/manual/Types/permissions.html +++ b/manual/Types/permissions.html @@ -25,11 +25,17 @@

Permissions

-

Note Permissions requires the use of Java SecurityManager. - Java version 17 deprecated SecurityManager for removal and Java 18 by default disallowed - setting SecurityManager at runtime. Permissions 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.

+

Note: Permissions 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. Permissions is thus no longer + supported when used in Java 18 or higher versions. Using it in those Java runtime versions + will throw a org.apache.tools.ant.BuildException. Throwing of + BuildException can be relaxed by setting the + ant.securitymanager.usage.warn system or Ant property to true, + which will then cause a warning to be logged instead of the exception being thrown. Even when + ant.securitymanager.usage.warn is set to true, + SecurityManager usage will still be disabled and no security checks will be performed. + It is recommended to no longer use <permissions>

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 12fbcf7316..4e3b8735e7 100644 --- a/src/main/org/apache/tools/ant/MagicNames.java +++ b/src/main/org/apache/tools/ant/MagicNames.java @@ -359,5 +359,16 @@ private 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 } 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 0964c91329..cb0d1250fc 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 void execute(Project project) throws BuildException { @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 void run() { } 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 703c8acc86..35144acf13 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 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. - *

- * Note: This class doesn't provide any functionality for Java 18 and higher * *

* The basic functionality is that nothing (except for a base set of permissions) is allowed, unless @@ -46,9 +46,13 @@ * It is not permissible to add permissions (either granted or revoked) while the Security Manager * is active (after calling setSecurityManager() but before calling restoreSecurityManager()). * + *

+ * 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 grantedPermissions = new LinkedList<>(); private final List revokedPermissions = new LinkedList<>(); @@ -99,11 +103,24 @@ public void addConfiguredRevoke(final Permissions.Permission perm) { * 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. + *

+ * 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 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 @@ private java.security.Permission createPermission( /** * To be used by tasks that just finished executing the parts subject to these permissions. + *

+ * 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 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 e27b14efb5..836a7b872b 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 4df8ef099f..f1559e9abe 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 @@ * 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. + *

+ * This class is no longer supported in Java runtime versions 18 and higher. * * @see ExitException */