From 00244a7ac89bf7e49a7c43f15cfd8a4ac5ccf8ba Mon Sep 17 00:00:00 2001 From: Benjamin Marwell Date: Thu, 19 Oct 2023 22:48:09 +0200 Subject: [PATCH] [#286] disable SecurityManager starting with Java 21 --- pom.xml | 23 ++++++++++ .../codehaus/gmavenplus/mojo/ShellMojo.java | 13 +++--- .../util/AbstractSecurityManagerSetter.java | 23 ++++++++++ .../util/DefaultSecurityManagerSetter.java | 46 +++++++++++++++++++ .../util/SecurityManagerSetter.java | 19 ++++++++ .../util/DefaultSecurityManagerSetter.java | 30 ++++++++++++ 6 files changed, 147 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/codehaus/gmavenplus/util/AbstractSecurityManagerSetter.java create mode 100644 src/main/java/org/codehaus/gmavenplus/util/DefaultSecurityManagerSetter.java create mode 100644 src/main/java/org/codehaus/gmavenplus/util/SecurityManagerSetter.java create mode 100644 src/main/java21/org/codehaus/gmavenplus/util/DefaultSecurityManagerSetter.java diff --git a/pom.xml b/pom.xml index b028bb0e..4602d76c 100644 --- a/pom.xml +++ b/pom.xml @@ -263,6 +263,22 @@ -Xlint:all + + + compile-java21 + compile + + compile + + + + ${project.basedir}/src/main/java21 + + + ${project.build.outputDirectory}/META-INF/versions/21 + + + org.codehaus.plexus @@ -345,6 +361,13 @@ org.apache.maven.plugins maven-jar-plugin 3.3.0 + + + + true + + + org.apache.maven.plugins diff --git a/src/main/java/org/codehaus/gmavenplus/mojo/ShellMojo.java b/src/main/java/org/codehaus/gmavenplus/mojo/ShellMojo.java index 112bf639..c52b7baa 100644 --- a/src/main/java/org/codehaus/gmavenplus/mojo/ShellMojo.java +++ b/src/main/java/org/codehaus/gmavenplus/mojo/ShellMojo.java @@ -22,11 +22,13 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.codehaus.gmavenplus.model.internal.Version; +import org.codehaus.gmavenplus.util.DefaultSecurityManagerSetter; import org.codehaus.gmavenplus.util.NoExitSecurityManager; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; +import org.codehaus.gmavenplus.util.SecurityManagerSetter; import static org.codehaus.gmavenplus.mojo.ExecuteMojo.GROOVY_4_0_0_RC_1; import static org.codehaus.gmavenplus.util.ReflectionUtils.findConstructor; @@ -91,11 +93,10 @@ public void execute() throws MojoExecutionException { } if (groovyVersionSupportsAction()) { - final SecurityManager sm = System.getSecurityManager(); + final SecurityManagerSetter securityManagerSetter = new DefaultSecurityManagerSetter(getLog(), this.allowSystemExits); + try { - if (!allowSystemExits) { - System.setSecurityManager(new NoExitSecurityManager()); - } + securityManagerSetter.setNoExitSecurityManager(); // get classes we need with reflection Class shellClass = classWrangler.getClass(groovyAtLeast(GROOVY_4_0_0_ALPHA1) ? "org.apache.groovy.groovysh.Groovysh" : "org.codehaus.groovy.tools.shell.Groovysh"); @@ -122,9 +123,7 @@ public void execute() throws MojoExecutionException { } catch (InstantiationException e) { throw new MojoExecutionException("Error occurred while instantiating a Groovy class from classpath.", e); } finally { - if (!allowSystemExits) { - System.setSecurityManager(sm); - } + securityManagerSetter.revertToPreviousSecurityManager(); } } else { getLog().error("Your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support running a shell. The minimum version of Groovy required is " + minGroovyVersion + ". Skipping shell startup."); diff --git a/src/main/java/org/codehaus/gmavenplus/util/AbstractSecurityManagerSetter.java b/src/main/java/org/codehaus/gmavenplus/util/AbstractSecurityManagerSetter.java new file mode 100644 index 00000000..2a291e53 --- /dev/null +++ b/src/main/java/org/codehaus/gmavenplus/util/AbstractSecurityManagerSetter.java @@ -0,0 +1,23 @@ +package org.codehaus.gmavenplus.util; + +import org.apache.maven.plugin.logging.Log; + +public abstract class AbstractSecurityManagerSetter implements SecurityManagerSetter{ + + private final boolean allowSystemExits; + + private final Log log; + + public AbstractSecurityManagerSetter(final Log log, final boolean allowSystemExits) { + this.log = log; + this.allowSystemExits = allowSystemExits; + } + + protected boolean getAllowSystemExits() { + return allowSystemExits; + } + + protected Log getLog() { + return log; + } +} diff --git a/src/main/java/org/codehaus/gmavenplus/util/DefaultSecurityManagerSetter.java b/src/main/java/org/codehaus/gmavenplus/util/DefaultSecurityManagerSetter.java new file mode 100644 index 00000000..110de536 --- /dev/null +++ b/src/main/java/org/codehaus/gmavenplus/util/DefaultSecurityManagerSetter.java @@ -0,0 +1,46 @@ +package org.codehaus.gmavenplus.util; + +import java.util.concurrent.atomic.AtomicReference; +import org.apache.maven.plugin.logging.Log; + +public class DefaultSecurityManagerSetter extends AbstractSecurityManagerSetter { + + private final AtomicReference previousSecurityManager = new AtomicReference<>(); + + public DefaultSecurityManagerSetter(Log log, final boolean allowSystemExits) { + super(log, allowSystemExits); + } + + @Override + public void setNoExitSecurityManager() { + if (this.getAllowSystemExits()) { + return; + } + + this.previousSecurityManager.set(System.getSecurityManager()); + + getLog().warn("Setting a security manager is deprecated. Running this build with Java 21 or newer might result in different behaviour."); + System.setSecurityManager(new NoExitSecurityManager()); + } + + @Override + public void revertToPreviousSecurityManager() { + if (this.getAllowSystemExits()) { + return; + } + + this.getPreviousSecurityManager().getAndUpdate((previousSecurityManager -> { + if (previousSecurityManager == null) { + return null; + } + + System.setSecurityManager(previousSecurityManager); + + return null; + })); + } + + protected AtomicReference getPreviousSecurityManager() { + return previousSecurityManager; + } +} diff --git a/src/main/java/org/codehaus/gmavenplus/util/SecurityManagerSetter.java b/src/main/java/org/codehaus/gmavenplus/util/SecurityManagerSetter.java new file mode 100644 index 00000000..4ddaaf60 --- /dev/null +++ b/src/main/java/org/codehaus/gmavenplus/util/SecurityManagerSetter.java @@ -0,0 +1,19 @@ +package org.codehaus.gmavenplus.util; + +/** + * Sets a custom security manager and returns the previous instance. + * Can also revert to the previous security Manager. + *

+ * Implementation notice: For Java 21 and above, + * the implementation must be a no-op and issue a warning. + * + */ +public interface SecurityManagerSetter { + + /** + * For Java until 20, this method should set the given Security manager if property {@code allowSystemExits} is set. + */ + void setNoExitSecurityManager(); + + void revertToPreviousSecurityManager(); +} diff --git a/src/main/java21/org/codehaus/gmavenplus/util/DefaultSecurityManagerSetter.java b/src/main/java21/org/codehaus/gmavenplus/util/DefaultSecurityManagerSetter.java new file mode 100644 index 00000000..57f230bb --- /dev/null +++ b/src/main/java21/org/codehaus/gmavenplus/util/DefaultSecurityManagerSetter.java @@ -0,0 +1,30 @@ +package org.codehaus.gmavenplus.util; + +import java.util.concurrent.atomic.AtomicReference; +import org.apache.maven.plugin.logging.Log; + +public class DefaultSecurityManagerSetter extends AbstractSecurityManagerSetter { + + public DefaultSecurityManagerSetter(Log log, final boolean allowSystemExits) { + super(log, allowSystemExits); + } + + @Override + public void setNoExitSecurityManager() { + if (this.getAllowSystemExits()) { + return; + } + + getLog().warn("Setting a security manager is not supported starting with Java 21."); + } + + @Override + public void revertToPreviousSecurityManager() { + if (this.getAllowSystemExits()) { + return; + } + + getLog().warn("Setting a security manager is not supported starting with Java 21."); + + } +}