changeset 4447:12dae20ea9b5

7046823: vulnerability with rhino javascript engine Reviewed-by: hawtin
author sundar
date Thu, 16 Jun 2011 21:36:23 +0530
parents 0456c855b396
children 69e973991866
files src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java src/share/classes/com/sun/script/javascript/RhinoTopLevel.java
diffstat 2 files changed, 58 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java	Wed Jun 15 14:49:25 2011 +0100
+++ b/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java	Thu Jun 16 21:36:23 2011 +0530
@@ -29,6 +29,7 @@
 import sun.org.mozilla.javascript.internal.*;
 import java.lang.reflect.Method;
 import java.io.*;
+import java.security.*;
 import java.util.*;
 
 
@@ -45,6 +46,8 @@
 
     private static final boolean DEBUG = false;
 
+    private AccessControlContext accCtxt;
+
     /* Scope where standard JavaScript objects and our
      * extensions to it are stored. Note that these are not
      * user defined engine level global variables. These are
@@ -63,8 +66,13 @@
 
     private static final int languageVersion = getLanguageVersion();
     private static final int optimizationLevel = getOptimizationLevel();
+
     static {
         ContextFactory.initGlobal(new ContextFactory() {
+            /**
+             * Create new Context instance to be associated with the current thread.
+             */
+            @Override
             protected Context makeContext() {
                 Context cx = super.makeContext();
                 cx.setLanguageVersion(languageVersion);
@@ -73,6 +81,40 @@
                 cx.setWrapFactory(RhinoWrapFactory.getInstance());
                 return cx;
             }
+
+            /**
+             * Execute top call to script or function. When the runtime is about to
+             * execute a script or function that will create the first stack frame
+             * with scriptable code, it calls this method to perform the real call.
+             * In this way execution of any script happens inside this function.
+             */
+            @Override
+            protected Object doTopCall(final Callable callable,
+                               final Context cx, final Scriptable scope,
+                               final Scriptable thisObj, final Object[] args) {
+                AccessControlContext accCtxt = null;
+                Scriptable global = ScriptableObject.getTopLevelScope(scope);
+                Scriptable globalProto = global.getPrototype();
+                if (globalProto instanceof RhinoTopLevel) {
+                    accCtxt = ((RhinoTopLevel)globalProto).getAccessContext();
+                }
+
+                if (accCtxt != null) {
+                    return AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                        public Object run() {
+                            return superDoTopCall(callable, cx, scope, thisObj, args);
+                        }
+                    }, accCtxt);
+                } else {
+                    return superDoTopCall(callable, cx, scope, thisObj, args);
+                }
+            }
+
+            private  Object superDoTopCall(Callable callable,
+                               Context cx, Scriptable scope,
+                               Scriptable thisObj, Object[] args) {
+                return super.doTopCall(callable, cx, scope, thisObj, args);
+            }
         });
     }
 
@@ -103,6 +145,9 @@
      * Creates a new instance of RhinoScriptEngine
      */
     public RhinoScriptEngine() {
+        if (System.getSecurityManager() != null) {
+            accCtxt = AccessController.getContext();
+        }
 
         Context cx = enterContext();
         try {
@@ -360,6 +405,10 @@
         factory = fac;
     }
 
+    AccessControlContext getAccessContext() {
+        return accCtxt;
+    }
+
     Object[] wrapArguments(Object[] args) {
         if (args == null) {
             return Context.emptyArgs;
--- a/src/share/classes/com/sun/script/javascript/RhinoTopLevel.java	Wed Jun 15 14:49:25 2011 +0100
+++ b/src/share/classes/com/sun/script/javascript/RhinoTopLevel.java	Thu Jun 16 21:36:23 2011 +0530
@@ -27,6 +27,7 @@
 
 import sun.org.mozilla.javascript.internal.*;
 import javax.script.*;
+import java.security.AccessControlContext;
 
 /**
  * This class serves as top level scope for Rhino. This class adds
@@ -38,10 +39,12 @@
  */
 public final class RhinoTopLevel extends ImporterTopLevel {
     RhinoTopLevel(Context cx, RhinoScriptEngine engine) {
-        super(cx);
+        // second boolean parameter to super constructor tells whether
+        // to seal standard JavaScript objects or not. If security manager
+        // is present, we seal the standard objects.
+        super(cx, System.getSecurityManager() != null);
         this.engine = engine;
 
-
         // initialize JSAdapter lazily. Reduces footprint & startup time.
         new LazilyLoadedCtor(this, "JSAdapter",
                 "com.sun.script.javascript.JSAdapter",
@@ -152,5 +155,9 @@
         return engine;
     }
 
+    AccessControlContext getAccessContext() {
+        return engine.getAccessContext();
+    }
+
     private RhinoScriptEngine engine;
 }