diff --git a/securesm/src/main/java/org/elasticsearch/SecureSM.java b/securesm/src/main/java/org/elasticsearch/SecureSM.java index c0ad45c44d0..c8b4bee5262 100644 --- a/securesm/src/main/java/org/elasticsearch/SecureSM.java +++ b/securesm/src/main/java/org/elasticsearch/SecureSM.java @@ -63,7 +63,7 @@ import java.util.Objects; */ public class SecureSM extends SecurityManager { - private final String[] packagesThatCanExit; + private final String[] classesThatCanExit; /** * Creates a new security manager where no packages can exit nor halt the virtual machine. @@ -73,22 +73,24 @@ public class SecureSM extends SecurityManager { } /** - * Creates a new security manager with the specified list of packages being the only packages - * that can exit or halt the virtual machine. + * Creates a new security manager with the specified list of regular expressions as the those that class names will be tested against to + * check whether or not a class can exit or halt the virtual machine. * - * @param packagesThatCanExit the list of packages that can exit or halt the virtual machine + * @param classesThatCanExit the list of classes that can exit or halt the virtual machine */ - public SecureSM(final String[] packagesThatCanExit) { - this.packagesThatCanExit = packagesThatCanExit; + public SecureSM(final String[] classesThatCanExit) { + this.classesThatCanExit = classesThatCanExit; } /** - * Creates a new security manager with a standard set of test packages being the only packages - * that can exit or halt the virtual machine. The packages that can exit are + * Creates a new security manager with a standard set of test packages being the only packages that can exit or halt the virtual machine. + * The packages that can exit are: + * * * @return an instance of SecureSM where test packages can halt or exit the virtual machine */ @@ -96,15 +98,15 @@ public class SecureSM extends SecurityManager { return new SecureSM(TEST_RUNNER_PACKAGES); } - private static final String[] TEST_RUNNER_PACKAGES = new String[] { + static final String[] TEST_RUNNER_PACKAGES = new String[] { // surefire test runner - "org.apache.maven.surefire.booter.", + "org\\.apache\\.maven\\.surefire\\.booter\\..*", // junit4 test runner - "com.carrotsearch.ant.tasks.junit4.", + "com\\.carrotsearch\\.ant\\.tasks\\.junit4\\.slave\\..*", // eclipse test runner - "org.eclipse.jdt.internal.junit.runner.", + "org\\.eclipse.jdt\\.internal\\.junit\\.runner\\..*", // intellij test runner - "com.intellij.rt.execution.junit." + "com\\.intellij\\.rt\\.execution\\.junit\\..*" }; // java.security.debug support @@ -203,6 +205,8 @@ public class SecureSM extends SecurityManager { /** * The "Uwe Schindler" algorithm. + * + * @param status the exit status */ protected void innerCheckExit(final int status) { AccessController.doPrivileged(new PrivilegedAction() { @@ -222,14 +226,12 @@ public class SecureSM extends SecurityManager { } if (exitMethodHit != null) { - if (packagesThatCanExit == null) { + if (classesThatCanExit == null) { break; } - for (String packageThatCanExit : packagesThatCanExit) { - if (className.startsWith(packageThatCanExit)) { - // this exit point is allowed, we return normally from closure: - return null; - } + if (classCanExit(className, classesThatCanExit)) { + // this exit point is allowed, we return normally from closure: + return null; } // anything else in stack trace is not allowed, break and throw SecurityException below: break; @@ -248,4 +250,13 @@ public class SecureSM extends SecurityManager { super.checkExit(status); } + static boolean classCanExit(final String className, final String[] classesThatCanExit) { + for (final String classThatCanExit : classesThatCanExit) { + if (className.matches(classThatCanExit)) { + return true; + } + } + return false; + } + } diff --git a/securesm/src/test/java/org/elasticsearch/TestSecureSM.java b/securesm/src/test/java/org/elasticsearch/TestSecureSM.java index 31c8d0ad4fb..99e376be847 100644 --- a/securesm/src/test/java/org/elasticsearch/TestSecureSM.java +++ b/securesm/src/test/java/org/elasticsearch/TestSecureSM.java @@ -55,6 +55,16 @@ public class TestSecureSM extends TestCase { fail("did not hit expected exception"); } catch (SecurityException expected) {} } + + @Test + public void testClassCanExit() { + assertTrue(SecureSM.classCanExit("org.apache.maven.surefire.booter.CommandReader", SecureSM.TEST_RUNNER_PACKAGES)); + assertTrue(SecureSM.classCanExit("com.carrotsearch.ant.tasks.junit4.slave.JvmExit", SecureSM.TEST_RUNNER_PACKAGES)); + assertTrue(SecureSM.classCanExit("org.eclipse.jdt.internal.junit.runner.RemoteTestRunner", SecureSM.TEST_RUNNER_PACKAGES)); + assertTrue(SecureSM.classCanExit("com.intellij.rt.execution.junit.JUnitStarter", SecureSM.TEST_RUNNER_PACKAGES)); + assertTrue(SecureSM.classCanExit("org.elasticsearch.Foo", new String[]{"org.elasticsearch.Foo"})); + assertFalse(SecureSM.classCanExit("org.elasticsearch.Foo", new String[]{"org.elasticsearch.Bar"})); + } @Test public void testCreateThread() throws Exception {