Skip to content

Commit

Permalink
[7.16] Tolerate unprivileged log4j getClassLoaders calls (#81903) (#8…
Browse files Browse the repository at this point in the history
…1923)

Backport of

Tolerate unprivileged log4j getClassLoaders calls Tolerate unprivileged log4j getClassLoaders calls #81840
  • Loading branch information
pgomulka committed Dec 20, 2021
1 parent 3768a92 commit a1b144d
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions server/src/main/java/org/elasticsearch/bootstrap/ESPolicy.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import java.security.Permissions;
import java.security.Policy;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;

/** custom policy for union of static and dynamic permissions */
Expand Down Expand Up @@ -58,6 +60,26 @@ final class ESPolicy extends Policy {
this.plugins = plugins;
}

private static final Predicate<StackTraceElement> JDK_BOOT = f -> f.getClassName().startsWith("java.lang.")
|| f.getClassName().startsWith("java.security.");
private static final Predicate<StackTraceElement> ES_BOOTSTRAP = f -> f.getClassName().startsWith("org.elasticsearch.bootstrap");
private static final Predicate<StackTraceElement> IS_LOG4J = f -> "org.apache.logging.log4j.util.LoaderUtil".equals(f.getClassName())
&& "getClassLoaders".equals(f.getMethodName());

/**
* Returns true if the top of the call stack has:
* 1) Only frames belonging from the JDK's boot loader or org.elasticsearch.bootstrap, followed directly by
* 2) org.apache.logging.log4j.util.LoaderUtil.getClassLoaders
*/
private static boolean isLoaderUtilGetClassLoaders() {
Optional<StackTraceElement> frame = Arrays.stream(Thread.currentThread().getStackTrace())
.filter(JDK_BOOT.or(ES_BOOTSTRAP).negate())
.limit(1)
.findFirst()
.filter(IS_LOG4J);
return frame.isPresent();
}

@Override
@SuppressForbidden(reason = "fast equals check is desired")
public boolean implies(ProtectionDomain domain, Permission permission) {
Expand Down Expand Up @@ -101,6 +123,10 @@ public boolean implies(ProtectionDomain domain, Permission permission) {
return true;
}

if (permission instanceof RuntimePermission && "getClassLoader".equals(permission.getName()) && isLoaderUtilGetClassLoaders()) {
return true;
}

// otherwise defer to template + dynamic file permissions
return template.implies(domain, permission) || dynamic.implies(permission) || system.implies(domain, permission);
}
Expand Down

0 comments on commit a1b144d

Please sign in to comment.