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;
