Bug 106608 - [v8] Security feature: JavaScript Bindings hardening
Summary: [v8] Security feature: JavaScript Bindings hardening
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore JavaScript (show other bugs)
Version: 528+ (Nightly build)
Hardware: All All
: P3 Normal
Assignee: Thomas Sepez
URL:
Keywords:
Depends on: 105642
Blocks:
  Show dependency treegraph
 
Reported: 2013-01-10 14:52 PST by Thomas Sepez
Modified: 2013-02-21 18:45 PST (History)
27 users (show)

See Also:


Attachments
Patch for discussion only. (31.34 KB, patch)
2013-01-11 13:34 PST, Thomas Sepez
no flags Details | Formatted Diff | Diff
Full perf test results (251.20 KB, text/html)
2013-01-14 13:26 PST, Thomas Sepez
no flags Details
Patch. (32.87 KB, patch)
2013-01-14 14:12 PST, Thomas Sepez
no flags Details | Formatted Diff | Diff
Patch, fix custom .cpp file. (33.00 KB, patch)
2013-01-14 14:38 PST, Thomas Sepez
no flags Details | Formatted Diff | Diff
Patch, add to features.gypi (initially disabled). (33.47 KB, patch)
2013-01-14 15:24 PST, Thomas Sepez
no flags Details | Formatted Diff | Diff
Patch, fix casting. (33.52 KB, patch)
2013-01-14 16:22 PST, Thomas Sepez
no flags Details | Formatted Diff | Diff
Patch, windows support attempt. (35.03 KB, patch)
2013-01-15 13:11 PST, Thomas Sepez
no flags Details | Formatted Diff | Diff
Patch, avoid merge conflicts, initial setting is "disable" (34.88 KB, patch)
2013-01-24 16:03 PST, Thomas Sepez
no flags Details | Formatted Diff | Diff
Patch, check at wrapper creation time. (20.63 KB, patch)
2013-01-28 12:24 PST, Thomas Sepez
no flags Details | Formatted Diff | Diff
Patch, specify exceptions in IDL files. (93.94 KB, patch)
2013-01-28 17:50 PST, Thomas Sepez
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Sepez 2013-01-10 14:52:03 PST
This is a tracking bug for some of the Bindings hardening work we are contemplating for the V8 bindings used by Chromium.

Recent full Chromium exploits at some point relied upon aliasing two JavaScript wrapper objects to the same underlying C++ object, and invoking methods from the unrelated class on that object. Run-time type checking would prevent this from happening and would stop the exploits. However, run-time type checks are too expensive in terms of cycles to perform everywhere throughout the code, but the JS Bindings code provides a clean API between layers at where these checks could be applied at reduced cost.
Comment 1 Kentaro Hara 2013-01-11 11:58:33 PST
I would recommend you discuss with the V8 team first. They were talking about a couple of concerns about the design.
Comment 2 Thomas Sepez 2013-01-11 13:34:09 PST
Created attachment 182407 [details]
Patch for discussion only.

This is the minimal patch in some sense in that it doesn't disturb webkit classes (to get better coverage) or V8 APIs (to get better performance).
I'm seeing about a 4% hit on Dromaeo/dom-traverse.html.  It would be good to get other data points from folks used to benchmarking these.
We can drop this to about 2% hit if the two calls to the V8 API in the toNativeChecked() method are combined through a new API returning two items at once.
Comment 3 Adam Barth 2013-01-11 13:54:21 PST
Comment on attachment 182407 [details]
Patch for discussion only.

View in context: https://bugs.webkit.org/attachment.cgi?id=182407&action=review

> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:58
> +my %vtableExceptions = (

Can we make this an IDL attribute rather than hardcoding this list in the code generator?
Comment 4 Thomas Sepez 2013-01-11 14:09:25 PST
> Can we make this an IDL attribute rather than hardcoding this list in the code generator?

I'd expect that we'd do it that way long-term.  But that requires modifying files in webkit, and the associated fist-fights.
Comment 5 Thomas Sepez 2013-01-11 14:12:41 PST
(In reply to comment #4)
> > Can we make this an IDL attribute rather than hardcoding this list in the code generator?
> 
> I'd expect that we'd do it that way long-term.  But that requires modifying files in webkit, and the associated fist-fights.

Also note that the plan would be to get rid of everything in %vtableExceptions by giving them virtual destructors on the platforms that implement this. The %polymorphicExceptions is a little harder.
Comment 6 Thomas Sepez 2013-01-11 14:15:55 PST
> Also note that the plan would be to get rid of everything in %vtableExceptions by giving them virtual destructors on the platforms that implement this.

Or, to be more precise, nearly everything in that list except for the small hot items.
Comment 7 Adam Barth 2013-01-11 15:05:12 PST
I should say that 2-4% on dom-traverse.html sounds like a reasonable price to pay for this security hardening.  Obviously, I'd prefer 2% rather than 4% (and the patch needs to be cleaned up a bit).
Comment 8 Thomas Sepez 2013-01-11 15:40:52 PST
(In reply to comment #7)
> and the patch needs to be cleaned up a bit.
Sure.  got any suggestions?
Comment 9 Adam Barth 2013-01-11 17:05:13 PST
Comment on attachment 182407 [details]
Patch for discussion only.

View in context: https://bugs.webkit.org/attachment.cgi?id=182407&action=review

> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:470
> +    # DO NOT CI this next line.  The symbol would come from the build environment.
> +    # We kludge this here to make building the prototype easier.

This stands out.  :)

> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:533
> +#ifdef V8_BINDING_TYPE_CHECKS_ENABLED

V8_BINDING_TYPE_CHECKS_ENABLED -> ENABLE(RUNTIME_TYPE_CHECKS_IN_BINDINGS) ?

> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:538
> +        void* lowPtr = (void*)((void**)classInfo->instanceValidationPointer + 2);
> +        void* highPtr = (void*)((void**)classInfo->instanceValidationPointer + 3);
> +        void* vtablePtr = *(void**)objectPtr;

These should use C++ style casts (e.g., reinterpret_cast)

> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:973
> +

This change seems spurious

> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:2846
> +    push(@implContentDecls, "#ifdef V8_BINDING_TYPE_CHECKS_ENABLED\nextern \"C\" { extern void* ${vtableName}[]; }\n#endif\n\n") if $vtableName;

Can we use the << style instead of using \n ?

> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:3732
> +sub GetVtableNameForType

Everything below this line is just magic to me.  :)

> Source/WebCore/bindings/v8/ScriptWrappable.h:42
> +    virtual ~ScriptWrappable() {}

I'm not sure about this change.  Won't this cause some objects to have multiple vtables?

> Source/WebCore/bindings/v8/WrapperTypeInfo.h:69
> -        
> -        
> +
> +

Lots of suprious whitespace changes
Comment 10 Thomas Sepez 2013-01-14 13:26:49 PST
Created attachment 182616 [details]
Full perf test results

Full test results: some of these are off more than the Dom-traverse.
Comment 11 Adam Barth 2013-01-14 13:42:53 PST
It's hard to tell whether those results are due to noise.  When you run that many tests, you need to worry about multiple hypothesis testing.  http://en.wikipedia.org/wiki/Multiple_comparisons
Comment 12 Thomas Sepez 2013-01-14 13:49:53 PST
Comment on attachment 182407 [details]
Patch for discussion only.

View in context: https://bugs.webkit.org/attachment.cgi?id=182407&action=review

>> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:470
>> +    # We kludge this here to make building the prototype easier.
> 
> This stands out.  :)

Clearly. :)

>> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:533
>> +#ifdef V8_BINDING_TYPE_CHECKS_ENABLED
> 
> V8_BINDING_TYPE_CHECKS_ENABLED -> ENABLE(RUNTIME_TYPE_CHECKS_IN_BINDINGS) ?

changed to ENABLE(BINDING_INTEGRITY)

>> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:538
>> +        void* vtablePtr = *(void**)objectPtr;
> 
> These should use C++ style casts (e.g., reinterpret_cast)

Done.

>> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:973
>> +
> 
> This change seems spurious

yep.

>> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:2846
>> +    push(@implContentDecls, "#ifdef V8_BINDING_TYPE_CHECKS_ENABLED\nextern \"C\" { extern void* ${vtableName}[]; }\n#endif\n\n") if $vtableName;
> 
> Can we use the << style instead of using \n ?

Done.

>> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:3732
>> +sub GetVtableNameForType
> 
> Everything below this line is just magic to me.  :)

Added link to ABI spec.

>> Source/WebCore/bindings/v8/ScriptWrappable.h:42
>> +    virtual ~ScriptWrappable() {}
> 
> I'm not sure about this change.  Won't this cause some objects to have multiple vtables?

Now surrounded with ENABLE(BINDING_INTEGRITY).  This class typically comes first, so its effect should be to grow an initial vtable.  There may be multiple ones.

>> Source/WebCore/bindings/v8/WrapperTypeInfo.h:69
>> +
> 
> Lots of suprious whitespace changes

Replaced lines with 8 spaces with truly blank lines cause it irked me.
Comment 13 Thomas Sepez 2013-01-14 14:12:09 PST
Created attachment 182626 [details]
Patch.
Comment 14 Thomas Sepez 2013-01-14 14:38:09 PST
Created attachment 182630 [details]
Patch, fix custom .cpp file.
Comment 15 Thomas Sepez 2013-01-14 14:59:02 PST
Q. How does one get a --[no-]binding-integrity in build-webkit scripts?  Is there bribery involved :) ?
Comment 16 Adam Barth 2013-01-14 15:01:12 PST
> Q. How does one get a --[no-]binding-integrity in build-webkit scripts?  Is there bribery involved :) ?

