|
20 | 20 | import java.security.Permissions;
|
21 | 21 | import java.security.Policy;
|
22 | 22 | import java.security.ProtectionDomain;
|
| 23 | +import java.util.Arrays; |
23 | 24 | import java.util.Collections;
|
24 | 25 | import java.util.Map;
|
| 26 | +import java.util.Optional; |
25 | 27 | import java.util.function.Predicate;
|
26 | 28 |
|
27 | 29 | /** custom policy for union of static and dynamic permissions */
|
@@ -58,6 +60,25 @@ final class ESPolicy extends Policy {
|
58 | 60 | this.plugins = plugins;
|
59 | 61 | }
|
60 | 62 |
|
| 63 | + private static final Predicate<StackTraceElement> JDK_BOOT = f -> f.getClassLoaderName() == null; |
| 64 | + private static final Predicate<StackTraceElement> ES_BOOTSTRAP = f -> f.getClassName().startsWith("org.elasticsearch.bootstrap"); |
| 65 | + private static final Predicate<StackTraceElement> IS_LOG4J = f -> "org.apache.logging.log4j.util.LoaderUtil".equals(f.getClassName()) |
| 66 | + && "getClassLoaders".equals(f.getMethodName()); |
| 67 | + |
| 68 | + /** |
| 69 | + * Returns true if the top of the call stack has: |
| 70 | + * 1) Only frames belonging from the JDK's boot loader or org.elasticsearch.bootstrap, followed directly by |
| 71 | + * 2) org.apache.logging.log4j.util.LoaderUtil.getClassLoaders |
| 72 | + */ |
| 73 | + private static boolean isLoaderUtilGetClassLoaders() { |
| 74 | + Optional<StackTraceElement> frame = Arrays.stream(Thread.currentThread().getStackTrace()) |
| 75 | + .dropWhile(JDK_BOOT.or(ES_BOOTSTRAP)) |
| 76 | + .limit(1) |
| 77 | + .findFirst() |
| 78 | + .filter(IS_LOG4J); |
| 79 | + return frame.isPresent(); |
| 80 | + } |
| 81 | + |
61 | 82 | @Override
|
62 | 83 | @SuppressForbidden(reason = "fast equals check is desired")
|
63 | 84 | public boolean implies(ProtectionDomain domain, Permission permission) {
|
@@ -101,6 +122,10 @@ public boolean implies(ProtectionDomain domain, Permission permission) {
|
101 | 122 | return true;
|
102 | 123 | }
|
103 | 124 |
|
| 125 | + if (permission instanceof RuntimePermission && "getClassLoader".equals(permission.getName()) && isLoaderUtilGetClassLoaders()) { |
| 126 | + return true; |
| 127 | + } |
| 128 | + |
104 | 129 | // otherwise defer to template + dynamic file permissions
|
105 | 130 | return template.implies(domain, permission) || dynamic.implies(permission) || system.implies(domain, permission);
|
106 | 131 | }
|
|
0 commit comments