Mercurial > hg > release > icedtea8-forest-3.0 > jdk
changeset 11672:e917bc6b356b icedtea-3.0.0pre10
Merge jdk8u77-b03
author | andrew |
---|---|
date | Tue, 29 Mar 2016 04:19:56 +0100 |
parents | ce68536198a5 (current diff) c44179bce874 (diff) |
children | 8957aff58901 |
files | .hgtags src/share/classes/java/lang/ClassLoader.java src/share/classes/java/lang/invoke/MemberName.java src/share/classes/java/lang/invoke/MethodHandleNatives.java src/share/classes/sun/invoke/util/VerifyAccess.java |
diffstat | 5 files changed, 92 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Tue Feb 23 02:34:54 2016 +0000 +++ b/.hgtags Tue Mar 29 04:19:56 2016 +0100 @@ -550,3 +550,13 @@ d841d3fdae44f120883dab0a3a809a054cd0274b jdk8u72-b13 f6d24d424cd2af4d2612f7737d3d9a25f58b882d jdk8u72-b14 dfad9b612327322033896d9bdfab58ae12ccac62 icedtea-3.0.0pre09 +f3e86cc607260bae368b52d88d7bc8883ee767e3 jdk8u72-b15 +892eb9ab179650b89b7bab6bc42f079391c98624 jdk8u73-b00 +9b77d3ca0d66a117c3cc0e0a74b8059545b22f0e jdk8u73-b01 +2ab13901d6f14bab0dcf4823d5e378a421fba7e2 jdk8u73-b02 +9a843dc6f959f62c61014a3a71ec9aa329f1daf1 jdk8u74-b00 +e829ab80dfd828803aa8837411900faeaa1254a5 jdk8u74-b01 +32c49f4a16599e376e4e46bb33c7bcc486e52ff3 jdk8u74-b02 +02e1209648050922a5a9f2789d9d359795f6f834 jdk8u77-b00 +f08584a0fde9344b0aa4766984266ca68b9a5018 jdk8u77-b01 +1a3e81c05703bb36def80a57681e1692c866f621 jdk8u77-b02
--- a/src/share/classes/java/lang/ClassLoader.java Tue Feb 23 02:34:54 2016 +0000 +++ b/src/share/classes/java/lang/ClassLoader.java Tue Mar 29 04:19:56 2016 +0100 @@ -653,6 +653,9 @@ if (!checkName(name)) throw new NoClassDefFoundError("IllegalName: " + name); + // Note: Checking logic in java.lang.invoke.MemberName.checkForTypeAlias + // relies on the fact that spoofing is impossible if a class has a name + // of the form "java.*" if ((name != null) && name.startsWith("java.")) { throw new SecurityException ("Prohibited package name: " +
--- a/src/share/classes/java/lang/invoke/MemberName.java Tue Feb 23 02:34:54 2016 +0000 +++ b/src/share/classes/java/lang/invoke/MemberName.java Tue Mar 29 04:19:56 2016 +0100 @@ -783,7 +783,7 @@ assert(isResolved() == isResolved); } - void checkForTypeAlias() { + void checkForTypeAlias(Class<?> refc) { if (isInvocable()) { MethodType type; if (this.type instanceof MethodType) @@ -791,16 +791,16 @@ else this.type = type = getMethodType(); if (type.erase() == type) return; - if (VerifyAccess.isTypeVisible(type, clazz)) return; - throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz); + if (VerifyAccess.isTypeVisible(type, refc)) return; + throw new LinkageError("bad method type alias: "+type+" not visible from "+refc); } else { Class<?> type; if (this.type instanceof Class<?>) type = (Class<?>) this.type; else this.type = type = getFieldType(); - if (VerifyAccess.isTypeVisible(type, clazz)) return; - throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz); + if (VerifyAccess.isTypeVisible(type, refc)) return; + throw new LinkageError("bad field type alias: "+type+" not visible from "+refc); } } @@ -959,10 +959,25 @@ MemberName m = ref.clone(); // JVM will side-effect the ref assert(refKind == m.getReferenceKind()); try { + // There are 4 entities in play here: + // * LC: lookupClass + // * REFC: symbolic reference class (MN.clazz before resolution); + // * DEFC: resolved method holder (MN.clazz after resolution); + // * PTYPES: parameter types (MN.type) + // + // What we care about when resolving a MemberName is consistency between DEFC and PTYPES. + // We do type alias (TA) checks on DEFC to ensure that. DEFC is not known until the JVM + // finishes the resolution, so do TA checks right after MHN.resolve() is over. + // + // All parameters passed by a caller are checked against MH type (PTYPES) on every invocation, + // so it is safe to call a MH from any context. + // + // REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't + // participate in method selection. m = MethodHandleNatives.resolve(m, lookupClass); - m.checkForTypeAlias(); + m.checkForTypeAlias(m.getDeclaringClass()); m.resolution = null; - } catch (LinkageError ex) { + } catch (ClassNotFoundException | LinkageError ex) { // JVM reports that the "bytecode behavior" would get an error assert(!m.isResolved()); m.resolution = ex;
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java Tue Feb 23 02:34:54 2016 +0000 +++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java Tue Mar 29 04:19:56 2016 +0100 @@ -45,7 +45,7 @@ static native void init(MemberName self, Object ref); static native void expand(MemberName self); - static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError; + static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError, ClassNotFoundException; static native int getMembers(Class<?> defc, String matchName, String matchSig, int matchFlags, Class<?> caller, int skip, MemberName[] results);
--- a/src/share/classes/sun/invoke/util/VerifyAccess.java Tue Feb 23 02:34:54 2016 +0000 +++ b/src/share/classes/sun/invoke/util/VerifyAccess.java Tue Mar 29 04:19:56 2016 +0100 @@ -185,22 +185,66 @@ * @param refc the class attempting to make the reference */ public static boolean isTypeVisible(Class<?> type, Class<?> refc) { - if (type == refc) return true; // easy check + if (type == refc) { + return true; // easy check + } while (type.isArray()) type = type.getComponentType(); - if (type.isPrimitive() || type == Object.class) return true; - ClassLoader parent = type.getClassLoader(); - if (parent == null) return true; - ClassLoader child = refc.getClassLoader(); - if (child == null) return false; - if (parent == child || loadersAreRelated(parent, child, true)) + if (type.isPrimitive() || type == Object.class) { return true; - // Do it the hard way: Look up the type name from the refc loader. - try { - Class<?> res = child.loadClass(type.getName()); - return (type == res); - } catch (ClassNotFoundException ex) { + } + ClassLoader typeLoader = type.getClassLoader(); + ClassLoader refcLoader = refc.getClassLoader(); + if (typeLoader == refcLoader) { + return true; + } + if (refcLoader == null && typeLoader != null) { return false; } + if (typeLoader == null && type.getName().startsWith("java.")) { + // Note: The API for actually loading classes, ClassLoader.defineClass, + // guarantees that classes with names beginning "java." cannot be aliased, + // because class loaders cannot load them directly. + return true; + } + + // Do it the hard way: Look up the type name from the refc loader. + // + // Force the refc loader to report and commit to a particular binding for this type name (type.getName()). + // + // In principle, this query might force the loader to load some unrelated class, + // which would cause this query to fail (and the original caller to give up). + // This would be wasted effort, but it is expected to be very rare, occurring + // only when an attacker is attempting to create a type alias. + // In the normal case, one class loader will simply delegate to the other, + // and the same type will be visible through both, with no extra loading. + // + // It is important to go through Class.forName instead of ClassLoader.loadClass + // because Class.forName goes through the JVM system dictionary, which records + // the class lookup once for all. This means that even if a not-well-behaved class loader + // would "change its mind" about the meaning of the name, the Class.forName request + // 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 + // that differs from "type"; this happens once due to JVM system dictionary + // memoization. And the caller never gets to look at the alternate type binding + // ("res"), whether it exists or not. + final String name = type.getName(); + Class<?> res = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction<Class>() { + public Class<?> run() { + try { + return Class.forName(name, false, refcLoader); + } catch (ClassNotFoundException | LinkageError e) { + return null; // Assume the class is not found + } + } + }); + return (type == res); } /**