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

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

commit 880acdfdb0b3c13c73c9ab3375924e238814f948
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.
---
 .../logging/log4j/util/ServiceLoaderUtil.java      | 32 ++++++++++++++++++----
 .../logging/log4j/util/ServiceLoaderUtil.java      | 32 ++++++++++++++++++----
 2 files changed, 52 insertions(+), 12 deletions(-)

diff --git 
a/log4j-api-java9/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
 
b/log4j-api-java9/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
index 9450e539a8..10b8cd547d 100644
--- 
a/log4j-api-java9/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
+++ 
b/log4j-api-java9/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
@@ -17,10 +17,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.util.Arrays;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.HashSet;
 import java.util.Objects;
 import java.util.ServiceConfigurationError;
@@ -32,9 +35,6 @@ import org.apache.logging.log4j.status.StatusLogger;
 
 public final class ServiceLoaderUtil {
 
-    private static final MethodType LOAD_CLASS_CLASSLOADER = 
MethodType.methodType(ServiceLoader.class, Class.class,
-            ClassLoader.class);
-
     private ServiceLoaderUtil() {
     }
 
@@ -87,8 +87,28 @@ public final 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();
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 ab2ddd3934..0230bf403b 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
@@ -17,9 +17,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.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -39,9 +43,6 @@ import org.apache.logging.log4j.status.StatusLogger;
  */
 public final class ServiceLoaderUtil {
 
-    private static final MethodType LOAD_CLASS_CLASSLOADER = 
MethodType.methodType(ServiceLoader.class, Class.class,
-            ClassLoader.class);
-
     private ServiceLoaderUtil() {
     }
 
@@ -102,8 +103,28 @@ public final class ServiceLoaderUtil {
     static <T> Iterable<T> callServiceLoader(Lookup lookup, Class<T> 
serviceType, ClassLoader classLoader,
             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;
         } catch (Throwable e) {
             if (verbose) {
@@ -111,7 +132,6 @@ public final class ServiceLoaderUtil {
             }
         }
         return Collections.emptyList();
-
     }
 
     private static class ServiceLoaderSpliterator<S> implements Spliterator<S> 
{

Reply via email to