This is an automated email from the ASF dual-hosted git repository.

pkarwasz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit a3a3dab606b00a0ae1e3d9e5f5e179155936a13c
Author: Piotr P. Karwasz <[email protected]>
AuthorDate: Sun Aug 21 22:00:48 2022 +0200

    LOG4J2-3579 Calls ServiceLoader with caller's security context
    
    When running with a security manager, `ServiceLoaderUtil` will call
    `ServiceLoader` with the privileges of the caller.
    
    The conflict was resolved by merging the version from `log4j-api-java9`
    to `log4j-api`.
---
 .../logging/log4j/util/ServiceLoaderUtil.java      | 36 +++++++++++++++++-----
 1 file changed, 29 insertions(+), 7 deletions(-)

diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java 
b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
index 32a2790b62..7272e84dd2 100644
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
@@ -16,9 +16,13 @@
  */
 package org.apache.logging.log4j.util;
 
+import java.lang.invoke.CallSite;
+import java.lang.invoke.LambdaMetafactory;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.invoke.MethodType;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.HashSet;
 import java.util.Objects;
 import java.util.ServiceConfigurationError;
@@ -31,10 +35,7 @@ import org.apache.logging.log4j.status.StatusLogger;
 /**
  * Loads all valid instances of a service.
  */
-public class ServiceLoaderUtil {
-
-    private static final MethodType LOAD_CLASS_CLASSLOADER = 
MethodType.methodType(ServiceLoader.class, Class.class,
-            ClassLoader.class);
+public final class ServiceLoaderUtil {
 
     private ServiceLoaderUtil() {
     }
@@ -88,14 +89,35 @@ public class ServiceLoaderUtil {
     static <T> Stream<T> loadClassloaderServices(final Class<T> serviceType, 
final Lookup lookup,
             final ClassLoader classLoader, final boolean verbose) {
         try {
-            final MethodHandle handle = lookup.findStatic(ServiceLoader.class, 
"load", LOAD_CLASS_CLASSLOADER);
-            final ServiceLoader<T> serviceLoader = (ServiceLoader<T>) 
handle.invokeExact(serviceType, classLoader);
+            // Creates a lambda in the caller's domain that calls 
`ServiceLoader`
+            final MethodHandle loadHandle = 
lookup.findStatic(ServiceLoader.class, "load",
+                    MethodType.methodType(ServiceLoader.class, Class.class, 
ClassLoader.class));
+            final CallSite callSite = LambdaMetafactory.metafactory(lookup,
+                    "run",
+                    MethodType.methodType(PrivilegedAction.class, Class.class, 
ClassLoader.class),
+                    MethodType.methodType(Object.class),
+                    loadHandle,
+                    MethodType.methodType(ServiceLoader.class));
+            final PrivilegedAction<ServiceLoader<T>> action = 
(PrivilegedAction<ServiceLoader<T>>) callSite
+                    .getTarget()//
+                    .bindTo(serviceType)
+                    .bindTo(classLoader)
+                    .invoke();
+            final ServiceLoader<T> serviceLoader;
+            if (System.getSecurityManager() == null) {
+                serviceLoader = action.run();
+            } else {
+                final MethodHandle privilegedHandle = 
lookup.findStatic(AccessController.class, "doPrivileged",
+                        MethodType.methodType(Object.class, 
PrivilegedAction.class));
+                serviceLoader = (ServiceLoader<T>) 
privilegedHandle.invoke(action);
+            }
             return serviceLoader.stream().map(provider -> {
                 try {
                     return provider.get();
                 } catch (ServiceConfigurationError e) {
                     if (verbose) {
-                        StatusLogger.getLogger().warn("Unable to load service 
class for service {}", serviceType, e);
+                        StatusLogger.getLogger().warn("Unable to load service 
class for service {}",
+                                serviceType.getClass(), e);
                     }
                 }
                 return null;

Reply via email to