8344319: SM cleanup in jdk.dynalink module

Reviewed-by: attila
This commit is contained in:
Roger Riggs 2024-11-25 16:46:19 +00:00
parent 15ae8d02ee
commit 593a5898f9
13 changed files with 32 additions and 232 deletions

View File

@ -27,14 +27,10 @@ package jdk.dynalink;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import jdk.dynalink.internal.AccessControlContextFactory;
import static jdk.dynalink.internal.InternalTypeUtilities.canReferenceDirectly;
@ -201,21 +197,14 @@ final class BiClassValue<T> {
}
}
@SuppressWarnings("removal")
private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
AccessControlContextFactory.createAccessControlContext("getClassLoader");
@SuppressWarnings("removal")
private static RetentionDirection getRetentionDirection(Class<?> from, Class<?> to) {
return AccessController.doPrivileged((PrivilegedAction<RetentionDirection>) () -> {
final ClassLoader cl1 = from.getClassLoader();
final ClassLoader cl2 = to.getClassLoader();
if (canReferenceDirectly(cl1, cl2)) {
return RetentionDirection.FORWARD;
} else if (canReferenceDirectly(cl2, cl1)) {
return RetentionDirection.REVERSE;
}
return RetentionDirection.NEITHER;
}, GET_CLASS_LOADER_CONTEXT);
final ClassLoader cl1 = from.getClassLoader();
final ClassLoader cl2 = to.getClassLoader();
if (canReferenceDirectly(cl1, cl2)) {
return RetentionDirection.FORWARD;
} else if (canReferenceDirectly(cl2, cl1)) {
return RetentionDirection.REVERSE;
}
return RetentionDirection.NEITHER;
}
}

View File

