1 /* 2 * Copyright (c) 2005, 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 27 package sun.reflect.misc; 28 29 import java.lang.reflect.Member; 30 import java.lang.reflect.Method; 31 import java.lang.reflect.Modifier; 32 import java.lang.reflect.Proxy; 33 import jdk.internal.reflect.Reflection; 34 import sun.security.util.SecurityConstants; 35 36 public final class ReflectUtil { 37 38 private ReflectUtil() { 39 } 40 41 public static Class<?> forName(String name) 42 throws ClassNotFoundException { 43 checkPackageAccess(name); 44 return Class.forName(name); 45 } 46 47 /* 48 * Reflection.ensureMemberAccess is overly-restrictive 49 * due to a bug. We awkwardly work around it for now. 50 */ 51 public static void ensureMemberAccess(Class<?> currentClass, 52 Class<?> memberClass, 53 Object target, 54 int modifiers) 55 throws IllegalAccessException 56 { 57 if (target == null && Modifier.isProtected(modifiers)) { 58 int mods = modifiers; 59 mods = mods & (~Modifier.PROTECTED); 60 mods = mods | Modifier.PUBLIC; 61 62 /* 63 * See if we fail because of class modifiers 64 */ 65 Reflection.ensureMemberAccess(currentClass, 66 memberClass, 67 target, 68 mods); 69 try { 70 /* 71 * We're still here so class access was ok. 72 * Now try with default field access. 73 */ 74 mods = mods & (~Modifier.PUBLIC); 75 Reflection.ensureMemberAccess(currentClass, 76 memberClass, 77 target, 78 mods); 79 /* 80 * We're still here so access is ok without 81 * checking for protected. 82 */ 83 return; 84 } catch (IllegalAccessException e) { 85 /* 86 * Access failed but we're 'protected' so 87 * if the test below succeeds then we're ok. 88 */ 89 if (isSubclassOf(currentClass, memberClass)) { 90 return; 91 } else { 92 throw e; 93 } 94 } 95 } else { 96 Reflection.ensureMemberAccess(currentClass, 97 memberClass, 98 target, 99 modifiers); 100 } 101 } 102 103 private static boolean isSubclassOf(Class<?> queryClass, 104 Class<?> ofClass) 105 { 106 while (queryClass != null) { 107 if (queryClass == ofClass) { 108 return true; 109 } 110 queryClass = queryClass.getSuperclass(); 111 } 112 return false; 113 } 114 115 /** 116 * Does a conservative approximation of member access check. Use this if 117 * you don't have an actual 'userland' caller Class/ClassLoader available. 118 * This might be more restrictive than a precise member access check where 119 * you have a caller, but should never allow a member access that is 120 * forbidden. 121 * 122 * @param m the {@code Member} about to be accessed 123 */ 124 public static void conservativeCheckMemberAccess(Member m) throws SecurityException{ 125 final SecurityManager sm = System.getSecurityManager(); 126 if (sm == null) 127 return; 128 129 // Check for package access on the declaring class. 130 // 131 // In addition, unless the member and the declaring class are both 132 // public check for access declared member permissions. 133 // 134 // This is done regardless of ClassLoader relations between the {@code 135 // Member m} and any potential caller. 136 137 final Class<?> declaringClass = m.getDeclaringClass(); 138 139 checkPackageAccess(declaringClass); 140 141 if (Modifier.isPublic(m.getModifiers()) && 142 Modifier.isPublic(declaringClass.getModifiers())) 143 return; 144 145 // Check for declared member access. 146 sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); 147 } 148 149 /** 150 * Checks package access on the given class. 151 * 152 * If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements 153 * a non-public interface (i.e. may be in a non-restricted package), 154 * also check the package access on the proxy interfaces. 155 */ 156 public static void checkPackageAccess(Class<?> clazz) { 157 checkPackageAccess(clazz.getName()); 158 if (isNonPublicProxyClass(clazz)) { 159 checkProxyPackageAccess(clazz); 160 } 161 } 162 163 /** 164 * Checks package access on the given classname. 165 * This method is typically called when the Class instance is not 166 * available and the caller attempts to load a class on behalf 167 * the true caller (application). 168 */ 169 public static void checkPackageAccess(String name) { 170 SecurityManager s = System.getSecurityManager(); 171 if (s != null) { 172 String cname = name.replace('/', '.'); 173 if (cname.startsWith("[")) { 174 int b = cname.lastIndexOf('[') + 2; 175 if (b > 1 && b < cname.length()) { 176 cname = cname.substring(b); 177 } 178 } 179 int i = cname.lastIndexOf('.'); 180 if (i != -1) { 181 s.checkPackageAccess(cname.substring(0, i)); 182 } 183 } 184 } 185 186 public static boolean isPackageAccessible(Class<?> clazz) { 187 try { 188 checkPackageAccess(clazz); 189 } catch (SecurityException e) { 190 return false; 191 } 192 return true; 193 } 194 195 // Returns true if p is an ancestor of cl i.e. class loader 'p' can 196 // be found in the cl's delegation chain 197 private static boolean isAncestor(ClassLoader p, ClassLoader cl) { 198 ClassLoader acl = cl; 199 do { 200 acl = acl.getParent(); 201 if (p == acl) { 202 return true; 203 } 204 } while (acl != null); 205 return false; 206 } 207 208 /** 209 * Returns true if package access check is needed for reflective 210 * access from a class loader 'from' to classes or members in 211 * a class defined by class loader 'to'. This method returns true 212 * if 'from' is not the same as or an ancestor of 'to'. All code 213 * in a system domain are granted with all permission and so this 214 * method returns false if 'from' class loader is a class loader 215 * loading system classes. On the other hand, if a class loader 216 * attempts to access system domain classes, it requires package 217 * access check and this method will return true. 218 */ 219 public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) { 220 if (from == null || from == to) 221 return false; 222 223 if (to == null) 224 return true; 225 226 return !isAncestor(from, to); 227 } 228 229 /** 230 * Check package access on the proxy interfaces that the given proxy class 231 * implements. 232 * 233 * @param clazz Proxy class object 234 */ 235 public static void checkProxyPackageAccess(Class<?> clazz) { 236 SecurityManager s = System.getSecurityManager(); 237 if (s != null) { 238 // check proxy interfaces if the given class is a proxy class 239 if (Proxy.isProxyClass(clazz)) { 240 for (Class<?> intf : clazz.getInterfaces()) { 241 checkPackageAccess(intf); 242 } 243 } 244 } 245 } 246 247 /** 248 * Access check on the interfaces that a proxy class implements and throw 249 * {@code SecurityException} if it accesses a restricted package from 250 * the caller's class loader. 251 * 252 * @param ccl the caller's class loader 253 * @param interfaces the list of interfaces that a proxy class implements 254 */ 255 public static void checkProxyPackageAccess(ClassLoader ccl, 256 Class<?>... interfaces) 257 { 258 SecurityManager sm = System.getSecurityManager(); 259 if (sm != null) { 260 for (Class<?> intf : interfaces) { 261 ClassLoader cl = intf.getClassLoader(); 262 if (needsPackageAccessCheck(ccl, cl)) { 263 checkPackageAccess(intf); 264 } 265 } 266 } 267 } 268 269 // Note that bytecode instrumentation tools may exclude 'sun.*' 270 // classes but not generated proxy classes and so keep it in com.sun.* 271 public static final String PROXY_PACKAGE = "com.sun.proxy"; 272 273 /** 274 * Test if the given class is a proxy class that implements 275 * non-public interface. Such proxy class may be in a non-restricted 276 * package that bypasses checkPackageAccess. 277 */ 278 public static boolean isNonPublicProxyClass(Class<?> cls) { 279 String name = cls.getName(); 280 int i = name.lastIndexOf('.'); 281 String pkg = (i != -1) ? name.substring(0, i) : ""; 282 return Proxy.isProxyClass(cls) && !pkg.startsWith(PROXY_PACKAGE); 283 } 284 285 /** 286 * Check if the given method is a method declared in the proxy interface 287 * implemented by the given proxy instance. 288 * 289 * @param proxy a proxy instance 290 * @param method an interface method dispatched to a InvocationHandler 291 * 292 * @throws IllegalArgumentException if the given proxy or method is invalid. 293 */ 294 public static void checkProxyMethod(Object proxy, Method method) { 295 // check if it is a valid proxy instance 296 if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) { 297 throw new IllegalArgumentException("Not a Proxy instance"); 298 } 299 if (Modifier.isStatic(method.getModifiers())) { 300 throw new IllegalArgumentException("Can't handle static method"); 301 } 302 303 Class<?> c = method.getDeclaringClass(); 304 if (c == Object.class) { 305 String name = method.getName(); 306 if (name.equals("hashCode") || name.equals("equals") || name.equals("toString")) { 307 return; 308 } 309 } 310 311 if (isSuperInterface(proxy.getClass(), c)) { 312 return; 313 } 314 315 // disallow any method not declared in one of the proxy interfaces 316 throw new IllegalArgumentException("Can't handle: " + method); 317 } 318 319 private static boolean isSuperInterface(Class<?> c, Class<?> intf) { 320 for (Class<?> i : c.getInterfaces()) { 321 if (i == intf) { 322 return true; 323 } 324 if (isSuperInterface(i, intf)) { 325 return true; 326 } 327 } 328 return false; 329 } 330 331 /** 332 * Checks if {@code Class cls} is a VM-anonymous class 333 * as defined by {@link jdk.internal.misc.Unsafe#defineAnonymousClass} 334 * (not to be confused with a Java Language anonymous inner class). 335 */ 336 public static boolean isVMAnonymousClass(Class<?> cls) { 337 return cls.getName().indexOf('/') > -1; 338 } 339 }