Fix classes that can exit
In a previous change, we locked down the classes that can exit by specifying explicit classes rather than packages than can exit. Alas, there was a bug in the sense that the class that we exit from in the case of an uncaught exception is not ElasticsearchUncaughtExceptionHandler but rather an anonymous nested class of ElasticsearchUncaughtExceptionHandler. To address this, we replace this anonymous class with a bonafide nested class ElasticsearchUncaughtExceptionHandler$PrivilegedHaltAction. Note that if we try to get this class name we have a $ in the middle of the string which is a special regular expression character; as such, we have to escape it. Relates #27518
This commit is contained in:
parent
e0e1a92d36
commit
0b6448726c
|
@ -65,12 +65,10 @@ class ElasticsearchUncaughtExceptionHandler implements Thread.UncaughtExceptionH
|
|||
}
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
static boolean isFatalUncaught(Throwable e) {
|
||||
return e instanceof Error;
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
void onFatalUncaught(final String threadName, final Throwable t) {
|
||||
final Logger logger = Loggers.getLogger(ElasticsearchUncaughtExceptionHandler.class, loggingPrefixSupplier.get());
|
||||
logger.error(
|
||||
|
@ -78,24 +76,32 @@ class ElasticsearchUncaughtExceptionHandler implements Thread.UncaughtExceptionH
|
|||
() -> new ParameterizedMessage("fatal error in thread [{}], exiting", threadName), t);
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
void onNonFatalUncaught(final String threadName, final Throwable t) {
|
||||
final Logger logger = Loggers.getLogger(ElasticsearchUncaughtExceptionHandler.class, loggingPrefixSupplier.get());
|
||||
logger.warn((org.apache.logging.log4j.util.Supplier<?>)
|
||||
() -> new ParameterizedMessage("uncaught exception in thread [{}]", threadName), t);
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
void halt(int status) {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
@SuppressForbidden(reason = "halt")
|
||||
@Override
|
||||
public Void run() {
|
||||
// we halt to prevent shutdown hooks from running
|
||||
Runtime.getRuntime().halt(status);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
AccessController.doPrivileged(new PrivilegedHaltAction(status));
|
||||
}
|
||||
|
||||
static class PrivilegedHaltAction implements PrivilegedAction<Void> {
|
||||
|
||||
private final int status;
|
||||
|
||||
private PrivilegedHaltAction(final int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@SuppressForbidden(reason = "halt")
|
||||
@Override
|
||||
public Void run() {
|
||||
// we halt to prevent shutdown hooks from running
|
||||
Runtime.getRuntime().halt(status);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -119,7 +119,11 @@ final class Security {
|
|||
Policy.setPolicy(new ESPolicy(createPermissions(environment), getPluginPermissions(environment), filterBadDefaults));
|
||||
|
||||
// enable security manager
|
||||
final String[] classesThatCanExit = new String[]{ElasticsearchUncaughtExceptionHandler.class.getName(), Command.class.getName()};
|
||||
final String[] classesThatCanExit =
|
||||
new String[]{
|
||||
// SecureSM matches class names as regular expressions so we escape the $ that arises from the nested class name
|
||||
ElasticsearchUncaughtExceptionHandler.PrivilegedHaltAction.class.getName().replace("$", "\\$"),
|
||||
Command.class.getName()};
|
||||
System.setSecurityManager(new SecureSM(classesThatCanExit));
|
||||
|
||||
// do some basic tests
|
||||
|
|
Loading…
Reference in New Issue