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
818 if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all
819 return new Lookup(requestedLookupClass, FULL_POWER_MODES);
820 if (requestedLookupClass == this.lookupClass)
821 return this; // keep same capabilities
822 int newModes = (allowedModes & FULL_POWER_MODES);
823 if (!VerifyAccess.isSameModule(this.lookupClass, requestedLookupClass)) {
824 // Need to drop all access when teleporting from a named module to another
825 // module. The exception is publicLookup where PUBLIC is not lost.
826 if (this.lookupClass.getModule().isNamed()
827 && (this.allowedModes & UNCONDITIONAL) == 0)
828 newModes = 0;
829 else
830 newModes &= ~(MODULE|PACKAGE|PRIVATE|PROTECTED);
831 }
832 if ((newModes & PACKAGE) != 0
833 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
834 newModes &= ~(PACKAGE|PRIVATE|PROTECTED);
835 }
836 // Allow nestmate lookups to be created without special privilege:
837 if ((newModes & PRIVATE) != 0
838 && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
839 newModes &= ~(PRIVATE|PROTECTED);
840 }
841 if ((newModes & PUBLIC) != 0
842 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) {
843 // The requested class it not accessible from the lookup class.
844 // No permissions.
845 newModes = 0;
846 }
847
848 checkUnprivilegedlookupClass(requestedLookupClass);
849 return new Lookup(requestedLookupClass, newModes);
850 }
851
852
853 /**
854 * Creates a lookup on the same lookup class which this lookup object
855 * finds members, but with a lookup mode that has lost the given lookup mode.
856 * The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE
857 * MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED} or {@link #PRIVATE PRIVATE}.
858 * {@link #PROTECTED PROTECTED} and {@link #UNCONDITIONAL UNCONDITIONAL} are always
2199 // check the class first:
2200 boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
2201 (defc == refc ||
2202 Modifier.isPublic(refc.getModifiers())));
2203 if (!classOK && (allowedModes & PACKAGE) != 0) {
2204 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), FULL_POWER_MODES) &&
2205 (defc == refc ||
2206 VerifyAccess.isClassAccessible(refc, lookupClass(), FULL_POWER_MODES)));
2207 }
2208 if (!classOK)
2209 return "class is not public";
2210 if (Modifier.isPublic(mods))
2211 return "access to public member failed"; // (how?, module not readable?)
2212 if (Modifier.isPrivate(mods))
2213 return "member is private";
2214 if (Modifier.isProtected(mods))
2215 return "member is protected";
2216 return "member is private to package";
2217 }
2218
2219 private static final boolean ALLOW_NESTMATE_ACCESS = false; // experiment with protected nestmate access
2220
2221 private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
2222 int allowedModes = this.allowedModes;
2223 if (allowedModes == TRUSTED) return;
2224 if (!hasPrivateAccess()
2225 || (specialCaller != lookupClass()
2226 // ensure non-abstract methods in superinterfaces can be special-invoked
2227 && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))
2228 && !(ALLOW_NESTMATE_ACCESS &&
2229 VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
2230 throw new MemberName(specialCaller).
2231 makeAccessException("no private access for invokespecial", this);
2232 }
2233
2234 private boolean restrictProtectedReceiver(MemberName method) {
2235 // The accessing class only has the right to use a protected member
2236 // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc.
2237 if (!method.isProtected() || method.isStatic()
2238 || allowedModes == TRUSTED
2239 || method.getDeclaringClass() == lookupClass()
2240 || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
2241 || (ALLOW_NESTMATE_ACCESS &&
2242 VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
2243 return false;
2244 return true;
2245 }
2246 private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
2247 assert(!method.isStatic());
2248 // receiver type of mh is too wide; narrow to caller
2249 if (!method.getDeclaringClass().isAssignableFrom(caller)) {
2250 throw method.makeAccessException("caller class must be a subclass below the method", caller);
2251 }
2252 MethodType rawType = mh.type();
2253 if (caller.isAssignableFrom(rawType.parameterType(0))) return mh; // no need to restrict; already narrow
2254 MethodType narrowType = rawType.changeParameterType(0, caller);
2255 assert(!mh.isVarargsCollector()); // viewAsType will lose varargs-ness
2256 assert(mh.viewAsTypeChecks(narrowType, true));
2257 return mh.copyWith(narrowType, mh.form);
2258 }
2259
2260 /** Check access and get the requested method. */
2261 private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
2262 final boolean doRestrict = true;
|
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
818 if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all
819 return new Lookup(requestedLookupClass, FULL_POWER_MODES);
820 if (requestedLookupClass == this.lookupClass)
821 return this; // keep same capabilities
822 int newModes = (allowedModes & FULL_POWER_MODES);
823 if (!VerifyAccess.isSameModule(this.lookupClass, requestedLookupClass)) {
824 // Need to drop all access when teleporting from a named module to another
825 // module. The exception is publicLookup where PUBLIC is not lost.
826 if (this.lookupClass.getModule().isNamed()
827 && (this.allowedModes & UNCONDITIONAL) == 0)
828 newModes = 0;
829 else
830 newModes &= ~(MODULE|PACKAGE|PRIVATE|PROTECTED);
831 }
832 if ((newModes & PACKAGE) != 0
833 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
834 newModes &= ~(PACKAGE|PRIVATE|PROTECTED);
835 }
836 // Allow nestmate lookups to be created without special privilege:
837 if ((newModes & PRIVATE) != 0
838 && !Reflection.areNestMates(this.lookupClass, requestedLookupClass)) {
839 newModes &= ~(PRIVATE|PROTECTED);
840 }
841 if ((newModes & PUBLIC) != 0
842 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) {
843 // The requested class it not accessible from the lookup class.
844 // No permissions.
845 newModes = 0;
846 }
847
848 checkUnprivilegedlookupClass(requestedLookupClass);
849 return new Lookup(requestedLookupClass, newModes);
850 }
851
852
853 /**
854 * Creates a lookup on the same lookup class which this lookup object
855 * finds members, but with a lookup mode that has lost the given lookup mode.
856 * The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE
857 * MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED} or {@link #PRIVATE PRIVATE}.
858 * {@link #PROTECTED PROTECTED} and {@link #UNCONDITIONAL UNCONDITIONAL} are always
2199 // check the class first:
2200 boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
2201 (defc == refc ||
2202 Modifier.isPublic(refc.getModifiers())));
2203 if (!classOK && (allowedModes & PACKAGE) != 0) {
2204 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), FULL_POWER_MODES) &&
2205 (defc == refc ||
2206 VerifyAccess.isClassAccessible(refc, lookupClass(), FULL_POWER_MODES)));
2207 }
2208 if (!classOK)
2209 return "class is not public";
2210 if (Modifier.isPublic(mods))
2211 return "access to public member failed"; // (how?, module not readable?)
2212 if (Modifier.isPrivate(mods))
2213 return "member is private";
2214 if (Modifier.isProtected(mods))
2215 return "member is protected";
2216 return "member is private to package";
2217 }
2218
2219 private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
2220 int allowedModes = this.allowedModes;
2221 if (allowedModes == TRUSTED) return;
2222 if (!hasPrivateAccess()
2223 || (specialCaller != lookupClass()
2224 // ensure non-abstract methods in superinterfaces can be special-invoked
2225 && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))))
2226 throw new MemberName(specialCaller).
2227 makeAccessException("no private access for invokespecial", this);
2228 }
2229
2230 private boolean restrictProtectedReceiver(MemberName method) {
2231 // The accessing class only has the right to use a protected member
2232 // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc.
2233 if (!method.isProtected() || method.isStatic()
2234 || allowedModes == TRUSTED
2235 || method.getDeclaringClass() == lookupClass()
2236 || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass()))
2237 return false;
2238 return true;
2239 }
2240 private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
2241 assert(!method.isStatic());
2242 // receiver type of mh is too wide; narrow to caller
2243 if (!method.getDeclaringClass().isAssignableFrom(caller)) {
2244 throw method.makeAccessException("caller class must be a subclass below the method", caller);
2245 }
2246 MethodType rawType = mh.type();
2247 if (caller.isAssignableFrom(rawType.parameterType(0))) return mh; // no need to restrict; already narrow
2248 MethodType narrowType = rawType.changeParameterType(0, caller);
2249 assert(!mh.isVarargsCollector()); // viewAsType will lose varargs-ness
2250 assert(mh.viewAsTypeChecks(narrowType, true));
2251 return mh.copyWith(narrowType, mh.form);
2252 }
2253
2254 /** Check access and get the requested method. */
2255 private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
2256 final boolean doRestrict = true;
|