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