Closed
Bug 1157456
Opened 10 years ago
Closed 10 years ago
Compartment mismatch assertion failures with SavedFrame accessors
Categories
(Core :: JavaScript Engine, defect)
Core
JavaScript Engine
Tracking
()
RESOLVED
FIXED
mozilla41
Tracking | Status | |
---|---|---|
firefox41 | --- | fixed |
People
(Reporter: fitzgen, Assigned: fitzgen)
References
(Blocks 1 open bug)
Details
Attachments
(1 file, 1 obsolete file)
6.78 KB,
patch
|
fitzgen
:
review+
|
Details | Diff | Splinter Review |
No description provided.
Assignee | ||
Comment 1•10 years ago
|
||
Attachment #8596199 -
Flags: review?(jorendorff)
Assignee | ||
Comment 2•10 years ago
|
||
Assignee | ||
Comment 3•10 years ago
|
||
Note that the testcase in the patch crashes without the changes made to the SavedFrame accessors. With those changes, everything is A-OK.
Assignee | ||
Comment 4•10 years ago
|
||
Try push is green.
Comment 5•10 years ago
|
||
Comment on attachment 8596199 [details] [diff] [review]
Re-wrap results in SavedFrame accessors
Review of attachment 8596199 [details] [diff] [review]:
-----------------------------------------------------------------
::: js/src/vm/SavedStacks.cpp
@@ +694,5 @@
> THIS_SAVEDFRAME(cx, argc, vp, "(get source)", args, frame);
> RootedString source(cx);
> + if (JS::GetSavedFrameSource(cx, frame, &source) == JS::SavedFrameResult::Ok) {
> + if (!cx->compartment()->wrap(cx, &source))
> + return false;
Unless I'm missing something, we need to do this inside JS::GetSavedFrameSource and change the API to allow for rewrapping errors (I think just OOM). You can just change all the related APIs at the same time and it won't be so bad.
The way that API is designed right now is surprising to me. I might have r-'d that. We have a standard way of reporting errors: set an exception and return false. Errors are hard enough to deal with when people use the standard. Why is that API any different?
Compartment correctness, too, is hard enough without making it harder on ourselves. Rewrapping must happen as close to the source as possible, to prevent this kind of error (and proliferation of this kind of code).
Attachment #8596199 -
Flags: review?(jorendorff) → review-
![]() |
||
Comment 6•10 years ago
|
||
So the problem is that the current setup is kinda messed up.
We have the following things in play:
1) Each SavedFrame has an associated principal for the stackframe itself.
2) Each SavedFrame has an associated compartment which may not match the principal of
the stackframe. This compartment represents whatever code happened to be on the
stack when the stack was captured.
Currently, we use #1 for deciding whether a given caller is allowed to see info about a given stackframe. We use #2 for deciding whether a given caller can touch the stack at all, in the usual way.
The current consumers of the C++ API really mostly want to use the lower of the two privilege sets "where the stack was captured" and "caller". This is implemented via the AutoMaybeEnterFrameCompartment thing in C++ accessors. From that point of view, ensuring that GetSavedFrameParent returns something in the same compartment as the SavedFrame whose parent you're getting is important: it preserves the "where the stack was captured" information.
Now we _could_ return a cross-compartment wrapper there and then just make sure that operations on saved frames always unwrap to the underlying object when trying to do the "where the stack was captured" bits... or something.
Also of note: it doesn't help that the security models are different here for access from JS and access from JS via C++...
One thing that we could consider doing is making the C++ JSAPI use some opaque type (a la JSFunction), not a JSObject. Then there would be no danger of compartment mismatches by the API consumers and the API implementation could make sure it does the right things depending on which compartments things are in. The hard part here is rooting...
Assignee | ||
Comment 7•10 years ago
|
||
(In reply to Jason Orendorff [:jorendorff] from comment #5)
> Comment on attachment 8596199 [details] [diff] [review]
> Re-wrap results in SavedFrame accessors
>
> Review of attachment 8596199 [details] [diff] [review]:
> -----------------------------------------------------------------
>
> ::: js/src/vm/SavedStacks.cpp
> @@ +694,5 @@
> > THIS_SAVEDFRAME(cx, argc, vp, "(get source)", args, frame);
> > RootedString source(cx);
> > + if (JS::GetSavedFrameSource(cx, frame, &source) == JS::SavedFrameResult::Ok) {
> > + if (!cx->compartment()->wrap(cx, &source))
> > + return false;
>
> Unless I'm missing something, we need to do this inside
> JS::GetSavedFrameSource and change the API to allow for rewrapping errors (I
> think just OOM). You can just change all the related APIs at the same time
> and it won't be so bad.
IIRC, this will break DOM use of the SavedFrame JSAPI.
> The way that API is designed right now is surprising to me. I might have
> r-'d that. We have a standard way of reporting errors: set an exception and
> return false. Errors are hard enough to deal with when people use the
> standard. Why is that API any different?
The thing is, access denied isn't an error and you still get the default value.
> Compartment correctness, too, is hard enough without making it harder on
> ourselves. Rewrapping must happen as close to the source as possible, to
> prevent this kind of error (and proliferation of this kind of code).
Agreed, but as mentioned above, IIRC this would break DOM usage of SavedFrames.
Assignee | ||
Comment 8•10 years ago
|
||
(In reply to Not doing reviews right now from comment #6)
> One thing that we could consider doing is making the C++ JSAPI use some
> opaque type (a la JSFunction), not a JSObject. Then there would be no
> danger of compartment mismatches by the API consumers and the API
> implementation could make sure it does the right things depending on which
> compartments things are in. The hard part here is rooting...
What if we split SavedFrame into SavedFrame (rootable C++/JSAPI thing) and SavedFrameObject (JSObject subclass with a private pointer to a SavedFrame)? Additionally, what if wrapping a SavedFrameObject just created a new SavedFrameObject in the target compartment and copied the SavedFrame private pointer?
![]() |
||
Comment 9•10 years ago
|
||
That seems reasonable, conceptually.
Assignee | ||
Comment 11•10 years ago
|
||
Jason, I don't have the cycles for a proper re-architecting of the SavedFrame internals right now. However, since this issue has come up twice now, would you be alright with going ahead with the original patch so we can stop getting the assertion failures, and file a follow up for the Proper Fix?
Flags: needinfo?(jorendorff)
Comment 12•10 years ago
|
||
Comment on attachment 8596199 [details] [diff] [review]
Re-wrap results in SavedFrame accessors
Review of attachment 8596199 [details] [diff] [review]:
-----------------------------------------------------------------
r=me as there's no real alternative at present.
Attachment #8596199 -
Flags: review- → review+
Assignee | ||
Comment 13•10 years ago
|
||
Attachment #8596199 -
Attachment is obsolete: true
Attachment #8623741 -
Flags: review+
Assignee | ||
Comment 14•10 years ago
|
||
Rebased and here is a new try push: https://treeherder.mozilla.org/#/jobs?repo=try&revision=89a3c95fff43
Flags: needinfo?(jorendorff)
Comment 15•10 years ago
|
||
Comment 16•10 years ago
|
||
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
status-firefox41:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla41
You need to log in
before you can comment on or make changes to this bug.
Description
•