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> {
