Bug 866823 - Don't create waivers in WaiveXrayAndWrap if the caller has no business waiving. r=gabor, r=mrbkap, a=akeybl
authorBobby Holley <bobbyholley@gmail.com>
Wed, 15 May 2013 21:13:12 -0700
changeset 142673 f0ab73e4906ab1b91c5b4ad7e1c086ec404867e9
parent 142672 fd4da843d914b3c9d413a78106c508569cfa670f
child 142674 08ddc20e3a7162a8beeab9c264ee3ef1d5ec216e
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgabor, mrbkap, akeybl
bugs866823
milestone23.0a2
Bug 866823 - Don't create waivers in WaiveXrayAndWrap if the caller has no business waiving. r=gabor, r=mrbkap, a=akeybl
js/xpconnect/wrappers/WrapperFactory.cpp
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -542,17 +542,27 @@ WrapperFactory::WaiveXrayAndWrap(JSConte
 
     JSObject *obj = js::UncheckedUnwrap(JSVAL_TO_OBJECT(*vp));
     MOZ_ASSERT(!js::IsInnerObject(obj));
     if (js::IsObjectInContextCompartment(obj, cx)) {
         *vp = OBJECT_TO_JSVAL(obj);
         return true;
     }
 
-    obj = WaiveXray(cx, obj);
+    // Even though waivers have no effect on access by scopes that don't subsume
+    // the underlying object, good defense-in-depth dictates that we should avoid
+    // handing out waivers to callers that can't use them. The transitive waiving
+    // machinery unconditionally calls WaiveXrayAndWrap on return values from
+    // waived functions, even though the return value might be not be same-origin
+    // with the function. So if we find ourselves trying to create a waiver for
+    // |cx|, we should check whether the caller has any business with waivers
+    // to things in |obj|'s compartment.
+    JSCompartment *target = js::GetContextCompartment(cx);
+    JSCompartment *origin = js::GetObjectCompartment(obj);
+    obj = AccessCheck::subsumes(target, origin) ? WaiveXray(cx, obj) : obj;
     if (!obj)
         return false;
 
     *vp = OBJECT_TO_JSVAL(obj);
     return JS_WrapValue(cx, vp);
 }
 
 JSObject *