nsTextEditorState runs script during frame destruction because DelegatedQueryInterface calls AutoEntryScript for builtinclass interfaces
Categories
(Core :: XPConnect, defect, P2)
Tracking
()
People
(Reporter: bzbarsky, Assigned: bzbarsky)
Details
(Keywords: sec-moderate, sec-want, Whiteboard: [post-critsmash-triage][adv-main74+r])
Attachments
(2 files)
|
3.06 KB,
patch
|
Details | Diff | Splinter Review | |
|
47 bytes,
text/x-phabricator-request
|
Details | Review |
| Assignee | ||
Comment 1•10 years ago
|
||
Comment 2•10 years ago
|
||
| Assignee | ||
Comment 3•10 years ago
|
||
Updated•10 years ago
|
Updated•10 years ago
|
Updated•10 years ago
|
Comment 5•10 years ago
|
||
Comment 6•10 years ago
|
||
| Assignee | ||
Comment 7•10 years ago
|
||
Comment 9•10 years ago
|
||
| Assignee | ||
Comment 10•10 years ago
|
||
| Assignee | ||
Comment 11•10 years ago
|
||
Comment 12•10 years ago
|
||
| Assignee | ||
Comment 13•10 years ago
|
||
| Assignee | ||
Comment 14•10 years ago
|
||
Updated•9 years ago
|
Updated•7 years ago
|
Updated•6 years ago
|
Comment 15•6 years ago
|
||
Hi Masayuki, as you did several clean-ups and refactoring in the past months, can you help evaluate if this is valid? Thank you.
Looks like that the issue is gone because:
nsIControllerContextis now abuiltinclassso that it cannot be implemented by JS.nsIControllerContextis QIed fromnsIControllerwhich is notbuiltinclass. However, that comes from controllers of<input>element or<textarea>element and both<input>element's controllers and<textarea>element's controllers arensBaseCommandControllerwhich is implemented by C++.- Finally,
TextControlState::UnbindFromFrame()has its ownkungFuDeathGripso that nobody is gone even if it runs script.
| Assignee | ||
Comment 17•6 years ago
|
||
I am still hitting asserts from bug 1181918 in a debug build with this stack:
#17 0x00007f8c9c0dadcb in mozilla::dom::AutoEntryScript::AutoEntryScript(nsIGlobalObject*, char const*, bool)
(this=0x7ffec902ca50, aGlobalObject=0x7f8c81d06e80, aReason=0x7f8c934075a2 "XPCWrappedJS QueryInterface", aIsMainThread=true)
at /home/bzbarsky/mozilla/dom-work/mozilla/dom/script/ScriptSettings.cpp:585
#18 0x00007f8c996ffc8c in nsXPCWrappedJS::DelegatedQueryInterface(nsID const&, void**)
(this=0x7f8c76ed8f20, aIID=..., aInstancePtr=0x7ffec902cb40)
at /home/bzbarsky/mozilla/dom-work/mozilla/js/xpconnect/src/XPCWrappedJSClass.cpp:332
#19 0x00007f8c9a11a05e in nsCOMPtr<nsIControllerContext>::assign_from_qi<nsIController>(nsQueryInterface<nsIController>, nsID const&)
(this=0x7ffec902cb88, aQI=..., aIID=...) at ../../dist/include/nsCOMPtr.h:1157
#20 0x00007f8c9b5b3ae6 in mozilla::TextControlState::UnbindFromFrame(nsTextControlFrame*) (this=0x7f8c772fec80, aFrame=<optimized out>)
at /home/bzbarsky/mozilla/dom-work/mozilla/dom/html/TextControlState.cpp:2490
#21 0x00007f8c9c7559a8 in nsTextControlFrame::DestroyFrom(nsIFrame*, mozilla::layout::PostFrameDestroyData&)
(this=0x7f8c7bc43ab8, aDestructRoot=0x7f8c7bc67690, aPostDestroyData=...)
at /home/bzbarsky/mozilla/dom-work/mozilla/layout/forms/nsTextControlFrame.cpp:145
In this case, in frame 20, controller is JS-implemented. The JS-implemented thing was passed to nsXULControllers::InsertControllerAt from script, with this JS stack:
0 _initCopyCutController() ["resource:///modules/UrlbarInput.jsm":1603:32]
this = [object Object]
1 UrlbarInput(options = "[object Object]") ["resource:///modules/UrlbarInput.jsm":223:9]
this = [object Object]
2 anonymous() ["chrome://browser/content/browser.js":331:9]
3 get() ["resource://gre/modules/XPCOMUtils.jsm":129:50]
this = [object ChromeWindow]
4 _setURLBarPlaceholder(name = ""Google"") ["chrome://browser/content/browser.js":4341:4]
this = [object Object]
5 initPlaceHolder() ["chrome://browser/content/browser.js":4238:11]
this = [object Object]
6 onDOMContentLoaded("[object Event]") ["chrome://browser/content/browser.js":1770:18]
this = [object Object]
7 onDOMContentLoaded("[object Event]") ["self-hosted":876:16]
this = [object ChromeWindow]
Finally, TextControlState::UnbindFromFrame() has its own kungFuDeathGrip so that nobody is gone even if it runs script.
The point is, this code is running while we are iterating over the frame tree. If that script that gets run (in this case the QI method for the JS-implemented thing) tried to ask for layout information, we would likely end up with very bad things happening.
Now we happen to control that script, so this is sort of OK in that it's not an imminent security bug. But it does prevent us landing the assertion in bug 1181918 (amongst other things that also prevent it).
Assuming we do need the scripted controllers here, maybe one option would be to QI the controller to nsIXPConnectWrappedJS (which is guaranteed to not run script) and if that succeeds avoid the QI to nsIControllerContext (which we know will fail, since that interface is builtinclass).
Alternately, maybe we could fix nsXPCWrappedJS::DelegatedQueryInterface to just fail out for IDs of builtinclass interfaces before trying to do anything with script? So just call nsXPCWrappedJS::GetInterfaceInfo at the beginning of that function, where we do the check for nsWrapperCache right now (which we could probably remove, then). Andrew, thoughts on that?
In theory an XPCWrappedJS could implement QI to a builtinclass interface via aggregation or something (as in, return an actual built-in object that knows to go back to the JS object for some other IID). In practice, I really doubt we do that or want to support it...
Comment 18•6 years ago
|
||
That sounds reasonable. It looks like nsXPCWrappedJS::CallQueryInterfaceOnJSObject, which DelegatedQueryInterface eventually calls, does that. Note the weird issue that nsISupports is builtinclass, but it is okay to QI to it. I'm not sure about any of the other special cases in this method. It does seem like conceptually if we were lazier about doing the AES it would work out, due to the shortcut in CallQueryInterfaceOnJSObject, but it looks like actually being lazy about all of that would be horrible.
(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #17)
I am still hitting asserts from bug 1181918 in a debug build with this stack:
I cannot access the bug, could you cc me? Or I just want to know how to reproduce it.
#17 0x00007f8c9c0dadcb in mozilla::dom::AutoEntryScript::AutoEntryScript(nsIGlobalObject*, char const*, bool) (this=0x7ffec902ca50, aGlobalObject=0x7f8c81d06e80, aReason=0x7f8c934075a2 "XPCWrappedJS QueryInterface", aIsMainThread=true) at /home/bzbarsky/mozilla/dom-work/mozilla/dom/script/ScriptSettings.cpp:585 #18 0x00007f8c996ffc8c in nsXPCWrappedJS::DelegatedQueryInterface(nsID const&, void**) (this=0x7f8c76ed8f20, aIID=..., aInstancePtr=0x7ffec902cb40) at /home/bzbarsky/mozilla/dom-work/mozilla/js/xpconnect/src/XPCWrappedJSClass.cpp:332 #19 0x00007f8c9a11a05e in nsCOMPtr<nsIControllerContext>::assign_from_qi<nsIController>(nsQueryInterface<nsIController>, nsID const&) (this=0x7ffec902cb88, aQI=..., aIID=...) at ../../dist/include/nsCOMPtr.h:1157 #20 0x00007f8c9b5b3ae6 in mozilla::TextControlState::UnbindFromFrame(nsTextControlFrame*) (this=0x7f8c772fec80, aFrame=<optimized out>) at /home/bzbarsky/mozilla/dom-work/mozilla/dom/html/TextControlState.cpp:2490 #21 0x00007f8c9c7559a8 in nsTextControlFrame::DestroyFrom(nsIFrame*, mozilla::layout::PostFrameDestroyData&) (this=0x7f8c7bc43ab8, aDestructRoot=0x7f8c7bc67690, aPostDestroyData=...) at /home/bzbarsky/mozilla/dom-work/mozilla/layout/forms/nsTextControlFrame.cpp:145In this case, in frame 20,
controlleris JS-implemented. The JS-implemented thing was passed tonsXULControllers::InsertControllerAtfrom script, with this JS stack:
Wow, I didn't know they are exposed:
- https://searchfox.org/mozilla-central/rev/f98dad153b59a985efd4505912588d4651033395/dom/webidl/HTMLInputElement.webidl#153
- https://searchfox.org/mozilla-central/rev/f98dad153b59a985efd4505912588d4651033395/dom/webidl/HTMLTextAreaElement.webidl#88
Assuming we do need the scripted controllers here, maybe one option would be to QI the controller to
nsIXPConnectWrappedJS(which is guaranteed to not run script) and if that succeeds avoid the QI tonsIControllerContext(which we know will fail, since that interface is builtinclass).
Well, I'm afraid about performance regression for adding QI twice per controller...
| Assignee | ||
Comment 20•6 years ago
|
||
I cannot access the bug, could you cc me?
Done.
Well, I'm afraid about performance regression for adding QI twice per controller...
Yeah. I'm going to try the XPConnect-side fix here.
| Assignee | ||
Comment 21•6 years ago
|
||
It looks like
nsXPCWrappedJS::CallQueryInterfaceOnJSObject, whichDelegatedQueryInterfaceeventually calls, does that.
Oh! Indeed. It just does it after possibly running script via the JS_GetPropertyById call to get the QueryInterface function.... Alright, then.
| Assignee | ||
Comment 22•6 years ago
|
||
For builtinclass interfaces, or ones not declared in IDL, we don't call out
into scripted QueryInterface anyway, so we can return earlier, before we ever
set up the AutoEntryScript.
| Assignee | ||
Comment 23•6 years ago
|
||
Comment on attachment 9122959 [details]
Bug 1181957. Don't set up an AutoEntryScript if we're not planning to call script in nsXPCWrappedJS::DelegatedQueryInterface. r=mccr8
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Not easily at all. In fact, I'm fairly sure this is not exploitable. It's just preventing us from adding an assert that would catch other cases that might be. Assuming those cases exist
- Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No
- Which older supported branches are affected by this flaw?: All of them
- If not all supported branches, which bug introduced the flaw?: None
- Do you have backports for the affected branches?: Yes
- If not, how different, hard to create, and risky will they be?: For what it's worth, I don't think this needs backporting to branches.
- How likely is this patch to cause regressions; how much testing does it need?: I think this is quite safe.
Comment 24•6 years ago
|
||
You don't need sec-approval for sec-moderate bugs.
| Assignee | ||
Updated•6 years ago
|
Comment 25•6 years ago
|
||
This turned into more of an XPConnect issue than an Editor issue, so I'll move it over there.
Updated•6 years ago
|
Comment 26•6 years ago
|
||
https://hg.mozilla.org/integration/autoland/rev/60c6637391e7dffa4bbe68f660eb9125ad1c8978
https://hg.mozilla.org/mozilla-central/rev/60c6637391e7
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Updated•5 years ago
|
Description
•