Bug 1082450 - Deny access to cross-origin callables on COWs. r=gabor

This commit is contained in:
Bobby Holley 2014-10-15 15:05:10 +02:00
parent 68628555ce
commit 620f04cfb5
4 changed files with 17 additions and 58 deletions

View File

@ -39,31 +39,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=760109
// refactoring has made it possible to do the right thing here.
is(typeof chromeObject.constructor, "undefined", "Object constructor does what we expect");
ok(chromeArray.constructor === Array, "Array constructor remapped properly");
// We should be able to .forEach on the Array.
var concat = '';
chromeArray.forEach(function(val) { concat += val; });
is(concat, 'abz', "Should be able to .forEach COW-ed Array");
// Try other Array operations.
is(chromeArray.indexOf('b'), 1, "indexOf works correctly");
is(chromeArray.join(''), concat, "join works correctly");
is(chromeArray.slice(1).join(''), 'bz', "slice works correctly");
is(chromeArray.length, 3, "Able to check array length");
// Try some operations that modify the array.
is(chromeArray.pop(), 'z', "Able to call pop");
is(chromeArray.push('z'), 3, "Able to call push");
chromeArray.reverse();
is(chromeArray.join(''), 'zba', "Able to call reverse");
chromeArray.sort();
is(chromeArray.join(''), 'abz', "Able to call sort");
// We should be able to .hasOwnProperty on the Object, and have
// it filter the objects we can see.
ok(chromeObject.hasOwnProperty('foo'), "Should see r property");
ok(!chromeObject.hasOwnProperty('bar'), "Shouldn't see non-exposed property");
ok(chromeObject.hasOwnProperty('baz'), "Should see rw property");
}
// We use a constructor to create the test object so that there's an

View File

@ -268,31 +268,6 @@ function COWTests() {
} catch (e) {
todo(false, "COWed functions should not raise " + e);
}
try {
var objWithFunc = {__exposedProps__: {foo: 'r'},
foo: function foo() { return 5; }};
is(getCOW((objWithFunc)).foo(), 5,
"Readable function exposed props should be callable");
} catch (e) {
ok(false, "Readable function exposed props should be callable" + e);
}
// Alien objects
try {
is(alienObject.funProp(1), 2,
"COWs wrapping objects from different principals should work");
} catch (e) {
ok(false, "COWs wrapping objs from different principals " +
"shouldn't throw " + e);
}
try {
is(alienObject.funProp(1), 2,
"COWs wrapping objs from different principals should work twice");
} catch (e) {
ok(false, "COWs wrapping objs from different principals " +
"shouldn't throw on second access but not first: " + e);
}
}
// Decompile the COW test suite, re-evaluate it in the sandbox and execute it.

View File

@ -6,18 +6,18 @@
const Cu = Components.utils;
// Use a COW to expose a function from a standard prototype, and make sure it's
// still remapped.
// Use a COW to expose a function from a standard prototype, and make we deny
// access to it.
function run_test()
{
var sb = Cu.Sandbox("http://www.example.com");
sb.obj = { foo: 42, __exposedProps__: { hasOwnProperty: 'r' } };
do_check_eq(Cu.evalInSandbox('typeof obj.foo', sb), 'undefined', "COW works as expected");
do_check_true(Cu.evalInSandbox('obj.hasOwnProperty === Object.prototype.hasOwnProperty', sb),
"Remapping happens even when the property is explicitly exposed");
// NB: We used to test for the following, but such behavior became very
// difficult to implement in a recent refactor. We're moving away from this
// API anyway, so we decided to explicitly drop support for this.
// do_check_eq(Cu.evalInSandbox('Object.prototype.bar = 10; obj.bar', sb), 10);
try {
Cu.evalInSandbox('obj.hasOwnProperty', sb);
do_check_true(false);
} catch (e) {
do_check_true(/privileged or cross-origin callable/i.test(e));
}
}

View File

@ -353,6 +353,15 @@ ExposedPropertiesOnly::check(JSContext *cx, HandleObject wrapper, HandleId id, W
return false;
}
// Reject privileged or cross-origin callables.
if (desc.value().isObject()) {
RootedObject maybeCallable(cx, js::UncheckedUnwrap(&desc.value().toObject()));
if (JS::IsCallable(maybeCallable) && !AccessCheck::subsumes(wrapper, maybeCallable)) {
EnterAndThrow(cx, wrapper, "Exposing privileged or cross-origin callable is prohibited");
return false;
}
}
return true;
}