ReflectionCheckLinker.java revision 953:221a84ef44c0
1/* 2 * Copyright (c) 2010, 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 26package jdk.nashorn.internal.runtime.linker; 27 28import java.lang.reflect.Modifier; 29import java.lang.reflect.Proxy; 30import jdk.internal.dynalink.CallSiteDescriptor; 31import jdk.internal.dynalink.linker.GuardedInvocation; 32import jdk.internal.dynalink.linker.LinkRequest; 33import jdk.internal.dynalink.linker.LinkerServices; 34import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; 35import jdk.internal.dynalink.support.CallSiteDescriptorFactory; 36import jdk.nashorn.internal.runtime.Context; 37 38/** 39 * Check java reflection permission for java reflective and java.lang.invoke access from scripts 40 */ 41final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{ 42 private static final Class<?> STATEMENT_CLASS = getBeanClass("Statement"); 43 private static final Class<?> XMLENCODER_CLASS = getBeanClass("XMLEncoder"); 44 private static final Class<?> XMLDECODER_CLASS = getBeanClass("XMLDecoder"); 45 46 private static Class<?> getBeanClass(final String name) { 47 try { 48 return Class.forName("java.beans." + name); 49 } catch (final ClassNotFoundException cnfe) { 50 // Possible to miss this class in other profiles. 51 return null; 52 } 53 } 54 55 @Override 56 public boolean canLinkType(final Class<?> type) { 57 return isReflectionClass(type); 58 } 59 60 private static boolean isReflectionClass(final Class<?> type) { 61 // Class or ClassLoader subclasses 62 if (type == Class.class || ClassLoader.class.isAssignableFrom(type)) { 63 return true; 64 } 65 66 // check for bean reflection 67 if ((STATEMENT_CLASS != null && STATEMENT_CLASS.isAssignableFrom(type)) || 68 (XMLENCODER_CLASS != null && XMLENCODER_CLASS.isAssignableFrom(type)) || 69 (XMLDECODER_CLASS != null && XMLDECODER_CLASS.isAssignableFrom(type))) { 70 return true; 71 } 72 73 // package name check 74 final String name = type.getName(); 75 return name.startsWith("java.lang.reflect.") || name.startsWith("java.lang.invoke."); 76 } 77 78 @Override 79 public GuardedInvocation getGuardedInvocation(final LinkRequest origRequest, final LinkerServices linkerServices) 80 throws Exception { 81 checkLinkRequest(origRequest); 82 // let the next linker deal with actual linking 83 return null; 84 } 85 86 private static boolean isReflectiveCheckNeeded(final Class<?> type, final boolean isStatic) { 87 // special handling for Proxy subclasses 88 if (Proxy.class.isAssignableFrom(type)) { 89 if (Proxy.isProxyClass(type)) { 90 // real Proxy class - filter only static access 91 return isStatic; 92 } 93 94 // fake Proxy subclass - filter it always! 95 return true; 96 } 97 98 // check for any other reflective Class 99 return isReflectionClass(type); 100 } 101 102 static void checkReflectionAccess(final Class<?> clazz, final boolean isStatic) { 103 final SecurityManager sm = System.getSecurityManager(); 104 if (sm != null && isReflectiveCheckNeeded(clazz, isStatic)) { 105 checkReflectionPermission(sm); 106 } 107 } 108 109 private static void checkLinkRequest(final LinkRequest origRequest) { 110 final SecurityManager sm = System.getSecurityManager(); 111 if (sm != null) { 112 final LinkRequest requestWithoutContext = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context 113 final Object self = requestWithoutContext.getReceiver(); 114 // allow 'static' access on Class objects representing public classes of non-restricted packages 115 if ((self instanceof Class) && Modifier.isPublic(((Class<?>)self).getModifiers())) { 116 final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor(); 117 if(CallSiteDescriptorFactory.tokenizeOperators(desc).contains("getProp")) { 118 if (desc.getNameTokenCount() > CallSiteDescriptor.NAME_OPERAND && 119 "static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) { 120 if (Context.isAccessibleClass((Class<?>)self) && !isReflectionClass((Class<?>)self)) { 121 122 // If "getProp:static" passes access checks, allow access. 123 return; 124 } 125 } 126 } 127 } 128 checkReflectionPermission(sm); 129 } 130 } 131 132 private static void checkReflectionPermission(final SecurityManager sm) { 133 sm.checkPermission(new RuntimePermission(Context.NASHORN_JAVA_REFLECTION)); 134 } 135} 136