@ -63,9 +63,6 @@ package jdk.dynalink;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -79,7 +76,6 @@ import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Supplier;
import jdk.dynalink.beans.BeansLinker;
import jdk.dynalink.internal.AccessControlContextFactory;
import jdk.dynalink.linker.GuardedInvocation;
import jdk.dynalink.linker.GuardedInvocationTransformer;
import jdk.dynalink.linker.GuardingDynamicLinker;
@ -108,10 +104,6 @@ import jdk.dynalink.linker.support.TypeUtilities;
* @since 9
*/
public final class DynamicLinkerFactory {
@SuppressWarnings("removal")
private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
AccessControlContextFactory.createAccessControlContext("getClassLoader");
/**
* Default value for {@link #setUnstableRelinkThreshold(int) unstable relink
* threshold}.
@ -430,17 +422,14 @@ public final class DynamicLinkerFactory {
private List<GuardingDynamicLinker> discoverAutoLoadLinkers() {
autoLoadingErrors = new LinkedList<>();
final ClassLoader effectiveClassLoader = classLoaderExplicitlySet ? classLoader : getThreadContextClassLoader();
final ClassLoader effectiveClassLoader =
classLoaderExplicitlySet ? classLoader : Thread.currentThread().getContextClassLoader();
final List<GuardingDynamicLinker> discovered = new LinkedList<>();
try {
@SuppressWarnings("removal")
final ServiceLoader<GuardingDynamicLinkerExporter> linkerLoader =
AccessController.doPrivileged((PrivilegedAction<ServiceLoader<GuardingDynamicLinkerExporter>>)()-> {
if (effectiveClassLoader == null) {
return ServiceLoader.loadInstalled(GuardingDynamicLinkerExporter.class);
}
return ServiceLoader.load(GuardingDynamicLinkerExporter.class, effectiveClassLoader);
});
(effectiveClassLoader == null)
? ServiceLoader.loadInstalled(GuardingDynamicLinkerExporter.class)
: ServiceLoader.load(GuardingDynamicLinkerExporter.class, effectiveClassLoader);
for(final Iterator<GuardingDynamicLinkerExporter> it = linkerLoader.iterator(); it.hasNext();) {
try {
@ -470,13 +459,6 @@ public final class DynamicLinkerFactory {
return discovered;
}
@SuppressWarnings("removal")
private static ClassLoader getThreadContextClassLoader() {
return AccessController.doPrivileged(
(PrivilegedAction<ClassLoader>) () -> Thread.currentThread().getContextClassLoader(),
GET_CLASS_LOADER_CONTEXT);
}
private static void addClasses(final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses,
final List<? extends GuardingDynamicLinker> linkers) {
for(final GuardingDynamicLinker linker: linkers) {

View File

@ -45,8 +45,6 @@ public class SecureLookupSupplier {
*/
public static final String GET_LOOKUP_PERMISSION_NAME = "dynalink.getLookup";
private static final RuntimePermission GET_LOOKUP_PERMISSION = new RuntimePermission(SecureLookupSupplier.GET_LOOKUP_PERMISSION_NAME);
private final MethodHandles.Lookup lookup;
/**
@ -63,11 +61,6 @@ public class SecureLookupSupplier {
* @return the lookup secured by this {@code SecureLookupSupplier}.
*/
public final Lookup getLookup() {
@SuppressWarnings("removal")
final SecurityManager sm = System.getSecurityManager();
if (sm != null && lookup != MethodHandles.publicLookup()) {
sm.checkPermission(GET_LOOKUP_PERMISSION);
}
return lookup;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -63,8 +63,6 @@ package jdk.dynalink.beans;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Method;
import java.lang.reflect.RecordComponent;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@ -86,20 +84,12 @@ class BeanIntrospector extends FacetIntrospector {
@Override Collection<Method> getRecordComponentGetters() {
if (clazz.isRecord()) {
try {
// Need to use doPrivileged as getRecordComponents is rather strict.
@SuppressWarnings("removal")
final RecordComponent[] rcs = AccessController.doPrivileged(
(PrivilegedAction<RecordComponent[]>) clazz::getRecordComponents);
return Arrays.stream(rcs)
.map(RecordComponent::getAccessor)
.map(membersLookup::getAccessibleMethod)
.filter(Objects::nonNull) // no accessible counterpart
.toList();
} catch (SecurityException e) {
// We couldn't execute getRecordComponents.
return List.of();
}
final RecordComponent[] rcs = clazz.getRecordComponents();
return Arrays.stream(rcs)
.map(RecordComponent::getAccessor)
.map(membersLookup::getAccessibleMethod)
.filter(Objects::nonNull) // no accessible counterpart
.toList();
} else {
return List.of();
}

View File

@ -67,12 +67,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.SecureLookupSupplier;
import jdk.dynalink.internal.AccessControlContextFactory;
import jdk.dynalink.linker.support.Lookup;
/**
@ -82,10 +78,6 @@ import jdk.dynalink.linker.support.Lookup;
* every request.
*/
class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
@SuppressWarnings("removal")
private static final AccessControlContext GET_LOOKUP_CONTEXT =
AccessControlContextFactory.createAccessControlContext(
SecureLookupSupplier.GET_LOOKUP_PERMISSION_NAME);
private final Executable target;
private final MethodType type;
@ -127,10 +119,7 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
@Override
MethodHandle getTarget(final CallSiteDescriptor desc) {
@SuppressWarnings("removal")
final MethodHandles.Lookup lookup = AccessController.doPrivileged(
(PrivilegedAction<MethodHandles.Lookup>)desc::getLookup,
GET_LOOKUP_CONTEXT);
final MethodHandles.Lookup lookup = desc.getLookup();
if(target instanceof Method) {
final MethodHandle mh = unreflect(lookup, (Method)target);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -61,25 +61,17 @@
package jdk.dynalink.beans;
import java.lang.reflect.Modifier;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import jdk.dynalink.internal.AccessControlContextFactory;
/**
* A utility class to check whether a given class is in a package with restricted access e.g. "sun.*" etc.
*/
class CheckRestrictedPackage {
@SuppressWarnings("removal")
private static final AccessControlContext NO_PERMISSIONS_CONTEXT =
AccessControlContextFactory.createAccessControlContext();
/**
* Returns true if the class is either not public, or it resides in a package with restricted access.
* @param clazz the class to test
* @return true if the class is either not public, or it resides in a package with restricted access.
*/
@SuppressWarnings("removal")
static boolean isRestrictedClass(final Class<?> clazz) {
if(!Modifier.isPublic(clazz.getModifiers())) {
// Non-public classes are always restricted
@ -97,21 +89,6 @@ class CheckRestrictedPackage {
// Classes in unexported packages of modules are always restricted
return true;
}
final SecurityManager sm = System.getSecurityManager();
if(sm == null) {
// No further restrictions if we don't have a security manager
return false;
}
// Do a package access check from within an access control context with no permissions
try {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
sm.checkPackageAccess(pkgName);
return null;
}, NO_PERMISSIONS_CONTEXT);
} catch(final SecurityException e) {
return true;
}
return false;
}
}

View File

@ -61,13 +61,10 @@
package jdk.dynalink.beans;
import java.lang.invoke.MethodHandle;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import jdk.dynalink.internal.AccessControlContextFactory;
import jdk.dynalink.internal.InternalTypeUtilities;
import jdk.dynalink.linker.LinkerServices;
import jdk.dynalink.linker.support.TypeUtilities;
@ -78,10 +75,6 @@ import jdk.dynalink.linker.support.TypeUtilities;
* JLS.
*/
final class ClassString {
@SuppressWarnings("removal")
private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
AccessControlContextFactory.createAccessControlContext("getClassLoader");
/**
* An anonymous inner class used solely to represent the "type" of null values for method applicability checking.
*/
@ -128,16 +121,13 @@ final class ClassString {
return "ClassString[" + Arrays.toString(classes) + "]";
}
@SuppressWarnings("removal")
boolean isVisibleFrom(final ClassLoader classLoader) {
return AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> {
for(final Class<?> clazz: classes) {
if(!InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader())) {
return false;
}
for(final Class<?> clazz: classes) {
if(!InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader())) {
return false;
}
return true;
}, GET_CLASS_LOADER_CONTEXT);
}
return true;
}
List<MethodHandle> getMaximallySpecifics(final List<MethodHandle> methods, final LinkerServices linkerServices, final boolean varArg) {

View File

@ -62,9 +62,6 @@ package jdk.dynalink.beans;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.Collator;
import java.util.ArrayList;
import java.util.IdentityHashMap;
@ -73,9 +70,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.SecureLookupSupplier;
import jdk.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest;
import jdk.dynalink.internal.AccessControlContextFactory;
import jdk.dynalink.internal.InternalTypeUtilities;
import jdk.dynalink.linker.LinkerServices;
@ -194,16 +189,8 @@ class OverloadedDynamicMethod extends DynamicMethod {
}
}
@SuppressWarnings("removal")
private static final AccessControlContext GET_CALL_SITE_CLASS_LOADER_CONTEXT =
AccessControlContextFactory.createAccessControlContext(
"getClassLoader", SecureLookupSupplier.GET_LOOKUP_PERMISSION_NAME);
@SuppressWarnings("removal")
private static ClassLoader getCallSiteClassLoader(final CallSiteDescriptor callSiteDescriptor) {
return AccessController.doPrivileged(
(PrivilegedAction<ClassLoader>) () -> callSiteDescriptor.getLookup().lookupClass().getClassLoader(),
GET_CALL_SITE_CLASS_LOADER_CONTEXT);
return callSiteDescriptor.getLookup().lookupClass().getClassLoader();
}
@Override

View File

@ -1,80 +0,0 @@
/*
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.dynalink.internal;
import java.security.AccessControlContext;
import java.security.Permission;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.util.stream.Stream;
/**
* Utility class for creating permission-restricting {@link AccessControlContext}s.
*/
public final class AccessControlContextFactory {
private AccessControlContextFactory () {
}
/**
* Creates an access control context with no permissions.
* @return an access control context with no permissions.
*/
@SuppressWarnings("removal")
public static AccessControlContext createAccessControlContext() {
return createAccessControlContext(new Permission[0]);
}
/**
* Creates an access control context limited to only the specified permissions.
* @param permissions the permissions for the newly created access control context.
* @return a new access control context limited to only the specified permissions.
*/
@SuppressWarnings("removal")
public static AccessControlContext createAccessControlContext(final Permission... permissions) {
final Permissions perms = new Permissions();
for(final Permission permission: permissions) {
perms.add(permission);
}
return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
}
/**
* Creates an access control context limited to only the {@link RuntimePermission}s
* of the given names.
* @param runtimePermissionNames the names of runtime permissions for the
* newly created access control context.
* @return a new access control context limited to only the runtime
* permissions with the specified names.
*/
@SuppressWarnings("removal")
public static AccessControlContext createAccessControlContext(final String... runtimePermissionNames) {
return createAccessControlContext(makeRuntimePermissions(runtimePermissionNames));
}
private static Permission[] makeRuntimePermissions(final String... runtimePermissionNames) {
return Stream.of(runtimePermissionNames).map(RuntimePermission::new).toArray(Permission[]::new);
}
}

View File

@ -63,9 +63,6 @@ public class InternalTypeUtilities {
* @param referredLoader the referred class loader
* @return true if it is safe to strongly reference the class from referred
* in referred.
* @throws SecurityException if the caller does not have the
* {@code RuntimePermission("getClassLoader")} permission and the method
* needs to traverse the parent class loader chain.
*/
public static boolean canReferenceDirectly(final ClassLoader referrerLoader, final ClassLoader referredLoader) {
if(referredLoader == null) {

View File

@ -52,16 +52,9 @@ public abstract class GuardingDynamicLinkerExporter implements Supplier<List<Gua
*/
public static final String AUTOLOAD_PERMISSION_NAME = "dynalink.exportLinkersAutomatically";
private static final Permission AUTOLOAD_PERMISSION = new RuntimePermission(AUTOLOAD_PERMISSION_NAME);
/**
* Creates a new linker exporter.
*/
protected GuardingDynamicLinkerExporter() {
@SuppressWarnings("removal")
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(AUTOLOAD_PERMISSION);
}
}
}

View File

@ -115,11 +115,7 @@ public interface GuardingTypeConverterFactory {
* it will return the public lookup. A typical case where the lookup might
* be needed is when the converter creates a Java adapter class on the fly
* (e.g. to convert some object from the dynamic language into a Java
* interface for interoperability). Invoking the {@link Supplier#get()}
* method on the passed supplier will be subject to the same security checks
* as {@link SecureLookupSupplier#getLookup()}. An implementation should avoid
* retrieving the lookup if it is not needed so as to avoid the expense of
* {@code AccessController.doPrivileged} call.
* interface for interoperability).
* @return a guarded invocation that can take an object (if it passes guard)
* and return another object that is its representation coerced into the
* target type. In case the factory is certain it is unable to handle a

View File

@ -215,10 +215,7 @@ public interface LinkerServices {
* operation to the context of some caller class, consider performing it
* within an invocation of this method and passing a full-strength lookup
* for that class, as it will associate that lookup with the current thread
* for the duration of the operation. Note that since you are passing a
* {@link SecureLookupSupplier}, any invoked type converter factories will
* still need to hold the necessary runtime permission to be able to get the
* lookup should they need it.
* for the duration of the operation.
* @param <T> the type of the return value provided by the passed-in supplier.
* @param operation the operation to execute in context of the specified lookup.
* @param lookupSupplier secure supplier of the lookup