Skip to content

Commit

Permalink
Throw BuildException when <permissions> is in use on Java 18 and higher
Browse files Browse the repository at this point in the history
  • Loading branch information
jaikiran committed Aug 16, 2023
1 parent 185c3a0 commit 2821ba0
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 12 deletions.
16 changes: 11 additions & 5 deletions manual/Types/permissions.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>&lt;permissions&gt;</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
Expand Down
11 changes: 11 additions & 0 deletions src/main/org/apache/tools/ant/MagicNames.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 <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";

}

4 changes: 3 additions & 1 deletion src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -224,7 +226,7 @@ public void run() {
} catch (Throwable t) {
caught = t;
} finally {
if (perm != null) {
if (perm != null && restoreSecMgr) {
perm.restoreSecurityManager();
}
synchronized (this) {
Expand Down
41 changes: 35 additions & 6 deletions src/main/org/apache/tools/ant/types/Permissions.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <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
Expand All @@ -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()).
*
* <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<>();
Expand Down Expand Up @@ -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.
* <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();
Expand Down Expand Up @@ -174,10 +191,22 @@ private java.security.Permission createPermission(

/**
* 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);
Expand Down
27 changes: 27 additions & 0 deletions src/main/org/apache/tools/ant/util/SecurityManagerUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <p>
* This class is no longer supported in Java runtime versions 18 and higher.
*
* @see ExitException
*/
Expand Down

0 comments on commit 2821ba0

Please sign in to comment.