Closed
Bug 1155985
Opened 9 years ago
Closed 9 years ago
EXC_BAD_ACCESS in js`JS_GetClass(JSObject*) [inlined] JSObject::getClass(this=0x0000000104685200) const at jsobj.h:128
Categories
(Core :: js-ctypes, defect)
Tracking
()
RESOLVED
FIXED
mozilla40
People
(Reporter: arai, Assigned: arai)
Details
(Keywords: sec-moderate, Whiteboard: [adv-main39+])
Attachments
(1 file, 1 obsolete file)
2.50 KB,
patch
|
arai
:
review+
lizzard
:
approval-mozilla-beta+
Sylvestre
:
approval-mozilla-esr38-
jocheng
:
approval-mozilla-b2g34+
jocheng
:
approval-mozilla-b2g37+
abillings
:
sec-approval+
|
Details | Diff | Splinter Review |
Derived from bug 891107 happened on 64bit cgc build, on OS X. Configure parameter: (compacting) --enable-optimize --enable-debug --enable-stdcxx-compat --enable-ctypes --disable-shared-js --enable-nspr-build Environment variable: JS_GC_ZEAL=14 Code: for (let i = 0; i < 1000; i++) { let test_struct = ctypes.StructType("test_struct", [{ "x": ctypes.int32_t }, { "bar": ctypes.uint32_t }]); try { new test_struct("foo", "x"); } catch (e) { } } Debug log: (lldb) run ~/Desktop/test.js Process 91361 launched: '/Users/arai/projects/mozilla-central/obj-sm-cgc/dist/bin/js' (x86_64) Process 91361 stopped * thread #1: tid = 0x99497c, 0x0000000100712244 js`JS_GetClass(JSObject*) [inlined] JSObject::getClass(this=0x0000000104685200) const at jsobj.h:128, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x104685200) frame #0: 0x0000000100712244 js`JS_GetClass(JSObject*) [inlined] JSObject::getClass(this=0x0000000104685200) const at jsobj.h:128 125 } 126 127 const js::Class* getClass() const { -> 128 return group_->clasp(); 129 } 130 const JSClass* getJSClass() const { 131 return Jsvalify(getClass()); (lldb) bt * thread #1: tid = 0x99497c, 0x0000000100712244 js`JS_GetClass(JSObject*) [inlined] JSObject::getClass(this=0x0000000104685200) const at jsobj.h:128, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x104685200) * frame #0: 0x0000000100712244 js`JS_GetClass(JSObject*) [inlined] JSObject::getClass(this=0x0000000104685200) const at jsobj.h:128 frame #1: 0x0000000100712244 js`JS_GetClass(JSObject*) [inlined] JSObject::getJSClass(this=0x0000000104685200) const at jsobj.h:131 frame #2: 0x0000000100712244 js`JS_GetClass(obj=0x0000000104685200) + 4 at jsapi.cpp:1769 frame #3: 0x000000010002f16e js`js::ctypes::CType::IsSizeDefined(JSObject*) [inlined] js::ctypes::CType::IsCType(obj=0x0000000104685200) + 5 at CTypes.cpp:3480 frame #4: 0x000000010002f169 js`js::ctypes::CType::IsSizeDefined(obj=0x0000000104685200) + 9 at CTypes.cpp:3609 frame #5: 0x0000000100032ef7 js`js::ctypes::ImplicitConvert(cx=0x0000000103088180, val=<unavailable>, targetType_=<unavailable>, buffer=0x0000000103031198, isArgument=false, freePointer=0x0000000000000000) + 87 at CTypes.cpp:2293 frame #6: 0x000000010003fe5a js`js::ctypes::CType::ConstructData(JSContext*, unsigned int, JS::Value*) + 260 at CTypes.cpp:5177 frame #7: 0x000000010003fd56 js`js::ctypes::CType::ConstructData(cx=0x0000000103088180, argc=2, vp=0x00000001048090b8) + 758 at CTypes.cpp:3249 frame #8: 0x00000001002531ba js`js::CallJSNativeConstructor(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), JS::CallArgs const&) [inlined] js::CallJSNative(native=0x000000010003fa60)(JSContext*, unsigned int, JS::Value*), JS::CallArgs const&) + 160 at jscntxtinlines.h:235 frame #9: 0x000000010025311a js`js::CallJSNativeConstructor(cx=0x0000000103088180, native=0x000000010003fa60, args=0x00007fff5fbfeb60)(JSContext*, unsigned int, JS::Value*), JS::CallArgs const&) + 106 at jscntxtinlines.h:268 frame #10: 0x000000010022c330 js`js::InvokeConstructor(cx=0x0000000103088180, args=CallArgs at 0x00007fff5fbfeb60) + 160 at Interpreter.cpp:821 frame #11: 0x00000001002222e8 js`Interpret(cx=0x0000000103088180, state=0x00007fff5fbff278) + 45864 at Interpreter.cpp:2953 frame #12: 0x0000000100216f8f js`js::RunScript(cx=0x0000000103088180, state=0x00007fff5fbff278) + 335 at Interpreter.cpp:677 frame #13: 0x000000010022d017 js`js::ExecuteKernel(cx=0x0000000103088180, script=<unavailable>, scopeChainArg=0x00000001046742e0, thisv=0x00007fff5fbff388, type=EXECUTE_GLOBAL, evalInFrame=<unavailable>, result=<unavailable>) + 1383 at Interpreter.cpp:902 frame #14: 0x000000010022d36f js`js::Execute(cx=0x0000000103088180, script=<unavailable>, scopeChainArg=<unavailable>, rval=0x0000000000000000) + 431 at Interpreter.cpp:941 frame #15: 0x000000010071a549 js`ExecuteScript(cx=0x0000000103088180, obj=<unavailable>, scriptArg=<unavailable>, rval=0x0000000000000000) + 505 at jsapi.cpp:4133 frame #16: 0x0000000100007f9a js`Process(JSContext*, char const*, bool) [inlined] RunFile(JSContext*, char const*, __sFILE*, bool) + 464 at js.cpp:467 frame #17: 0x0000000100007dca js`Process(cx=0x0000000103088180, filename=<unavailable>, forceTTY=<unavailable>) + 1866 at js.cpp:597 frame #18: 0x0000000100004f9b js`main + 64 at js.cpp:5789 frame #19: 0x0000000100004f5b js`main [inlined] Shell(JSContext*, js::cli::OptionParser*, char**) + 348 at js.cpp:6055 frame #20: 0x0000000100004dff js`main(argc=<unavailable>, argv=<unavailable>, envp=<unavailable>) + 15951 at js.cpp:6376 frame #21: 0x0000000100000fa4 js`start + 52 I guess this is same bug as following, in bug 891107 comment #28: https://treeherder.mozilla.org/logviewer.html#?job_id=9001639&repo=mozilla-inbound
Assignee | ||
Comment 1•9 years ago
|
||
more debug log. (lldb) up frame #2: 0x0000000100712244 js`JS_GetClass(obj=0x0000000104685200) + 4 at jsapi.cpp:1769 1766 JS_PUBLIC_API(const JSClass*) 1767 JS_GetClass(JSObject* obj) 1768 { -> 1769 return obj->getJSClass(); 1770 } 1771 1772 JS_PUBLIC_API(bool) (lldb) up frame #3: 0x000000010002f16e js`js::ctypes::CType::IsSizeDefined(JSObject*) [inlined] js::ctypes::CType::IsCType(obj=0x0000000104685200) + 5 at CTypes.cpp:3480 3477 bool 3478 CType::IsCType(JSObject* obj) 3479 { -> 3480 return JS_GetClass(obj) == &sCTypeClass; 3481 } 3482 3483 bool (lldb) up frame #4: 0x000000010002f169 js`js::ctypes::CType::IsSizeDefined(obj=0x0000000104685200) + 9 at CTypes.cpp:3609 3606 bool 3607 CType::IsSizeDefined(JSObject* obj) 3608 { -> 3609 MOZ_ASSERT(CType::IsCType(obj)); 3610 3611 jsval size = JS_GetReservedSlot(obj, SLOT_SIZE); 3612 (lldb) up frame #5: 0x0000000100032ef7 js`js::ctypes::ImplicitConvert(cx=0x0000000103088180, val=<unavailable>, targetType_=<unavailable>, buffer=0x0000000103031198, isArgument=false, freePointer=0x0000000000000000) + 87 at CTypes.cpp:2293 2290 bool* freePointer) 2291 { 2292 RootedObject targetType(cx, targetType_); -> 2293 MOZ_ASSERT(CType::IsSizeDefined(targetType)); 2294 2295 // First, check if val is either a CData object or a CDataFinalizer 2296 // of type targetType. (lldb) up frame #6: 0x000000010003fe5a js`js::ctypes::CType::ConstructData(JSContext*, unsigned int, JS::Value*) + 260 at CTypes.cpp:5177 5174 for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) { 5175 const FieldInfo& field = r.front().value(); 5176 STATIC_ASSUME(field.mIndex < fields->count()); /* Quantified invariant */ -> 5177 if (!ImplicitConvert(cx, args[field.mIndex], field.mType, 5178 buffer + field.mOffset, 5179 false, nullptr)) 5180 return false;
Assignee | ||
Comment 2•9 years ago
|
||
The object is FieldInfo.mType. I guess it's not traced correctly in StructType::DefineInternal, and the pointer is not updated on move. mType is assigned here: https://dxr.mozilla.org/mozilla-central/source/js/src/ctypes/CTypes.cpp#4966 > FieldInfo info; > info.mType = fieldType; > info.mIndex = i; > info.mOffset = fieldOffset; > ASSERT_OK(fields->add(entryPtr, name, info)); but not traced until `fields` gets stored to reserved slot, am I correct? https://dxr.mozilla.org/mozilla-central/source/js/src/ctypes/CTypes.cpp#4999 > JS_SetReservedSlot(typeObj, SLOT_FIELDINFO, PRIVATE_TO_JSVAL(fields.release())); if so, mType should be assigned just before JS_SetReservedSlot, from fieldRoots array.
Assignee | ||
Comment 3•9 years ago
|
||
Changed to assign mType field just before JS_SetReservedSlot.
Assignee: nobody → arai.unmht
Attachment #8594353 -
Flags: review?(terrence)
Comment 4•9 years ago
|
||
Comment on attachment 8594353 [details] [diff] [review] Set FieldInto::mType just before storing to reserved slot. Review of attachment 8594353 [details] [diff] [review]: ----------------------------------------------------------------- Forwarding review.
Attachment #8594353 -
Flags: review?(terrence) → review?(jcoppeard)
Comment 5•9 years ago
|
||
Comment on attachment 8594353 [details] [diff] [review] Set FieldInto::mType just before storing to reserved slot. Review of attachment 8594353 [details] [diff] [review]: ----------------------------------------------------------------- Thanks for tracking this down! This will fix the issue. I think this code needs some refactoring but I'm not going to ask you to do that here.
Attachment #8594353 -
Flags: review?(jcoppeard) → review+
Comment 6•9 years ago
|
||
Comment on attachment 8594353 [details] [diff] [review] Set FieldInto::mType just before storing to reserved slot. Review of attachment 8594353 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/ctypes/CTypes.cpp @@ +4998,5 @@ > > + int i = 0; > + for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) { > + FieldInfo& field = r.front().value(); > + MOZ_ASSERT(i == field.mIndex); I get a warning here about comparison of integers of different signs. Best change i to be a size_t like FieldInfo::mIndex.
Assignee | ||
Comment 7•9 years ago
|
||
Thank you for reviewing :) Fixed `int i = 0;` to `size_t i = 0;`. [Security approval request comment] > How easily could an exploit be constructed based on the patch? I have no idea how to exploit this. This is basically use-after-free, but currently it occurs only in compacting JS shell build with JS_GC_ZEAL=14 env, this is very different situation about GC than normal build. Normal build has very reduced chance to cause this issue. Also, only chrome-priv code can access js-ctypes on browser. so it might be difficult to exploit it. > Do comments in the patch, the check-in comment, or tests included > in the patch paint a bulls-eye on the security problem? The code comment "Value of fields are not yet traceable here." may describe the problem, but doesn't provide enough information how to exploit it. The test shows how to cause EXC_BAD_ACCESS, but this also doesn't provice enough information for exploit, I guess. > Which older supported branches are affected by this flaw? All supported branches has almost same code in StructType::DefineInternal. > Do you have backports for the affected branches? If not, how different, > hard to create, and risky will they be? Not yet prepared though, it will be easy and low risk. > How likely is this patch to cause regressions; how much testing does it need? Not likely, if it passes all automated tests (especially js-ctypes tests in jstests and mochitest, which are passed locally).
Attachment #8594353 -
Attachment is obsolete: true
Attachment #8594748 -
Flags: sec-approval?
Attachment #8594748 -
Flags: review+
Updated•9 years ago
|
Keywords: sec-moderate
Comment 8•9 years ago
|
||
Comment on attachment 8594748 [details] [diff] [review] Set FieldInto::mType just before storing to reserved slot. r=jonco sec-approval+ though it is a sec-moderate now so technically it doesn't need it.
Attachment #8594748 -
Flags: sec-approval? → sec-approval+
Assignee | ||
Comment 9•9 years ago
|
||
Thank you for approval :) https://hg.mozilla.org/integration/mozilla-inbound/rev/7eee0cdd0feb
Assignee | ||
Comment 10•9 years ago
|
||
backed out for xpcshell-test failure. https://hg.mozilla.org/integration/mozilla-inbound/rev/680258d72d0c might be related to the patches landed at sametime though.
Assignee | ||
Comment 11•9 years ago
|
||
that wasn't this patch's issue https://treeherder.mozilla.org/#/jobs?repo=try&revision=5888cd6bb3f1 landed again. https://hg.mozilla.org/integration/mozilla-inbound/rev/3ba8d6cc53c0
https://hg.mozilla.org/mozilla-central/rev/3ba8d6cc53c0
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla40
Comment 13•9 years ago
|
||
Please nominate this for Fx39. Not sure if we care about this for ESR/B2G.
status-b2g-master:
--- → fixed
status-firefox38:
--- → wontfix
status-firefox38.0.5:
--- → wontfix
status-firefox39:
--- → affected
status-firefox-esr31:
--- → wontfix
status-firefox-esr38:
--- → affected
Flags: needinfo?(arai.unmht)
Assignee | ||
Comment 14•9 years ago
|
||
Comment on attachment 8594748 [details] [diff] [review] Set FieldInto::mType just before storing to reserved slot. r=jonco Approval Request Comment > [Feature/regressing bug #] js-ctypes > [User impact if declined] Possible crash due to use-after-free (the possibility is very low tho). > [Describe test coverage new/current, TreeHerder] newly added js/src/jit-test/tests/ctypes/bug1155985.js covers the case. > [Risks and why] Low. Exactly same patch is landed to firefox 40, and no regression happens until now. > [String/UUID change made/needed] None
Flags: needinfo?(arai.unmht)
Attachment #8594748 -
Flags: approval-mozilla-beta?
Updated•9 years ago
|
status-b2g-v2.0:
--- → wontfix
status-b2g-v2.0M:
--- → wontfix
status-b2g-v2.1:
--- → affected
status-b2g-v2.1S:
--- → affected
status-b2g-v2.2:
--- → affected
Comment 15•9 years ago
|
||
Comment on attachment 8594748 [details] [diff] [review] Set FieldInto::mType just before storing to reserved slot. r=jonco Might as well ask and see what RelMan says about ESR/B2G.
Attachment #8594748 -
Flags: approval-mozilla-esr38?
Attachment #8594748 -
Flags: approval-mozilla-b2g37?
Attachment #8594748 -
Flags: approval-mozilla-b2g34?
Comment 16•9 years ago
|
||
Comment on attachment 8594748 [details] [diff] [review] Set FieldInto::mType just before storing to reserved slot. r=jonco Approving and please NI for any side effect. Thanks
Attachment #8594748 -
Flags: approval-mozilla-b2g37?
Attachment #8594748 -
Flags: approval-mozilla-b2g37+
Attachment #8594748 -
Flags: approval-mozilla-b2g34?
Attachment #8594748 -
Flags: approval-mozilla-b2g34+
Comment 18•9 years ago
|
||
https://hg.mozilla.org/releases/mozilla-b2g34_v2_1/rev/11e5d073db75 https://hg.mozilla.org/releases/mozilla-b2g34_v2_1s/rev/11e5d073db75
Comment 19•9 years ago
|
||
Comment on attachment 8594748 [details] [diff] [review] Set FieldInto::mType just before storing to reserved slot. r=jonco Approved for uplift to beta; adds test coverage and fixes a sec-moderate regression.
Attachment #8594748 -
Flags: approval-mozilla-beta? → approval-mozilla-beta+
Assignee | ||
Comment 20•9 years ago
|
||
Thank you! https://hg.mozilla.org/releases/mozilla-beta/rev/04e07d5a9b00
Comment 21•9 years ago
|
||
Comment on attachment 8594748 [details] [diff] [review] Set FieldInto::mType just before storing to reserved slot. r=jonco sec-moderate (esr expects high or critical security fixes), "possibility [of having the crash] is very low", not taking it.
Attachment #8594748 -
Flags: approval-mozilla-esr38? → approval-mozilla-esr38-
Updated•9 years ago
|
Whiteboard: [adv-main39+]
Updated•9 years ago
|
Group: core-security → core-security-release
Updated•8 years ago
|
Group: core-security-release
You need to log in
before you can comment on or make changes to this bug.
Description
•