< prev index next >

src/java.base/share/classes/sun/invoke/util/VerifyAccess.java

Print this page

 88      * @param defc the class in which the proposed member is actually defined
 89      * @param mods modifier flags for the proposed member
 90      * @param lookupClass the class for which the access check is being made
 91      * @param prevLookupClass the class for which the access check is being made
 92      * @param allowedModes allowed modes
 93      * @return true iff the accessing class can access such a member
 94      */
 95     public static boolean isMemberAccessible(Class<?> refc,  // symbolic ref class
 96                                              Class<?> defc,  // actual def class
 97                                              int      mods,  // actual member mods
 98                                              Class<?> lookupClass,
 99                                              Class<?> prevLookupClass,
100                                              int      allowedModes) {
101         if (allowedModes == 0)  return false;
102         assert((allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED|UNCONDITIONAL_ALLOWED|ORIGINAL_ALLOWED)) == 0);
103         // The symbolic reference class (refc) must always be fully verified.
104         if (!isClassAccessible(refc, lookupClass, prevLookupClass, allowedModes)) {
105             return false;
106         }
107         // Usually refc and defc are the same, but verify defc also in case they differ.
108         if (defc == lookupClass  &&
109             (allowedModes & PRIVATE) != 0)
110             return true;        // easy check; all self-access is OK with a private lookup
111 
112         switch (mods & ALL_ACCESS_MODES) {
113         case PUBLIC:
114             assert (allowedModes & PUBLIC) != 0 || (allowedModes & UNCONDITIONAL_ALLOWED) != 0;
115             return true;  // already checked above
116         case PROTECTED:
117             assert !defc.isInterface(); // protected members aren't allowed in interfaces
118             if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
119                 isSamePackage(defc, lookupClass))
120                 return true;
121             if ((allowedModes & PROTECTED) == 0)
122                 return false;
123             // Protected members are accessible by subclasses, which does not include interfaces.
124             // Interfaces are types, not classes. They should not have access to
125             // protected members in j.l.Object, even though it is their superclass.
126             if ((mods & STATIC) != 0 &&
127                 !isRelatedClass(refc, lookupClass))
128                 return false;
129             if ((allowedModes & PROTECTED) != 0 &&
130                 isSubClass(lookupClass, defc))
131                 return true;
132             return false;
133         case PACKAGE_ONLY:  // That is, zero.  Unmarked member is package-only access.
134             assert !defc.isInterface(); // package-private members aren't allowed in interfaces
135             return ((allowedModes & PACKAGE_ALLOWED) != 0 &&
136                     isSamePackage(defc, lookupClass));
137         case PRIVATE:
138             // Rules for privates follows access rules for nestmates.
139             boolean canAccess = ((allowedModes & PRIVATE) != 0 &&
140                                  Reflection.areNestMates(defc, lookupClass));
141             // for private methods the selected method equals the
142             // resolved method - so refc == defc
143             assert (canAccess && refc == defc) || !canAccess;
144             return canAccess;
145         default:
146             throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
147         }
148     }
149 
150     static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
151         return (refc == lookupClass ||
152                 isSubClass(refc, lookupClass) ||
153                 isSubClass(lookupClass, refc));
154     }
155 
156     static boolean isSubClass(Class<?> lookupClass, Class<?> defc) {
157         return defc.isAssignableFrom(lookupClass) &&
158                !lookupClass.isInterface(); // interfaces are types, not classes.
159     }
160 
161     static int getClassModifiers(Class<?> c) {
162         // This would return the mask stored by javac for the source-level modifiers.
163         //   return c.getModifiers();
164         // But what we need for JVM access checks are the actual bits from the class header.
165         // ...But arrays and primitives are synthesized with their own odd flags:
166         if (c.isArray() || c.isPrimitive())
167             return c.getModifiers();
168         return Reflection.getClassAccessFlags(c);
169     }
170 
171     /**

256         int mods = getClassModifiers(refc);
257         if (isPublic(mods)) {
258             if (m1.canRead(refModule) && (m2 == null || m2.canRead(refModule))) {
259                 String pn = refc.getPackageName();
260 
261                 // refc is exported package to at least both m1 and m2
262                 if (refModule.isExported(pn, m1) && (m2 == null || refModule.isExported(pn, m2)))
263                     return true;
264             }
265         }
266         return false;
267     }
268 
269     /**
270      * Decide if the given method type, attributed to a member or symbolic
271      * reference of a given reference class, is really visible to that class.
272      * @param type the supposed type of a member or symbolic reference of refc
273      * @param refc the class attempting to make the reference
274      */
275     public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
276         if (type == refc) {
277             return true;  // easy check
278         }
279         while (type.isArray())  type = type.getComponentType();
280         if (type.isPrimitive() || type == Object.class) {
281             return true;
282         }
283         ClassLoader typeLoader = type.getClassLoader();
284         ClassLoader refcLoader = refc.getClassLoader();
285         if (typeLoader == refcLoader) {
286             return true;
287         }
288         if (refcLoader == null && typeLoader != null) {
289             return false;
290         }
291         if (typeLoader == null && type.getName().startsWith("java.")) {
292             // Note:  The API for actually loading classes, ClassLoader.defineClass,
293             // guarantees that classes with names beginning "java." cannot be aliased,
294             // because class loaders cannot load them directly.
295             return true;
296         }

304         // This would be wasted effort, but it is expected to be very rare, occurring
305         // only when an attacker is attempting to create a type alias.
306         // In the normal case, one class loader will simply delegate to the other,
307         // and the same type will be visible through both, with no extra loading.
308         //
309         // It is important to go through Class.forName instead of ClassLoader.loadClass
310         // because Class.forName goes through the JVM system dictionary, which records
311         // the class lookup once for all. This means that even if a not-well-behaved class loader
312         // would "change its mind" about the meaning of the name, the Class.forName request
313         // will use the result cached in the JVM system dictionary. Note that the JVM system dictionary
314         // will record the first successful result. Unsuccessful results are not stored.
315         //
316         // We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary
317         // class loader about the binding of the proposed name (type.getName()).
318         // The looked up type ("res") is compared for equality against the proposed
319         // type ("type") and then is discarded.  Thus, the worst that can happen to
320         // the "child" class loader is that it is bothered to load and report a class
321         // that differs from "type"; this happens once due to JVM system dictionary
322         // memoization.  And the caller never gets to look at the alternate type binding
323         // ("res"), whether it exists or not.

324         final String name = type.getName();
325         @SuppressWarnings("removal")
326         Class<?> res = java.security.AccessController.doPrivileged(
327                 new java.security.PrivilegedAction<>() {
328                     public Class<?> run() {
329                         try {
330                             return Class.forName(name, false, refcLoader);
331                         } catch (ClassNotFoundException | LinkageError e) {
332                             return null; // Assume the class is not found
333                         }
334                     }
335             });
336         return (type == res);
337     }
338 
339     /**
340      * Decide if the given method type, attributed to a member or symbolic
341      * reference of a given reference class, is really visible to that class.
342      * @param type the supposed type of a member or symbolic reference of refc
343      * @param refc the class attempting to make the reference
344      */
345     public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
346         if (!isTypeVisible(type.returnType(), refc)) {
347             return false;
348         }
349         for (int n = 0, max = type.parameterCount(); n < max; n++) {
350             if (!isTypeVisible(type.parameterType(n), refc)) {
351                 return false;
352             }
353         }
354         return true;
355     }
356 

 88      * @param defc the class in which the proposed member is actually defined
 89      * @param mods modifier flags for the proposed member
 90      * @param lookupClass the class for which the access check is being made
 91      * @param prevLookupClass the class for which the access check is being made
 92      * @param allowedModes allowed modes
 93      * @return true iff the accessing class can access such a member
 94      */
 95     public static boolean isMemberAccessible(Class<?> refc,  // symbolic ref class
 96                                              Class<?> defc,  // actual def class
 97                                              int      mods,  // actual member mods
 98                                              Class<?> lookupClass,
 99                                              Class<?> prevLookupClass,
100                                              int      allowedModes) {
101         if (allowedModes == 0)  return false;
102         assert((allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED|UNCONDITIONAL_ALLOWED|ORIGINAL_ALLOWED)) == 0);
103         // The symbolic reference class (refc) must always be fully verified.
104         if (!isClassAccessible(refc, lookupClass, prevLookupClass, allowedModes)) {
105             return false;
106         }
107         // Usually refc and defc are the same, but verify defc also in case they differ.
108         if (defc.asPrimaryType() == lookupClass  &&
109             (allowedModes & PRIVATE) != 0)
110             return true;        // easy check; all self-access is OK with a private lookup
111 
112         switch (mods & ALL_ACCESS_MODES) {
113         case PUBLIC:
114             assert (allowedModes & PUBLIC) != 0 || (allowedModes & UNCONDITIONAL_ALLOWED) != 0;
115             return true;  // already checked above
116         case PROTECTED:
117             assert !defc.isInterface(); // protected members aren't allowed in interfaces
118             if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
119                 isSamePackage(defc, lookupClass))
120                 return true;
121             if ((allowedModes & PROTECTED) == 0)
122                 return false;
123             // Protected members are accessible by subclasses, which does not include interfaces.
124             // Interfaces are types, not classes. They should not have access to
125             // protected members in j.l.Object, even though it is their superclass.
126             if ((mods & STATIC) != 0 &&
127                 !isRelatedClass(refc, lookupClass))
128                 return false;
129             if ((allowedModes & PROTECTED) != 0 &&
130                 isSubClass(lookupClass, defc))
131                 return true;
132             return false;
133         case PACKAGE_ONLY:  // That is, zero.  Unmarked member is package-only access.
134             assert !defc.isInterface(); // package-private members aren't allowed in interfaces
135             return ((allowedModes & PACKAGE_ALLOWED) != 0 &&
136                     isSamePackage(defc, lookupClass));
137         case PRIVATE:
138             // Rules for privates follows access rules for nestmates.
139             boolean canAccess = ((allowedModes & PRIVATE) != 0 &&
140                                  Reflection.areNestMates(defc, lookupClass));
141             // for private methods the selected method equals the
142             // resolved method - so refc == defc
143             assert (canAccess && refc.asPrimaryType() == defc.asPrimaryType()) || !canAccess;
144             return canAccess;
145         default:
146             throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
147         }
148     }
149 
150     static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
151         return (refc.asPrimaryType() == lookupClass.asPrimaryType() ||
152                 isSubClass(refc, lookupClass) ||
153                 isSubClass(lookupClass, refc));
154     }
155 
156     static boolean isSubClass(Class<?> lookupClass, Class<?> defc) {
157         return defc.isAssignableFrom(lookupClass) &&
158                !lookupClass.isInterface(); // interfaces are types, not classes.
159     }
160 
161     static int getClassModifiers(Class<?> c) {
162         // This would return the mask stored by javac for the source-level modifiers.
163         //   return c.getModifiers();
164         // But what we need for JVM access checks are the actual bits from the class header.
165         // ...But arrays and primitives are synthesized with their own odd flags:
166         if (c.isArray() || c.isPrimitive())
167             return c.getModifiers();
168         return Reflection.getClassAccessFlags(c);
169     }
170 
171     /**

256         int mods = getClassModifiers(refc);
257         if (isPublic(mods)) {
258             if (m1.canRead(refModule) && (m2 == null || m2.canRead(refModule))) {
259                 String pn = refc.getPackageName();
260 
261                 // refc is exported package to at least both m1 and m2
262                 if (refModule.isExported(pn, m1) && (m2 == null || refModule.isExported(pn, m2)))
263                     return true;
264             }
265         }
266         return false;
267     }
268 
269     /**
270      * Decide if the given method type, attributed to a member or symbolic
271      * reference of a given reference class, is really visible to that class.
272      * @param type the supposed type of a member or symbolic reference of refc
273      * @param refc the class attempting to make the reference
274      */
275     public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
276         if (type.asPrimaryType() == refc.asPrimaryType()) {
277             return true;  // easy check
278         }
279         while (type.isArray())  type = type.getComponentType();
280         if (type.isPrimitive() || type == Object.class) {
281             return true;
282         }
283         ClassLoader typeLoader = type.getClassLoader();
284         ClassLoader refcLoader = refc.getClassLoader();
285         if (typeLoader == refcLoader) {
286             return true;
287         }
288         if (refcLoader == null && typeLoader != null) {
289             return false;
290         }
291         if (typeLoader == null && type.getName().startsWith("java.")) {
292             // Note:  The API for actually loading classes, ClassLoader.defineClass,
293             // guarantees that classes with names beginning "java." cannot be aliased,
294             // because class loaders cannot load them directly.
295             return true;
296         }

