8020508: Enforce reflection access restrictions on Object.bindProperties
authorattila
Mon, 15 Jul 2013 16:31:49 +0200
changeset 18878 078eb52cf5bc
parent 18877 6d75ba520886
child 18879 382986b34105
8020508: Enforce reflection access restrictions on Object.bindProperties Reviewed-by: jlaskey, sundar
nashorn/src/jdk/nashorn/internal/objects/NativeObject.java
nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
nashorn/test/script/basic/JDK-8020508.js
nashorn/test/script/basic/JDK-8020508.js.EXPECTED
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java	Mon Jul 15 15:51:06 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java	Mon Jul 15 16:31:49 2013 +0200
@@ -619,6 +619,7 @@
         propertyNames.addAll(writablePropertyNames);
 
         final Class<?> clazz = source.getClass();
+        Bootstrap.checkReflectionAccess(clazz);
 
         final MethodType getterType = MethodType.methodType(Object.class, clazz);
         final MethodType setterType = MethodType.methodType(Object.class, clazz, Object.class);
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Mon Jul 15 15:51:06 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Mon Jul 15 16:31:49 2013 +0200
@@ -217,6 +217,17 @@
     public static Object bindDynamicMethod(Object dynamicMethod, Object boundThis) {
         return new BoundDynamicMethod(dynamicMethod, boundThis);
     }
+
+    /**
+     * If the given class is a reflection-specific class (anything in {@code java.lang.reflect} and
+     * {@code java.lang.invoke} package, as well a {@link Class} and any subclass of {@link ClassLoader}) and there is
+     * a security manager in the system, then it checks the {@code nashorn.JavaReflection} {@code RuntimePermission}.
+     * @param clazz the class being tested
+     */
+    public static void checkReflectionAccess(Class<?> clazz) {
+        ReflectionCheckLinker.checkReflectionAccess(clazz);
+    }
+
     /**
      * Returns the Nashorn's internally used dynamic linker's services object. Note that in code that is processing a
      * linking request, you will normally use the {@code LinkerServices} object passed by whatever top-level linker
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java	Mon Jul 15 15:51:06 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java	Mon Jul 15 16:31:49 2013 +0200
@@ -40,10 +40,10 @@
 final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{
     @Override
     public boolean canLinkType(final Class<?> type) {
-        return canLinkTypeStatic(type);
+        return isReflectionClass(type);
     }
 
-    private static boolean canLinkTypeStatic(final Class<?> type) {
+    private static boolean isReflectionClass(final Class<?> type) {
         if (type == Class.class || ClassLoader.class.isAssignableFrom(type)) {
             return true;
         }
@@ -54,6 +54,19 @@
     @Override
     public GuardedInvocation getGuardedInvocation(final LinkRequest origRequest, final LinkerServices linkerServices)
             throws Exception {
+        checkLinkRequest(origRequest);
+        // let the next linker deal with actual linking
+        return null;
+    }
+
+    static void checkReflectionAccess(Class<?> clazz) {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null && isReflectionClass(clazz)) {
+            checkReflectionPermission(sm);
+        }
+    }
+
+    private static void checkLinkRequest(final LinkRequest origRequest) {
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             final LinkRequest requestWithoutContext = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
@@ -61,23 +74,19 @@
             // allow 'static' access on Class objects representing public classes of non-restricted packages
             if ((self instanceof Class) && Modifier.isPublic(((Class<?>)self).getModifiers())) {
                 final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();
-                final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
-                // check for 'get' on 'static' property
-                switch (operator) {
-                    case "getProp":
-                    case "getMethod": {
-                       if ("static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
-                           Context.checkPackageAccess(((Class)self).getName());
-                           // let bean linker do the actual linking part
-                           return null;
-                       }
+                if(CallSiteDescriptorFactory.tokenizeOperators(desc).contains("getProp")) {
+                    if ("static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
+                        Context.checkPackageAccess(((Class)self).getName());
+                        // If "getProp:static" passes package access, allow access.
+                        return;
                     }
-                    break;
-                } // fall through for all other stuff
+                }
             }
-            sm.checkPermission(new RuntimePermission("nashorn.JavaReflection"));
+            checkReflectionPermission(sm);
         }
-        // let the next linker deal with actual linking
-        return null;
+    }
+
+    private static void checkReflectionPermission(final SecurityManager sm) {
+        sm.checkPermission(new RuntimePermission("nashorn.JavaReflection"));
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8020508.js	Mon Jul 15 16:31:49 2013 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8020508: Enforce reflection check on 
+ * Object.bindProperties(target, source) for beans
+ *
+ * @test
+ * @run
+ */
+
+var x = {}
+try {
+  Object.bindProperties(x, java.util.Vector.class)
+} catch(e) {
+  print(e)
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8020508.js.EXPECTED	Mon Jul 15 16:31:49 2013 +0200
@@ -0,0 +1,1 @@
+java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "nashorn.JavaReflection")