diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java index fa3cb607855..91a4d016a37 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java @@ -31,11 +31,13 @@ import java.security.PrivilegedAction; import java.util.List; import java.util.ArrayList; import java.util.Arrays; + import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyAccess; import sun.invoke.util.Wrapper; import sun.reflect.CallerSensitive; import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; import sun.security.util.SecurityConstants; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; @@ -578,14 +580,11 @@ public class MethodHandles { * refuses access * @throws NullPointerException if any argument is null */ - @CallerSensitive public MethodHandle findStatic(Class refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); - Class callerClass = Reflection.getCallerClass(); - checkSecurityManager(refc, method, callerClass); - return getDirectMethod(REF_invokeStatic, refc, method, - findBoundCallerClass(method, callerClass)); + checkSecurityManager(refc, method); + return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerClass(method)); } /** @@ -631,7 +630,6 @@ public class MethodHandles { * refuses access * @throws NullPointerException if any argument is null */ - @CallerSensitive public MethodHandle findVirtual(Class refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { if (refc == MethodHandle.class) { MethodHandle mh = findVirtualForMH(name, type); @@ -639,10 +637,8 @@ public class MethodHandles { } byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); MemberName method = resolveOrFail(refKind, refc, name, type); - Class callerClass = Reflection.getCallerClass(); - checkSecurityManager(refc, method, callerClass); - return getDirectMethod(refKind, refc, method, - findBoundCallerClass(method, callerClass)); + checkSecurityManager(refc, method); + return getDirectMethod(refKind, refc, method, findBoundCallerClass(method)); } private MethodHandle findVirtualForMH(String name, MethodType type) { // these names require special lookups because of the implicit MethodType argument @@ -679,11 +675,10 @@ public class MethodHandles { * refuses access * @throws NullPointerException if any argument is null */ - @CallerSensitive public MethodHandle findConstructor(Class refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { String name = ""; MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type); - checkSecurityManager(refc, ctor, Reflection.getCallerClass()); + checkSecurityManager(refc, ctor); return getDirectConstructor(refc, ctor); } @@ -721,16 +716,13 @@ public class MethodHandles { * refuses access * @throws NullPointerException if any argument is null */ - @CallerSensitive public MethodHandle findSpecial(Class refc, String name, MethodType type, Class specialCaller) throws NoSuchMethodException, IllegalAccessException { checkSpecialCaller(specialCaller); Lookup specialLookup = this.in(specialCaller); MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); - Class callerClass = Reflection.getCallerClass(); - checkSecurityManager(refc, method, callerClass); - return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, - findBoundCallerClass(method, callerClass)); + checkSecurityManager(refc, method); + return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, findBoundCallerClass(method)); } /** @@ -750,10 +742,9 @@ public class MethodHandles { * refuses access * @throws NullPointerException if any argument is null */ - @CallerSensitive public MethodHandle findGetter(Class refc, String name, Class type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_getField, refc, name, type); - checkSecurityManager(refc, field, Reflection.getCallerClass()); + checkSecurityManager(refc, field); return getDirectField(REF_getField, refc, field); } @@ -774,10 +765,9 @@ public class MethodHandles { * refuses access * @throws NullPointerException if any argument is null */ - @CallerSensitive public MethodHandle findSetter(Class refc, String name, Class type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_putField, refc, name, type); - checkSecurityManager(refc, field, Reflection.getCallerClass()); + checkSecurityManager(refc, field); return getDirectField(REF_putField, refc, field); } @@ -797,10 +787,9 @@ public class MethodHandles { * refuses access * @throws NullPointerException if any argument is null */ - @CallerSensitive public MethodHandle findStaticGetter(Class refc, String name, Class type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_getStatic, refc, name, type); - checkSecurityManager(refc, field, Reflection.getCallerClass()); + checkSecurityManager(refc, field); return getDirectField(REF_getStatic, refc, field); } @@ -820,10 +809,9 @@ public class MethodHandles { * refuses access * @throws NullPointerException if any argument is null */ - @CallerSensitive public MethodHandle findStaticSetter(Class refc, String name, Class type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_putStatic, refc, name, type); - checkSecurityManager(refc, field, Reflection.getCallerClass()); + checkSecurityManager(refc, field); return getDirectField(REF_putStatic, refc, field); } @@ -873,14 +861,11 @@ return mh1; * refuses access * @throws NullPointerException if any argument is null */ - @CallerSensitive public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { Class refc = receiver.getClass(); // may get NPE MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); - Class callerClass = Reflection.getCallerClass(); - checkSecurityManager(refc, method, callerClass); - MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, - findBoundCallerClass(method, callerClass)); + checkSecurityManager(refc, method); + MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method)); return mh.bindReceiver(receiver).setVarargs(method); } @@ -905,16 +890,14 @@ return mh1; * is set and {@code asVarargsCollector} fails * @throws NullPointerException if the argument is null */ - @CallerSensitive public MethodHandle unreflect(Method m) throws IllegalAccessException { MemberName method = new MemberName(m); byte refKind = method.getReferenceKind(); if (refKind == REF_invokeSpecial) refKind = REF_invokeVirtual; assert(method.isMethod()); - Class callerClass = findBoundCallerClass(method, Reflection.getCallerClass()); Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass); + return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method)); } /** @@ -938,15 +921,13 @@ return mh1; * is set and {@code asVarargsCollector} fails * @throws NullPointerException if any argument is null */ - @CallerSensitive public MethodHandle unreflectSpecial(Method m, Class specialCaller) throws IllegalAccessException { checkSpecialCaller(specialCaller); Lookup specialLookup = this.in(specialCaller); MemberName method = new MemberName(m, true); assert(method.isMethod()); - Class callerClass = findBoundCallerClass(method, Reflection.getCallerClass()); // ignore m.isAccessible: this is a new kind of access - return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass); + return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerClass(method)); } /** @@ -1047,21 +1028,25 @@ return mh1; /** * Find my trustable caller class if m is a caller sensitive method. * If this lookup object has private access, then the caller class is the lookupClass. - * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). - * This is the same caller class as is used by checkSecurityManager. + * Otherwise, if m is caller-sensitive, throw IllegalAccessException. */ - Class findBoundCallerClass(MemberName m, Class callerAtEntryPoint) { + Class findBoundCallerClass(MemberName m) throws IllegalAccessException { Class callerClass = null; if (MethodHandleNatives.isCallerSensitive(m)) { - // Do not refactor this to a more "logical" place, since it is stack walk magic. - // Note that this is the same expression as in Step 2 below in checkSecurityManager. - callerClass = ((allowedModes & PRIVATE) != 0 - ? lookupClass // for strong access modes, no extra check - : callerAtEntryPoint); + // Only full-power lookup is allowed to resolve caller-sensitive methods + if (isFullPowerLookup()) { + callerClass = lookupClass; + } else { + throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object"); + } } return callerClass; } + private boolean isFullPowerLookup() { + return (allowedModes & PRIVATE) != 0; + } + /** * Determine whether a security manager has an overridden * SecurityManager.checkMemberAccess method. @@ -1082,10 +1067,8 @@ return mh1; * Perform necessary access checks. * Determines a trustable caller class to compare with refc, the symbolic reference class. * If this lookup object has private access, then the caller class is the lookupClass. - * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). - * This function performs stack walk magic: do not refactor it. */ - void checkSecurityManager(Class refc, MemberName m, Class caller) { + void checkSecurityManager(Class refc, MemberName m) { SecurityManager smgr = System.getSecurityManager(); if (smgr == null) return; if (allowedModes == TRUSTED) return; @@ -1105,13 +1088,10 @@ return mh1; } // Step 2: - Class callerClass = ((allowedModes & PRIVATE) != 0 - ? lookupClass // for strong access modes, no extra check - : caller); - if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) || - (callerClass != lookupClass && - !VerifyAccess.classLoaderIsAncestor(callerClass, refc))) - smgr.checkPackageAccess(VerifyAccess.getPackageName(refc)); + if (!isFullPowerLookup() || + !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) { + ReflectUtil.checkPackageAccess(refc); + } // Step 3: if (m.isPublic()) return; @@ -1121,7 +1101,7 @@ return mh1; final int which = Member.DECLARED; final Class clazz = defc; if (!overridden) { - if (caller.getClassLoader() != clazz.getClassLoader()) { + if (!isFullPowerLookup()) { smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); } } else { @@ -1132,8 +1112,9 @@ return mh1; } // Step 4: - if (defc != refc) - smgr.checkPackageAccess(VerifyAccess.getPackageName(defc)); + if (defc != refc) { + ReflectUtil.checkPackageAccess(defc); + } } void checkMethod(byte refKind, Class refc, MemberName m) throws IllegalAccessException {