1 /*
2 * Copyright (c) 2008, 2013, 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
23 * questions.
24 */
25
26 package sun.invoke.util;
27
28 import java.lang.reflect.Modifier;
29 import static java.lang.reflect.Modifier.*;
30 import java.lang.reflect.Module;
31 import java.util.Objects;
32 import jdk.internal.reflect.Reflection;
33
34 /**
35 * This class centralizes information about the JVM's linkage access control.
36 * @author jrose
37 */
38 public class VerifyAccess {
39
40 private VerifyAccess() { } // cannot instantiate
41
42 private static final int MODULE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.MODULE;
43 private static final int PACKAGE_ONLY = 0;
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 private static final boolean ALLOW_NESTMATE_ACCESS = false;
48
49 /**
50 * Evaluate the JVM linkage rules for access to the given method
51 * on behalf of a caller class which proposes to perform the access.
52 * Return true if the caller class has privileges to invoke a method
53 * or access a field with the given properties.
54 * This requires an accessibility check of the referencing class,
55 * plus an accessibility check of the member within the class,
56 * which depends on the member's modifier flags.
57 * <p>
58 * The relevant properties include the defining class ({@code defc})
59 * of the member, and its modifier flags ({@code mods}).
60 * Also relevant is the class used to make the initial symbolic reference
61 * to the member ({@code refc}). If this latter class is not distinguished,
75 * <li>R is private and is declared in D.
76 * </ul>
77 * This discussion of access control omits a related restriction
78 * on the target of a protected field access or method invocation
79 * (the target must be of class D or a subtype of D). That
80 * requirement is checked as part of the verification process
81 * (5.4.1); it is not part of link-time access control.
82 * @param refc the class used in the symbolic reference to the proposed member
83 * @param defc the class in which the proposed member is actually defined
84 * @param mods modifier flags for the proposed member
85 * @param lookupClass the class for which the access check is being made
86 * @return true iff the accessing class can access such a member
87 */
88 public static boolean isMemberAccessible(Class<?> refc, // symbolic ref class
89 Class<?> defc, // actual def class
90 int mods, // actual member mods
91 Class<?> lookupClass,
92 int allowedModes) {
93 if (allowedModes == 0) return false;
94 assert((allowedModes & PUBLIC) != 0 &&
95 (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED)) == 0);
96 // The symbolic reference class (refc) must always be fully verified.
97 if (!isClassAccessible(refc, lookupClass, allowedModes)) {
98 return false;
99 }
100 // Usually refc and defc are the same, but verify defc also in case they differ.
101 if (defc == lookupClass &&
102 (allowedModes & PRIVATE) != 0)
103 return true; // easy check; all self-access is OK
104 switch (mods & ALL_ACCESS_MODES) {
105 case PUBLIC:
106 return true; // already checked above
107 case PROTECTED:
108 assert !defc.isInterface(); // protected members aren't allowed in interfaces
109 if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
110 isSamePackage(defc, lookupClass))
111 return true;
112 if ((allowedModes & PROTECTED) == 0)
113 return false;
114 // Protected members are accessible by subclasses, which does not include interfaces.
115 // Interfaces are types, not classes. They should not have access to
156 return Reflection.getClassAccessFlags(c);
157 }
158
159 /**
160 * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
161 * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
162 * A class or interface C is accessible to a class or interface D
163 * if and only if any of the following conditions are true:<ul>
164 * <li>C is public and in the same module as D.
165 * <li>D is in a module that reads the module containing C, C is public and in a
166 * package that is exported to the module that contains D.
167 * <li>C and D are members of the same runtime package.
168 * </ul>
169 * @param refc the symbolic reference class to which access is being checked (C)
170 * @param lookupClass the class performing the lookup (D)
171 */
172 public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass,
173 int allowedModes) {
174 if (allowedModes == 0) return false;
175 assert((allowedModes & PUBLIC) != 0 &&
176 (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED)) == 0);
177 int mods = getClassModifiers(refc);
178 if (isPublic(mods)) {
179
180 Module lookupModule = lookupClass.getModule();
181 Module refModule = refc.getModule();
182
183 // early VM startup case, java.base not defined
184 if (lookupModule == null) {
185 assert refModule == null;
186 return true;
187 }
188
189 // trivially allow
190 if ((allowedModes & MODULE_ALLOWED) != 0 &&
191 (lookupModule == refModule))
192 return true;
193
194 // check readability
195 if (lookupModule.canRead(refModule)) {
196
197 // check that refc is in an exported package
198 Class<?> c = refc;
199 while (c.isArray()) {
200 c = c.getComponentType();
201 }
202 if (c.isPrimitive())
203 return true;
204 if ((allowedModes & MODULE_ALLOWED) != 0) {
205 if (refModule.isExported(c.getPackageName(), lookupModule))
206 return true;
207 } else {
208 // exported unconditionally
209 if (refModule.isExported(c.getPackageName()))
210 return true;
211 }
212
213 // not exported but allow access during VM initialization
214 // because java.base does not have its exports setup
215 if (!jdk.internal.misc.VM.isModuleSystemInited())
216 return true;
217 }
218
219 // public class not accessible to lookupClass
220 return false;
221 }
222 if ((allowedModes & PACKAGE_ALLOWED) != 0 &&
223 isSamePackage(lookupClass, refc))
224 return true;
225 return false;
226 }
227
228 /**
229 * Decide if the given method type, attributed to a member or symbolic
|
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
23 * questions.
24 */
25
26 package sun.invoke.util;
27
28 import java.lang.reflect.Modifier;
29 import static java.lang.reflect.Modifier.*;
30 import java.lang.reflect.Module;
31 import java.util.Objects;
32 import jdk.internal.reflect.Reflection;
33
34 /**
35 * This class centralizes information about the JVM's linkage access control.
36 * @author jrose
37 */
38 public class VerifyAccess {
39
40 private VerifyAccess() { } // cannot instantiate
41
42 private static final int UNCONDITIONAL_ALLOWED = java.lang.invoke.MethodHandles.Lookup.UNCONDITIONAL;
43 private static final int MODULE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.MODULE;
44 private static final int PACKAGE_ONLY = 0;
45 private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE;
46 private static final int PROTECTED_OR_PACKAGE_ALLOWED = (PACKAGE_ALLOWED|PROTECTED);
47 private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
48 private static final boolean ALLOW_NESTMATE_ACCESS = false;
49
50 /**
51 * Evaluate the JVM linkage rules for access to the given method
52 * on behalf of a caller class which proposes to perform the access.
53 * Return true if the caller class has privileges to invoke a method
54 * or access a field with the given properties.
55 * This requires an accessibility check of the referencing class,
56 * plus an accessibility check of the member within the class,
57 * which depends on the member's modifier flags.
58 * <p>
59 * The relevant properties include the defining class ({@code defc})
60 * of the member, and its modifier flags ({@code mods}).
61 * Also relevant is the class used to make the initial symbolic reference
62 * to the member ({@code refc}). If this latter class is not distinguished,
76 * <li>R is private and is declared in D.
77 * </ul>
78 * This discussion of access control omits a related restriction
79 * on the target of a protected field access or method invocation
80 * (the target must be of class D or a subtype of D). That
81 * requirement is checked as part of the verification process
82 * (5.4.1); it is not part of link-time access control.
83 * @param refc the class used in the symbolic reference to the proposed member
84 * @param defc the class in which the proposed member is actually defined
85 * @param mods modifier flags for the proposed member
86 * @param lookupClass the class for which the access check is being made
87 * @return true iff the accessing class can access such a member
88 */
89 public static boolean isMemberAccessible(Class<?> refc, // symbolic ref class
90 Class<?> defc, // actual def class
91 int mods, // actual member mods
92 Class<?> lookupClass,
93 int allowedModes) {
94 if (allowedModes == 0) return false;
95 assert((allowedModes & PUBLIC) != 0 &&
96 (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED|UNCONDITIONAL_ALLOWED)) == 0);
97 // The symbolic reference class (refc) must always be fully verified.
98 if (!isClassAccessible(refc, lookupClass, allowedModes)) {
99 return false;
100 }
101 // Usually refc and defc are the same, but verify defc also in case they differ.
102 if (defc == lookupClass &&
103 (allowedModes & PRIVATE) != 0)
104 return true; // easy check; all self-access is OK
105 switch (mods & ALL_ACCESS_MODES) {
106 case PUBLIC:
107 return true; // already checked above
108 case PROTECTED:
109 assert !defc.isInterface(); // protected members aren't allowed in interfaces
110 if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
111 isSamePackage(defc, lookupClass))
112 return true;
113 if ((allowedModes & PROTECTED) == 0)
114 return false;
115 // Protected members are accessible by subclasses, which does not include interfaces.
116 // Interfaces are types, not classes. They should not have access to
157 return Reflection.getClassAccessFlags(c);
158 }
159
160 /**
161 * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
162 * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
163 * A class or interface C is accessible to a class or interface D
164 * if and only if any of the following conditions are true:<ul>
165 * <li>C is public and in the same module as D.
166 * <li>D is in a module that reads the module containing C, C is public and in a
167 * package that is exported to the module that contains D.
168 * <li>C and D are members of the same runtime package.
169 * </ul>
170 * @param refc the symbolic reference class to which access is being checked (C)
171 * @param lookupClass the class performing the lookup (D)
172 */
173 public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass,
174 int allowedModes) {
175 if (allowedModes == 0) return false;
176 assert((allowedModes & PUBLIC) != 0 &&
177 (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED|UNCONDITIONAL_ALLOWED)) == 0);
178 int mods = getClassModifiers(refc);
179 if (isPublic(mods)) {
180
181 Module lookupModule = lookupClass.getModule();
182 Module refModule = refc.getModule();
183
184 // early VM startup case, java.base not defined
185 if (lookupModule == null) {
186 assert refModule == null;
187 return true;
188 }
189
190 // trivially allow
191 if ((allowedModes & MODULE_ALLOWED) != 0 &&
192 (lookupModule == refModule))
193 return true;
194
195 // check readability when UNCONDITIONAL not allowed
196 if (((allowedModes & UNCONDITIONAL_ALLOWED) != 0)
197 || lookupModule.canRead(refModule)) {
198
199 // check that refc is in an exported package
200 if ((allowedModes & MODULE_ALLOWED) != 0) {
201 if (refModule.isExported(refc.getPackageName(), lookupModule))
202 return true;
203 } else {
204 // exported unconditionally
205 if (refModule.isExported(refc.getPackageName()))
206 return true;
207 }
208
209 // not exported but allow access during VM initialization
210 // because java.base does not have its exports setup
211 if (!jdk.internal.misc.VM.isModuleSystemInited())
212 return true;
213 }
214
215 // public class not accessible to lookupClass
216 return false;
217 }
218 if ((allowedModes & PACKAGE_ALLOWED) != 0 &&
219 isSamePackage(lookupClass, refc))
220 return true;
221 return false;
222 }
223
224 /**
225 * Decide if the given method type, attributed to a member or symbolic
|