Those flags don't do anything in Chromium.  For Chromium, you want to add something to features.gypi.
Comment 17 Thomas Sepez 2013-01-14 15:24:34 PST
Created attachment 182637 [details]
Patch, add to features.gypi (initially disabled).
Comment 18 Thomas Sepez 2013-01-14 16:22:19 PST
Created attachment 182650 [details]
Patch, fix casting.
Comment 19 Thomas Sepez 2013-01-15 13:11:55 PST
Created attachment 182836 [details]
Patch, windows support attempt.
Comment 20 Thomas Sepez 2013-01-24 16:03:47 PST
Created attachment 184603 [details]
Patch, avoid merge conflicts, initial setting is "disable"
Comment 21 WebKit Review Bot 2013-01-24 16:05:10 PST
Attachment 184603 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WebCore/ChangeLog', u'Source/WebCore/bindings/scripts/CodeGeneratorV8.pm', u'Source/WebCore/bindings/v8/ScriptWrappable.h', u'Source/WebCore/bindings/v8/WrapperTypeInfo.h', u'Source/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp', u'Source/WebCore/bindings/v8/custom/V8PerformanceEntryCustom.cpp', u'Source/WebKit/chromium/ChangeLog', u'Source/WebKit/chromium/features.gypi']" exit_code: 1
Source/WebKit/chromium/ChangeLog:1:  ChangeLog entry has no bug number  [changelog/bugnumber] [5]
Source/WebCore/bindings/v8/ScriptWrappable.h:43:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Total errors found: 2 in 8 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 22 Adam Barth 2013-01-24 21:38:34 PST
Can you explain the scenario in which this patch helps security?  I'm not sure I quite understand.  If there's a JS wrapper pointing to a native object, the JS wrapper should be retaining the object, preventing it from being freed (and therefore used-after-freed).
Comment 23 Thomas Sepez 2013-01-24 22:47:42 PST
(In reply to comment #22)
> Can you explain the scenario in which this patch helps security?  I'm not sure I quite understand.  If there's a JS wrapper pointing to a native object, the JS wrapper should be retaining the object, preventing it from being freed (and therefore used-after-freed).

That would imply that the object is already free at the time it is first wrapped.
Comment 24 Kentaro Hara 2013-01-24 22:51:30 PST
A few tips for stable performance testing:

(1) You can use ./run-perf-tests instead of chrome.

(2) You can specify CPU affinity by a taskset command; e.g. 'taskset -c 12 ./Tools/Scripts/run-perf-tests Dromaeo/dom-traverse'. It's important to specify a CPU ID that is not likely to be used by other processes (i.e. you want to avoid 0)
Comment 25 Thomas Sepez 2013-01-24 22:53:33 PST
(In reply to comment #23)
> (In reply to comment #22)
> > Can you explain the scenario in which this patch helps security?  I'm not sure I quite understand.  If there's a JS wrapper pointing to a native object, the JS wrapper should be retaining the object, preventing it from being freed (and therefore used-after-freed).
> 
> That would imply that the object is already free at the time it is first wrapped.

which begs the question "why not just check there"?  We had convinced ourselves that an object could be free and still have an intact vtable pointer.  But that was before the performance headaches, so maybe we could get away with this on platforms that trash the first word with something like the heap freelist pointer upon free.
Comment 26 Thomas Sepez 2013-01-24 22:56:27 PST
Thanks for the tips.  Responses inline:

> (1) You can use ./run-perf-tests instead of chrome.
Yep.  That's what I'm using.

> 
> (2) You can specify CPU affinity by a taskset command; e.g. 'taskset -c 12 ./Tools/Scripts/run-perf-tests Dromaeo/dom-traverse'. It's important to specify a CPU ID that is not likely to be used by other processes (i.e. you want to avoid 0
Thanks.  That's a good idea.  I've been closing all GUI apps on the mac, but there's still a ton of stuff that's always running.
Comment 27 Thomas Sepez 2013-01-24 23:02:37 PST
(I
> > (2) You can specify CPU affinity by a taskset command; e.g. 'taskset -c 12 ./Tools/Scripts/run-perf-tests Dromaeo/dom-traverse'. It's important to specify a CPU ID that is not likely to be used by other processes (i.e. you want to avoid 0
> Thanks.  That's a good idea.  I've been closing all GUI apps on the mac, but there's still a ton of stuff that's always running.

Except that I don't see an equivalent for OSX.  A quick search turns up a couple of pages claiming that no such feature exists for mac.
Comment 28 Thomas Sepez 2013-01-28 12:24:23 PST
Created attachment 185033 [details]
Patch, check at wrapper creation time.

I did not notice any performance hit when I ran dom-traverse against this patch.
Comment 29 Adam Barth 2013-01-28 12:29:37 PST
Comment on attachment 185033 [details]
Patch, check at wrapper creation time.

View in context: https://bugs.webkit.org/attachment.cgi?id=185033&action=review

> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:3739
> +        || $typename eq "AudioBuffer"
> +        || $typename eq "AudioListener"
> +        || $typename eq "AudioSourceNode"
> +        || $typename eq "AudioSourceNode"
> +        || $typename eq "CSSPrimitiveValue"
> +        || $typename eq "CSSValue"

We don't want to the these big lists of interface names in the code generator.  Instead, we should use IDL attributes to control the code generator.
Comment 30 Thomas Sepez 2013-01-28 12:33:05 PST
Yep, and there's a comment about doing this long-term in V8CodeGenerator.pm.  The alternative is to patch 100s of files now, which we can do incrementally otherwise.
Comment 31 Adam Barth 2013-01-28 12:35:28 PST
Don't be afraid of editing 100s of files.  That's better than hard-coding interface names in the code generator.
Comment 32 Thomas Sepez 2013-01-28 17:50:18 PST
Created attachment 185118 [details]
Patch, specify exceptions in IDL files.
Comment 33 Kentaro Hara 2013-01-28 17:54:24 PST
(In reply to comment #28)
> Created an attachment (id=185033) [details]
> Patch, check at wrapper creation time.
> 
> I did not notice any performance hit when I ran dom-traverse against this patch.

Would you also check the perf impact on Bindings/first-child.html? It will tell you the worst case number. (I'm not intending to block your work by the number, I just want to know the number.)
Comment 34 Thomas Sepez 2013-01-28 18:14:00 PST
(In reply to comment #33)
> (In reply to comment #28)
> > Created an attachment (id=185033) [details] [details]
> > Patch, check at wrapper creation time.
> > 
> > I did not notice any performance hit when I ran dom-traverse against this patch.
> 
> Would you also check the perf impact on Bindings/first-child.html? It will tell you the worst case number. (I'm not intending to block your work by the number, I just want to know the number.)

No Problem.  before = [ 458, 462 ], after = [ 459, 455].
Comment 35 Adam Barth 2013-01-28 18:23:33 PST
Comment on attachment 185118 [details]
Patch, specify exceptions in IDL files.

View in context: https://bugs.webkit.org/attachment.cgi?id=185118&action=review

This looks much better.  Thank you for pushing this data out into IDL attributes.

> Source/WebCore/bindings/scripts/CodeGeneratorV8.pm:3603
> +sub GetGnuVTableOffsetForType

I probably would have added a FIXME or a comment explaining this function.

> Source/WebCore/css/WebKitCSSFilterValue.idl:30
>          Conditional=CSS_FILTERS,
>          IndexedGetter,
> -        DoNotCheckConstants
> +        DoNotCheckConstants,
> +    ImplementationLacksVTable

Looks like there are some indent issues.  It would be nice to clean up the bad indents to match the four-space indent, but we can do that in a followup patch.

> Source/WebKit/chromium/features.gypi:37
> +      'ENABLE_BINDING_INTEGRITY=0',

Did you mean to land the patch with this disabled?  I guess we can flip the switch separately from the big code edit.
Comment 36 Adam Barth 2013-01-28 18:24:55 PST
> > Would you also check the perf impact on Bindings/first-child.html? It will tell you the worst case number. (I'm not intending to block your work by the number, I just want to know the number.)
> 
> No Problem.  before = [ 458, 462 ], after = [ 459, 455].

@haraken: He's moved the check from toNative to createWrapper, which means this version is much better for performance.
Comment 37 Kentaro Hara 2013-01-28 18:36:57 PST
(In reply to comment #36)
> > No Problem.  before = [ 458, 462 ], after = [ 459, 455].
> 
> @haraken: He's moved the check from toNative to createWrapper, which means this version is much better for performance.

Great!
Comment 38 Adam Barth 2013-01-28 18:39:18 PST
Comment on attachment 185118 [details]
Patch, specify exceptions in IDL files.

Clearing flags on attachment: 185118

Committed r141034: <http://trac.webkit.org/changeset/141034>
Comment 39 Adam Barth 2013-01-28 18:39:25 PST
All reviewed patches have been landed.  Closing bug.
Comment 40 Zoltan Arvai 2013-01-29 01:13:12 PST
After the patch landed some binging tests are failing. 
Can you check it, please?

(In reply to comment #38)
> (From update of attachment 185118 [details])
> Clearing flags on attachment: 185118
> 
> Committed r141034: <http://trac.webkit.org/changeset/141034>
Comment 41 Florin Malita 2013-01-29 06:24:08 PST
(In reply to comment #40)
> After the patch landed some binging tests are failing. 
> Can you check it, please?

Looks like the results just need to be updated: http://trac.webkit.org/changeset/141105

Adam,Thomas: can you please double-check that the new results are correct?
Comment 42 Thomas Sepez 2013-01-29 09:56:33 PST
The changes look OK, but having said that, it seems a little strange that we have source-controlled files that must match generated ones -- maybe someone with some background on run-bindings-tests can let me in on the thinking?

I missed this because I only ran run-webkit-tests --- not the run-bindings-tests.  Sorry.
Comment 43 Adam Barth 2013-01-29 12:50:02 PST
> The changes look OK, but having said that, it seems a little strange that we have source-controlled files that must match generated ones -- maybe someone with some background on run-bindings-tests can let me in on the thinking?

It helps us test the code generator and makes it easier to review changes to the generated code.  We should run them automatically in the EWS to remind folks to update the results in their patch.  (It's just test data---it's not compiled into the product.)
Comment 44 Kentaro Hara 2013-02-21 18:10:09 PST
BTW, how are [JSNoStaticTables] and [ImplementationLacksVTable] different? Maybe can we merge the two IDL attributes?
Comment 45 Adam Barth 2013-02-21 18:44:01 PST
Nostatictables is about whether the generated code is thread safe.
Comment 46 Kentaro Hara 2013-02-21 18:45:19 PST
(In reply to comment #45)
> Nostatictables is about whether the generated code is thread safe.

Ah, makes sense. Thanks.