1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2005, 2013 Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 28 package sun.reflect.misc; 29 30 import java.lang.reflect.Modifier; 31 import java.lang.reflect.Proxy; 32 import sun.reflect.Reflection; 33 34 public final class ReflectUtil { 35 ReflectUtil()36 private ReflectUtil() { 37 } 38 forName(String name)39 public static Class<?> forName(String name) 40 throws ClassNotFoundException { 41 checkPackageAccess(name); 42 return Class.forName(name); 43 } 44 newInstance(Class<?> cls)45 public static Object newInstance(Class<?> cls) 46 throws InstantiationException, IllegalAccessException { 47 checkPackageAccess(cls); 48 return cls.newInstance(); 49 } 50 51 /* 52 * Reflection.ensureMemberAccess is overly-restrictive 53 * due to a bug. We awkwardly work around it for now. 54 */ ensureMemberAccess(Class<?> currentClass, Class<?> memberClass, Object target, int modifiers)55 public static void ensureMemberAccess(Class<?> currentClass, 56 Class<?> memberClass, 57 Object target, 58 int modifiers) 59 throws IllegalAccessException 60 { 61 if (target == null && Modifier.isProtected(modifiers)) { 62 int mods = modifiers; 63 mods = mods & (~Modifier.PROTECTED); 64 mods = mods | Modifier.PUBLIC; 65 66 /* 67 * See if we fail because of class modifiers 68 */ 69 Reflection.ensureMemberAccess(currentClass, 70 memberClass, 71 target, 72 mods); 73 try { 74 /* 75 * We're still here so class access was ok. 76 * Now try with default field access. 77 */ 78 mods = mods & (~Modifier.PUBLIC); 79 Reflection.ensureMemberAccess(currentClass, 80 memberClass, 81 target, 82 mods); 83 /* 84 * We're still here so access is ok without 85 * checking for protected. 86 */ 87 return; 88 } catch (IllegalAccessException e) { 89 /* 90 * Access failed but we're 'protected' so 91 * if the test below succeeds then we're ok. 92 */ 93 if (isSubclassOf(currentClass, memberClass)) { 94 return; 95 } else { 96 throw e; 97 } 98 } 99 } else { 100 Reflection.ensureMemberAccess(currentClass, 101 memberClass, 102 target, 103 modifiers); 104 } 105 } 106 isSubclassOf(Class<?> queryClass, Class<?> ofClass)107 private static boolean isSubclassOf(Class<?> queryClass, 108 Class<?> ofClass) 109 { 110 while (queryClass != null) { 111 if (queryClass == ofClass) { 112 return true; 113 } 114 queryClass = queryClass.getSuperclass(); 115 } 116 return false; 117 } 118 119 // Android-removed: Dead code: Unused method conservativeCheckMemberAccess(). 120 121 /** 122 * Checks package access on the given class. 123 * 124 * If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements 125 * a non-public interface (i.e. may be in a non-restricted package), 126 * also check the package access on the proxy interfaces. 127 */ checkPackageAccess(Class<?> clazz)128 public static void checkPackageAccess(Class<?> clazz) { 129 checkPackageAccess(clazz.getName()); 130 if (isNonPublicProxyClass(clazz)) { 131 checkProxyPackageAccess(clazz); 132 } 133 } 134 135 /** 136 * Checks package access on the given classname. 137 * This method is typically called when the Class instance is not 138 * available and the caller attempts to load a class on behalf 139 * the true caller (application). 140 */ checkPackageAccess(String name)141 public static void checkPackageAccess(String name) { 142 SecurityManager s = System.getSecurityManager(); 143 if (s != null) { 144 String cname = name.replace('/', '.'); 145 if (cname.startsWith("[")) { 146 int b = cname.lastIndexOf('[') + 2; 147 if (b > 1 && b < cname.length()) { 148 cname = cname.substring(b); 149 } 150 } 151 int i = cname.lastIndexOf('.'); 152 if (i != -1) { 153 s.checkPackageAccess(cname.substring(0, i)); 154 } 155 } 156 } 157 isPackageAccessible(Class<?> clazz)158 public static boolean isPackageAccessible(Class<?> clazz) { 159 try { 160 checkPackageAccess(clazz); 161 } catch (SecurityException e) { 162 return false; 163 } 164 return true; 165 } 166 167 // Returns true if p is an ancestor of cl i.e. class loader 'p' can 168 // be found in the cl's delegation chain isAncestor(ClassLoader p, ClassLoader cl)169 private static boolean isAncestor(ClassLoader p, ClassLoader cl) { 170 ClassLoader acl = cl; 171 do { 172 acl = acl.getParent(); 173 if (p == acl) { 174 return true; 175 } 176 } while (acl != null); 177 return false; 178 } 179 180 /** 181 * Returns true if package access check is needed for reflective 182 * access from a class loader 'from' to classes or members in 183 * a class defined by class loader 'to'. This method returns true 184 * if 'from' is not the same as or an ancestor of 'to'. All code 185 * in a system domain are granted with all permission and so this 186 * method returns false if 'from' class loader is a class loader 187 * loading system classes. On the other hand, if a class loader 188 * attempts to access system domain classes, it requires package 189 * access check and this method will return true. 190 */ needsPackageAccessCheck(ClassLoader from, ClassLoader to)191 public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) { 192 if (from == null || from == to) 193 return false; 194 195 if (to == null) 196 return true; 197 198 return !isAncestor(from, to); 199 } 200 201 /** 202 * Check package access on the proxy interfaces that the given proxy class 203 * implements. 204 * 205 * @param clazz Proxy class object 206 */ checkProxyPackageAccess(Class<?> clazz)207 public static void checkProxyPackageAccess(Class<?> clazz) { 208 SecurityManager s = System.getSecurityManager(); 209 if (s != null) { 210 // check proxy interfaces if the given class is a proxy class 211 if (Proxy.isProxyClass(clazz)) { 212 for (Class<?> intf : clazz.getInterfaces()) { 213 checkPackageAccess(intf); 214 } 215 } 216 } 217 } 218 219 /** 220 * Access check on the interfaces that a proxy class implements and throw 221 * {@code SecurityException} if it accesses a restricted package from 222 * the caller's class loader. 223 * 224 * @param ccl the caller's class loader 225 * @param interfaces the list of interfaces that a proxy class implements 226 */ checkProxyPackageAccess(ClassLoader ccl, Class<?>... interfaces)227 public static void checkProxyPackageAccess(ClassLoader ccl, 228 Class<?>... interfaces) 229 { 230 SecurityManager sm = System.getSecurityManager(); 231 if (sm != null) { 232 for (Class<?> intf : interfaces) { 233 ClassLoader cl = intf.getClassLoader(); 234 if (needsPackageAccessCheck(ccl, cl)) { 235 checkPackageAccess(intf); 236 } 237 } 238 } 239 } 240 241 // Android-changed: Proxy classes are generated in the default package on Android. 242 /* 243 // Note that bytecode instrumentation tools may exclude 'sun.*' 244 // classes but not generated proxy classes and so keep it in com.sun.* 245 public static final String PROXY_PACKAGE = "com.sun.proxy"; 246 */ 247 248 /** 249 * Test if the given class is a proxy class that implements 250 * non-public interface. Such proxy class may be in a non-restricted 251 * package that bypasses checkPackageAccess. 252 */ isNonPublicProxyClass(Class<?> cls)253 public static boolean isNonPublicProxyClass(Class<?> cls) { 254 String name = cls.getName(); 255 int i = name.lastIndexOf('.'); 256 String pkg = (i != -1) ? name.substring(0, i) : ""; 257 // Android-changed: Proxy classes are generated in the default package on Android. 258 // The use of the default package (as opposed to com.sun.proxy) makes this check 259 // imprecise. However, this function is only ever called if there's 260 // a security manager installed (which is the never case on Android). 261 // return Proxy.isProxyClass(cls) && !pkg.equals(PROXY_PACKAGE); 262 return Proxy.isProxyClass(cls) && !pkg.isEmpty(); 263 } 264 265 // Android-removed: Dead code: unused method checkProxyMethod(). 266 // Android-removed: Dead code: unused method isVMAnonymousClass(). 267 } 268