Closed Bug 820862 Opened 12 years ago Closed 12 years ago

JSJitInfo needs to say what sort of function it is

Categories

(Core :: DOM: Core & HTML, defect)

x86
macOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla20
Tracking Status
firefox17 --- unaffected
firefox18 + fixed
firefox19 + fixed
firefox20 + fixed
firefox-esr10 --- unaffected
firefox-esr17 --- unaffected
b2g18 --- fixed

People

(Reporter: bzbarsky, Assigned: bzbarsky)

Details

(Keywords: sec-critical, Whiteboard: [adv-main18-])

Attachments

(4 files, 1 obsolete file)

JSJitInfo has a JSJitPropertyOp op in it, which has this signature:

typedef bool
(* JSJitPropertyOp)(JSContext *cx, JSHandleObject thisObj,
                    void *specializedThis, JS::Value *vp);

But for methods we reinterpret it as a JSJitMethodOp, which has this signature:

typedef bool
(* JSJitMethodOp)(JSContext *cx, JSHandleObject thisObj,
                  void *specializedThis, unsigned argc, JS::Value *vp);

The attached testcase causes us to erroneously treat a JSJitPropertyOp as a JSJitMethodOp, and in particular allows the caller to control the value of the "vp" pointer passed to the property op.  Just so you can avoid loading it and crashing, it looks like this:

    var xhr = new XMLHttpRequest();
    var desc = Object.getOwnPropertyDescriptor(xhr.__proto__, "readyState");
    xhr.__proto__.foopy = desc.get;
    for (var i = 0; i < 1000000; ++i)
      xhr.foopy(1,2,3,4,5,6,7,8);

This invokes get_readyState with the fourth argument set to 8.

Marking security-sensitive, since this seems to allow an attacker to write near-arbitrary values (by picking your getter properly) to near-arbitrary memory locations.

Furthermore, even though the signature for getters and setters is compatible the meaning of "vp" is not.  For a getter it's a pointer to uninitialized stack memory while for a setter it's a pointer to the value being set.  So we should really distinguish between the two kinds of JSJitPropertyOp too; otherwise it might be possible to read data off the stack, which is bad.  It would probably also be possible to trigger writes to stuff that shouldn't be written to (by treating a setter as a getter).

Anyway, patch coming up.
Attached file Testcase
(In reply to Boris Zbarsky (:bz) from comment #0)

> Marking security-sensitive, since this seems to allow an attacker to write
> near-arbitrary values (by picking your getter properly) to near-arbitrary
> memory locations.

sec-critical?
Attachment #691373 - Flags: review?(jdemooij)
> sec-critical?

I believe so, yes.
Oh, and this is ion-only, so esr17 not affected.  But 18 and up are affected.
Comment on attachment 691373 [details] [diff] [review]
JSJitInfo should say what sort of function it is.

Review of attachment 691373 [details] [diff] [review]:
-----------------------------------------------------------------

Great catch.

::: js/src/ion/IonBuilder.cpp
@@ +6303,5 @@
>      if (singleton->isFunction()) {
>          RootedFunction singletonFunc(cx, singleton->toFunction());
>          if (TestAreKnownDOMTypes(cx, unaryTypes.inTypes) &&
> +            TestShouldDOMCall(cx, unaryTypes.inTypes, singletonFunc,
> +                              JSJitInfo::eMethod))

Nit: fits on one line (SpiderMonkey limit is 99 characters for code, 80 for comments).

@@ +6370,5 @@
>      MDefinition *obj = current->pop();
>      RootedFunction getter(cx, commonGetter);
>  
> +    if (isDOM && TestShouldDOMCall(cx, unaryTypes.inTypes, getter,
> +                                   JSJitInfo::eGetter)) {

Same here.

::: js/src/jsfriendapi.h
@@ +1424,5 @@
>                    void *specializedThis, unsigned argc, JS::Value *vp);
>  
>  struct JSJitInfo {
> +    enum OpType {
> +        eGetter,

Nit: SpiderMonkey style is either GETTER or Getter (and it's what other enums in this file seem to use).
Attachment #691373 - Flags: review?(jdemooij) → review+
Attachment #691373 - Attachment is obsolete: true
Whiteboard: [need review] → [need approval]
Comment on attachment 691417 [details] [diff] [review]
Updated to review comments

[Security approval request comment]
How easily can the security issue be deduced from the patch?  Probably fairly
   easily for anyone familiar with ECMAScript.  They'd have to find the cases
   we use this functionality in, but other than that...

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? 18, 19.  No shipping
   browsers yet.

If not all supported branches, which bug introduced the flaw? Bug 747288.

Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be?  I have backports for Aurora and Beta.  Will
   attach them in a sec.

How likely is this patch to cause regressions; how much testing does it need? 
   Extremely unlikely to cause regressions.
Attachment #691417 - Flags: sec-approval?
Attached patch Aurora 19 patchSplinter Review
Attached patch Beta 18 patchSplinter Review
Comment on attachment 691426 [details] [diff] [review]
Aurora 19 patch

[Approval Request Comment]
Bug caused by (feature/regressing bug #): Bug 747288
User impact if declined: Security problem.
Testing completed (on m-c, etc.): Passes attached testcase, local performance
   tests.
Risk to taking this patch (and alternatives if risky): Extremely low.
String or UUID changes made by this patch: None.
Attachment #691426 - Flags: approval-mozilla-aurora?
Attachment #691427 - Flags: approval-mozilla-beta?
Comment on attachment 691417 [details] [diff] [review]
Updated to review comments

sec-approval+. Let's get this in for 18 and 19 if possible to avoid shipping this issue.
Attachment #691417 - Flags: sec-approval? → sec-approval+
Attachment #691426 - Flags: approval-mozilla-aurora? → approval-mozilla-aurora+
Attachment #691427 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Note: I did NOT check in the test.  Should I?
Flags: needinfo?(abillings)
Flags: in-testsuite?
Pretty sure you meant to post a beta link there.
https://hg.mozilla.org/releases/mozilla-beta/rev/865b57171950

Also, *please* don't land things on aurora/beta until they're safely on m-c. (I type this as I see that your push got backed out of inbound).
This didn't get backed out of inbound, and it would have been _very_ odd for it to have failed there.

On the other hand, we do want to get this on branches ASAP so we get it out to users....
Yes, I'm aware that it was the other patch in your push that got backed out. But it did illustrate the point that landing on inbound and across branches can potentially lead to messy backouts. With the exception of nightly testers, getting this on Aurora/Beta one day earlier isn't going to make a significant difference as to when users get it.
https://hg.mozilla.org/mozilla-central/rev/55b2d38ac36c

(I'm with Ryan on this one. Please make sure the inbound/m-c run is green before pushing to branches, just in case.)
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
(In reply to Boris Zbarsky (:bz) from comment #14)
> Note: I did NOT check in the test.  Should I?

Only if it makes it onto 18 and 19, otherwise, we expose those releases.
Flags: needinfo?(abillings)
This is already landed on 18 and 19.  Should I wait for the next beta or something, or just land the test everywhere?
Flags: needinfo?(abillings)
Release management, do you see a reason not to land the test right now?
Flags: needinfo?(abillings)
Whiteboard: [adv-main18-]
Group: core-security
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: