mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
8344011: Remove usage of security manager from Class and reflective APIs
Reviewed-by: liach, yzheng, rriggs
This commit is contained in:
parent
c977ef7b45
commit
abacece826
26 changed files with 163 additions and 1251 deletions
|
@ -311,8 +311,6 @@ public class VerifyAccess {
|
|||
// will use the result cached in the JVM system dictionary. Note that the JVM system dictionary
|
||||
// will record the first successful result. Unsuccessful results are not stored.
|
||||
//
|
||||
// We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary
|
||||
// class loader about the binding of the proposed name (type.getName()).
|
||||
// The looked up type ("res") is compared for equality against the proposed
|
||||
// type ("type") and then is discarded. Thus, the worst that can happen to
|
||||
// the "child" class loader is that it is bothered to load and report a class
|
||||
|
@ -320,17 +318,12 @@ public class VerifyAccess {
|
|||
// memoization. And the caller never gets to look at the alternate type binding
|
||||
// ("res"), whether it exists or not.
|
||||
final String name = type.getName();
|
||||
@SuppressWarnings("removal")
|
||||
Class<?> res = java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<>() {
|
||||
public Class<?> run() {
|
||||
try {
|
||||
return Class.forName(name, false, refcLoader);
|
||||
} catch (ClassNotFoundException | LinkageError e) {
|
||||
return null; // Assume the class is not found
|
||||
}
|
||||
}
|
||||
});
|
||||
Class<?> res = null;
|
||||
try {
|
||||
res = Class.forName(name, false, refcLoader);
|
||||
} catch (ClassNotFoundException | LinkageError e) {
|
||||
// Assume the class is not found
|
||||
}
|
||||
return (type == res);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
|
@ -23,7 +23,6 @@
|
|||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package sun.reflect.misc;
|
||||
|
||||
import java.lang.reflect.Member;
|
||||
|
@ -31,16 +30,13 @@ import java.lang.reflect.Method;
|
|||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import jdk.internal.reflect.Reflection;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
public final class ReflectUtil {
|
||||
|
||||
private ReflectUtil() {
|
||||
}
|
||||
|
||||
public static Class<?> forName(String name)
|
||||
throws ClassNotFoundException {
|
||||
checkPackageAccess(name);
|
||||
public static Class<?> forName(String name) throws ClassNotFoundException {
|
||||
return Class.forName(name);
|
||||
}
|
||||
|
||||
|
@ -73,182 +69,48 @@ public final class ReflectUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Does a conservative approximation of member access check. Use this if
|
||||
* you don't have an actual 'userland' caller Class/ClassLoader available.
|
||||
* This might be more restrictive than a precise member access check where
|
||||
* you have a caller, but should never allow a member access that is
|
||||
* forbidden.
|
||||
*
|
||||
* @param m the {@code Member} about to be accessed
|
||||
* Does nothing.
|
||||
*/
|
||||
public static void conservativeCheckMemberAccess(Member m) throws SecurityException{
|
||||
@SuppressWarnings("removal")
|
||||
final SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null)
|
||||
return;
|
||||
|
||||
// Check for package access on the declaring class.
|
||||
//
|
||||
// In addition, unless the member and the declaring class are both
|
||||
// public check for access declared member permissions.
|
||||
//
|
||||
// This is done regardless of ClassLoader relations between the {@code
|
||||
// Member m} and any potential caller.
|
||||
|
||||
final Class<?> declaringClass = m.getDeclaringClass();
|
||||
|
||||
privateCheckPackageAccess(sm, declaringClass);
|
||||
|
||||
if (Modifier.isPublic(m.getModifiers()) &&
|
||||
Modifier.isPublic(declaringClass.getModifiers()))
|
||||
return;
|
||||
|
||||
// Check for declared member access.
|
||||
sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
|
||||
public static void conservativeCheckMemberAccess(Member m) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks package access on the given class.
|
||||
*
|
||||
* If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements
|
||||
* a non-public interface (i.e. may be in a non-restricted package),
|
||||
* also check the package access on the proxy interfaces.
|
||||
* Does nothing.
|
||||
*/
|
||||
public static void checkPackageAccess(Class<?> clazz) {
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
if (s != null) {
|
||||
privateCheckPackageAccess(s, clazz);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: should only be called if a SecurityManager is installed
|
||||
*/
|
||||
private static void privateCheckPackageAccess(@SuppressWarnings("removal") SecurityManager s, Class<?> clazz) {
|
||||
String pkg = clazz.getPackageName();
|
||||
if (!pkg.isEmpty()) {
|
||||
s.checkPackageAccess(pkg);
|
||||
}
|
||||
|
||||
if (isNonPublicProxyClass(clazz)) {
|
||||
privateCheckProxyPackageAccess(s, clazz);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks package access on the given classname.
|
||||
* This method is typically called when the Class instance is not
|
||||
* available and the caller attempts to load a class on behalf
|
||||
* the true caller (application).
|
||||
* Does nothing
|
||||
*/
|
||||
public static void checkPackageAccess(String name) {
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
if (s != null) {
|
||||
String cname = name.replace('/', '.');
|
||||
if (cname.startsWith("[")) {
|
||||
int b = cname.lastIndexOf('[') + 2;
|
||||
if (b > 1 && b < cname.length()) {
|
||||
cname = cname.substring(b);
|
||||
}
|
||||
}
|
||||
int i = cname.lastIndexOf('.');
|
||||
if (i != -1) {
|
||||
s.checkPackageAccess(cname.substring(0, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true.
|
||||
*/
|
||||
public static boolean isPackageAccessible(Class<?> clazz) {
|
||||
try {
|
||||
checkPackageAccess(clazz);
|
||||
} catch (SecurityException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true if p is an ancestor of cl i.e. class loader 'p' can
|
||||
// be found in the cl's delegation chain
|
||||
private static boolean isAncestor(ClassLoader p, ClassLoader cl) {
|
||||
ClassLoader acl = cl;
|
||||
do {
|
||||
acl = acl.getParent();
|
||||
if (p == acl) {
|
||||
return true;
|
||||
}
|
||||
} while (acl != null);
|
||||
/**
|
||||
* Returns false.
|
||||
*/
|
||||
public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if package access check is needed for reflective
|
||||
* access from a class loader 'from' to classes or members in
|
||||
* a class defined by class loader 'to'. This method returns true
|
||||
* if 'from' is not the same as or an ancestor of 'to'. All code
|
||||
* in a system domain are granted with all permission and so this
|
||||
* method returns false if 'from' class loader is a class loader
|
||||
* loading system classes. On the other hand, if a class loader
|
||||
* attempts to access system domain classes, it requires package
|
||||
* access check and this method will return true.
|
||||
*/
|
||||
public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) {
|
||||
if (from == null || from == to)
|
||||
return false;
|
||||
|
||||
if (to == null)
|
||||
return true;
|
||||
|
||||
return !isAncestor(from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check package access on the proxy interfaces that the given proxy class
|
||||
* implements.
|
||||
*
|
||||
* @param clazz Proxy class object
|
||||
* Does nothing
|
||||
*/
|
||||
public static void checkProxyPackageAccess(Class<?> clazz) {
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
if (s != null) {
|
||||
privateCheckProxyPackageAccess(s, clazz);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: should only be called if a SecurityManager is installed
|
||||
*/
|
||||
private static void privateCheckProxyPackageAccess(@SuppressWarnings("removal") SecurityManager s, Class<?> clazz) {
|
||||
// check proxy interfaces if the given class is a proxy class
|
||||
if (Proxy.isProxyClass(clazz)) {
|
||||
for (Class<?> intf : clazz.getInterfaces()) {
|
||||
privateCheckPackageAccess(s, intf);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Access check on the interfaces that a proxy class implements and throw
|
||||
* {@code SecurityException} if it accesses a restricted package from
|
||||
* the caller's class loader.
|
||||
*
|
||||
* @param ccl the caller's class loader
|
||||
* @param interfaces the list of interfaces that a proxy class implements
|
||||
* Does nothing.
|
||||
*/
|
||||
public static void checkProxyPackageAccess(ClassLoader ccl,
|
||||
Class<?>... interfaces)
|
||||
{
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
for (Class<?> intf : interfaces) {
|
||||
ClassLoader cl = intf.getClassLoader();
|
||||
if (needsPackageAccessCheck(ccl, cl)) {
|
||||
privateCheckPackageAccess(sm, intf);
|
||||
}
|
||||
}
|
||||
}
|
||||
Class<?>... interfaces) {
|
||||
}
|
||||
|
||||
// Note that bytecode instrumentation tools may exclude 'sun.*'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue