1 /*
2 * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
44 private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE;
45 private static final int PROTECTED_OR_PACKAGE_ALLOWED = (PACKAGE_ALLOWED|PROTECTED);
46 private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
47
48 /**
49 * Evaluate the JVM linkage rules for access to the given method
50 * on behalf of a caller class which proposes to perform the access.
51 * Return true if the caller class has privileges to invoke a method
52 * or access a field with the given properties.
53 * This requires an accessibility check of the referencing class,
54 * plus an accessibility check of the member within the class,
55 * which depends on the member's modifier flags.
56 * <p>
57 * The relevant properties include the defining class ({@code defc})
58 * of the member, and its modifier flags ({@code mods}).
59 * Also relevant is the class used to make the initial symbolic reference
60 * to the member ({@code refc}). If this latter class is not distinguished,
61 * the defining class should be passed for both arguments ({@code defc == refc}).
62 * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
63 * A field or method R is accessible to a class or interface D if
64 * and only if any of the following conditions is true:<ul>
65 * <li>R is public.
66 * <li>R is protected and is declared in a class C, and D is either
67 * a subclass of C or C itself. Furthermore, if R is not
68 * static, then the symbolic reference to R must contain a
69 * symbolic reference to a class T, such that T is either a
70 * subclass of D, a superclass of D or D itself.
71 * <li>R is either protected or has default access (that is,
72 * neither public nor protected nor private), and is declared
73 * by a class in the same runtime package as D.
74 * <li>R is private and is declared in D.
75 * </ul>
76 * This discussion of access control omits a related restriction
77 * on the target of a protected field access or method invocation
78 * (the target must be of class D or a subtype of D). That
79 * requirement is checked as part of the verification process
80 * (5.4.1); it is not part of link-time access control.
81 * @param refc the class used in the symbolic reference to the proposed member
82 * @param defc the class in which the proposed member is actually defined
83 * @param mods modifier flags for the proposed member
84 * @param lookupClass the class for which the access check is being made
85 * @return true iff the accessing class can access such a member
86 */
87 public static boolean isMemberAccessible(Class<?> refc, // symbolic ref class
88 Class<?> defc, // actual def class
89 int mods, // actual member mods
90 Class<?> lookupClass,
91 int allowedModes) {
92 if (allowedModes == 0) return false;
93 assert((allowedModes & PUBLIC) != 0 &&
94 (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED|UNCONDITIONAL_ALLOWED)) == 0);
95 // The symbolic reference class (refc) must always be fully verified.
96 if (!isClassAccessible(refc, lookupClass, allowedModes)) {
97 return false;
98 }
99 // Usually refc and defc are the same, but verify defc also in case they differ.
100 if (defc == lookupClass &&
101 (allowedModes & PRIVATE) != 0)
102 return true; // easy check; all self-access is OK
103 switch (mods & ALL_ACCESS_MODES) {
104 case PUBLIC:
105 return true; // already checked above
106 case PROTECTED:
107 assert !defc.isInterface(); // protected members aren't allowed in interfaces
108 if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
109 isSamePackage(defc, lookupClass))
110 return true;
111 if ((allowedModes & PROTECTED) == 0)
112 return false;
113 // Protected members are accessible by subclasses, which does not include interfaces.
114 // Interfaces are types, not classes. They should not have access to
115 // protected members in j.l.Object, even though it is their superclass.
116 if ((mods & STATIC) != 0 &&
117 !isRelatedClass(refc, lookupClass))
118 return false;
119 if ((allowedModes & PROTECTED) != 0 &&
120 isSubClass(lookupClass, defc))
121 return true;
122 return false;
123 case PACKAGE_ONLY: // That is, zero. Unmarked member is package-only access.
124 assert !defc.isInterface(); // package-private members aren't allowed in interfaces
125 return ((allowedModes & PACKAGE_ALLOWED) != 0 &&
126 isSamePackage(defc, lookupClass));
127 case PRIVATE:
128 // Loosened rules for privates follows access rules for nestmates.
129 return ((allowedModes & PRIVATE) != 0 &&
130 isSamePackageMember(defc, lookupClass));
131 default:
132 throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
133 }
134 }
135
136 static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
137 return (refc == lookupClass ||
138 isSubClass(refc, lookupClass) ||
139 isSubClass(lookupClass, refc));
140 }
141
142 static boolean isSubClass(Class<?> lookupClass, Class<?> defc) {
143 return defc.isAssignableFrom(lookupClass) &&
144 !lookupClass.isInterface(); // interfaces are types, not classes.
145 }
146
147 static int getClassModifiers(Class<?> c) {
148 // This would return the mask stored by javac for the source-level modifiers.
149 // return c.getModifiers();
150 // But what we need for JVM access checks are the actual bits from the class header.
311 * @param class2 another class
312 * @return whether they are in the same module
313 */
314 public static boolean isSameModule(Class<?> class1, Class<?> class2) {
315 return class1.getModule() == class2.getModule();
316 }
317
318 /**
319 * Test if two classes have the same class loader and package qualifier.
320 * @param class1 a class
321 * @param class2 another class
322 * @return whether they are in the same package
323 */
324 public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
325 assert(!class1.isArray() && !class2.isArray());
326 if (class1 == class2)
327 return true;
328 if (class1.getClassLoader() != class2.getClassLoader())
329 return false;
330 return Objects.equals(class1.getPackageName(), class2.getPackageName());
331 }
332
333 /**
334 * Test if two classes are defined as part of the same package member (top-level class).
335 * If this is true, they can share private access with each other.
336 * @param class1 a class
337 * @param class2 another class
338 * @return whether they are identical or nested together
339 */
340 public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
341 if (class1 == class2)
342 return true;
343 if (!isSamePackage(class1, class2))
344 return false;
345
346 return Reflection.areNestMates(class1, class2);
347 }
348
349 private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2,
350 boolean loader1MustBeParent) {
351 if (loader1 == loader2 || loader1 == null
352 || (loader2 == null && !loader1MustBeParent)) {
353 return true;
354 }
355 for (ClassLoader scan2 = loader2;
356 scan2 != null; scan2 = scan2.getParent()) {
357 if (scan2 == loader1) return true;
358 }
359 if (loader1MustBeParent) return false;
360 // see if loader2 is a parent of loader1:
361 for (ClassLoader scan1 = loader1;
362 scan1 != null; scan1 = scan1.getParent()) {
363 if (scan1 == loader2) return true;
364 }
365 return false;
366 }
|
1 /*
2 * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
44 private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE;
45 private static final int PROTECTED_OR_PACKAGE_ALLOWED = (PACKAGE_ALLOWED|PROTECTED);
46 private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
47
48 /**
49 * Evaluate the JVM linkage rules for access to the given method
50 * on behalf of a caller class which proposes to perform the access.
51 * Return true if the caller class has privileges to invoke a method
52 * or access a field with the given properties.
53 * This requires an accessibility check of the referencing class,
54 * plus an accessibility check of the member within the class,
55 * which depends on the member's modifier flags.
56 * <p>
57 * The relevant properties include the defining class ({@code defc})
58 * of the member, and its modifier flags ({@code mods}).
59 * Also relevant is the class used to make the initial symbolic reference
60 * to the member ({@code refc}). If this latter class is not distinguished,
61 * the defining class should be passed for both arguments ({@code defc == refc}).
62 * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
63 * A field or method R is accessible to a class or interface D if
64 * and only if any of the following is true:
65 * <ul>
66 * <li>R is public.</li>
67 * <li>R is protected and is declared in a class C, and D is either
68 * a subclass of C or C itself. Furthermore, if R is not static,
69 * then the symbolic reference to R must contain a symbolic
70 * reference to a class T, such that T is either a subclass of D,
71 * a superclass of D, or D itself.
72 * <p>During verification, it was also required that, even if T is
73 * a superclass of D, the target reference of a protected instance
74 * field access or method invocation must be an instance of D or a
75 * subclass of D (4.10.1.8).</p></li>
76 * <li>R is either protected or has default access (that is, neither
77 * public nor protected nor private), and is declared by a class
78 * in the same run-time package as D.</li>
79 * <li>R is private and is declared in D by a class or interface
80 * belonging to the same nest as D.</li>
81 * </ul>
82 * If a referenced field or method is not accessible, access checking
83 * throws an IllegalAccessError. If an exception is thrown while
84 * attempting to determine the nest host of a class or interface,
85 * access checking fails for the same reason.
86 *
87 * @param refc the class used in the symbolic reference to the proposed member
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 * @return true iff the accessing class can access such a member
92 */
93 public static boolean isMemberAccessible(Class<?> refc, // symbolic ref class
94 Class<?> defc, // actual def class
95 int mods, // actual member mods
96 Class<?> lookupClass,
97 int allowedModes) {
98 if (allowedModes == 0) return false;
99 assert((allowedModes & PUBLIC) != 0 &&
100 (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED|UNCONDITIONAL_ALLOWED)) == 0);
101 // The symbolic reference class (refc) must always be fully verified.
102 if (!isClassAccessible(refc, lookupClass, allowedModes)) {
103 return false;
104 }
105 // Usually refc and defc are the same, but verify defc also in case they differ.
106 if (defc == lookupClass)
107 return true; // easy check; all self-access is OK
108
109 switch (mods & ALL_ACCESS_MODES) {
110 case PUBLIC:
111 return true; // already checked above
112 case PROTECTED:
113 assert !defc.isInterface(); // protected members aren't allowed in interfaces
114 if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
115 isSamePackage(defc, lookupClass))
116 return true;
117 if ((allowedModes & PROTECTED) == 0)
118 return false;
119 // Protected members are accessible by subclasses, which does not include interfaces.
120 // Interfaces are types, not classes. They should not have access to
121 // protected members in j.l.Object, even though it is their superclass.
122 if ((mods & STATIC) != 0 &&
123 !isRelatedClass(refc, lookupClass))
124 return false;
125 if ((allowedModes & PROTECTED) != 0 &&
126 isSubClass(lookupClass, defc))
127 return true;
128 return false;
129 case PACKAGE_ONLY: // That is, zero. Unmarked member is package-only access.
130 assert !defc.isInterface(); // package-private members aren't allowed in interfaces
131 return ((allowedModes & PACKAGE_ALLOWED) != 0 &&
132 isSamePackage(defc, lookupClass));
133 case PRIVATE:
134 // Rules for privates follows access rules for nestmates.
135 return ((allowedModes & PRIVATE) != 0 &&
136 Reflection.areNestMates(defc, lookupClass));
137 default:
138 throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
139 }
140 }
141
142 static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
143 return (refc == lookupClass ||
144 isSubClass(refc, lookupClass) ||
145 isSubClass(lookupClass, refc));
146 }
147
148 static boolean isSubClass(Class<?> lookupClass, Class<?> defc) {
149 return defc.isAssignableFrom(lookupClass) &&
150 !lookupClass.isInterface(); // interfaces are types, not classes.
151 }
152
153 static int getClassModifiers(Class<?> c) {
154 // This would return the mask stored by javac for the source-level modifiers.
155 // return c.getModifiers();
156 // But what we need for JVM access checks are the actual bits from the class header.
317 * @param class2 another class
318 * @return whether they are in the same module
319 */
320 public static boolean isSameModule(Class<?> class1, Class<?> class2) {
321 return class1.getModule() == class2.getModule();
322 }
323
324 /**
325 * Test if two classes have the same class loader and package qualifier.
326 * @param class1 a class
327 * @param class2 another class
328 * @return whether they are in the same package
329 */
330 public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
331 assert(!class1.isArray() && !class2.isArray());
332 if (class1 == class2)
333 return true;
334 if (class1.getClassLoader() != class2.getClassLoader())
335 return false;
336 return Objects.equals(class1.getPackageName(), class2.getPackageName());
337 }
338
339 private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2,
340 boolean loader1MustBeParent) {
341 if (loader1 == loader2 || loader1 == null
342 || (loader2 == null && !loader1MustBeParent)) {
343 return true;
344 }
345 for (ClassLoader scan2 = loader2;
346 scan2 != null; scan2 = scan2.getParent()) {
347 if (scan2 == loader1) return true;
348 }
349 if (loader1MustBeParent) return false;
350 // see if loader2 is a parent of loader1:
351 for (ClassLoader scan1 = loader1;
352 scan1 != null; scan1 = scan1.getParent()) {
353 if (scan1 == loader2) return true;
354 }
355 return false;
356 }
|