304         // This would be wasted effort, but it is expected to be very rare, occurring
305         // only when an attacker is attempting to create a type alias.
306         // In the normal case, one class loader will simply delegate to the other,
307         // and the same type will be visible through both, with no extra loading.
308         //
309         // It is important to go through Class.forName instead of ClassLoader.loadClass
310         // because Class.forName goes through the JVM system dictionary, which records
311         // the class lookup once for all. This means that even if a not-well-behaved class loader
312         // would "change its mind" about the meaning of the name, the Class.forName request
313         // will use the result cached in the JVM system dictionary. Note that the JVM system dictionary
314         // will record the first successful result. Unsuccessful results are not stored.
315         //
316         // We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary
317         // class loader about the binding of the proposed name (type.getName()).
318         // The looked up type ("res") is compared for equality against the proposed
319         // type ("type") and then is discarded.  Thus, the worst that can happen to
320         // the "child" class loader is that it is bothered to load and report a class
321         // that differs from "type"; this happens once due to JVM system dictionary
322         // memoization.  And the caller never gets to look at the alternate type binding
323         // ("res"), whether it exists or not.
324 
325         final String name = type.getName();
326         @SuppressWarnings("removal")
327         Class<?> res = java.security.AccessController.doPrivileged(
328                 new java.security.PrivilegedAction<>() {
329                     public Class<?> run() {
330                         try {
331                             return Class.forName(name, false, refcLoader);
332                         } catch (ClassNotFoundException | LinkageError e) {
333                             return null; // Assume the class is not found
334                         }
335                     }
336             });
337         return (type.asPrimaryType() == res);
338     }
339 
340     /**
341      * Decide if the given method type, attributed to a member or symbolic
342      * reference of a given reference class, is really visible to that class.
343      * @param type the supposed type of a member or symbolic reference of refc
344      * @param refc the class attempting to make the reference
345      */
346     public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
347         if (!isTypeVisible(type.returnType(), refc)) {
348             return false;
349         }
350         for (int n = 0, max = type.parameterCount(); n < max; n++) {
351             if (!isTypeVisible(type.parameterType(n), refc)) {
352                 return false;
353             }
354         }
355         return true;
356     }
357 
< prev index next >