WebAssembly: disable some APIs under CSP
authorjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Jun 2017 18:49:18 +0000 (18:49 +0000)
committerjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Jun 2017 18:49:18 +0000 (18:49 +0000)
commit4f15d97c2115063ecf9b4e18dc72afd054bdc0f7
tree4fbec19df051fa9fb1c498907e798d7e0e31fb53
parent0ef14a5f1330a1e2322b3a4a1db564c67730b76c
WebAssembly: disable some APIs under CSP
https://bugs.webkit.org/show_bug.cgi?id=173892
<rdar://problem/32914613>

Reviewed by Daniel Bates.

Source/JavaScriptCore:

We should disable parts of WebAssembly under Content Security
Policy as discussed here:

https://github.com/WebAssembly/design/issues/1092

Exactly what should be disabled isn't super clear, so we may as
well be conservative and disable many things if developers already
opted into CSP. It's easy to loosen what we disable later.

This patch disables:
- WebAssembly.Instance
- WebAssembly.instantiate
- WebAssembly.Memory
- WebAssembly.Table

And leaves:
- WebAssembly on the global object
- WebAssembly.Module
- WebAssembly.compile
- WebAssembly.CompileError
- WebAssembly.LinkError

Nothing because currently unimplmented:
- WebAssembly.compileStreaming
- WebAssembly.instantiateStreaming

That way it won't be possible to call WebAssembly-compiled code,
or create memories (which use fancy 4GiB allocations
sometimes). Table isn't really useful on its own, and eventually
we may make them shareable so without more details it seems benign
to disable them (and useless if we don't).

I haven't done anything with postMessage, so you can still
postMessage a WebAssembly.Module cross-CSP, but you can't
instantiate it so it's useless. Because of this I elected to leave
WebAssembly.Module and friends available.

I haven't added any new directives. It's still unsafe-eval. We can
add something else later, but it seems odd to add a WebAssembly as
a new capability and tell developers "you should have been using
this directive which we just implemented if you wanted to disable
WebAssembly which didn't exist when you adopted CSP". So IMO we
should keep unsafe-eval as it currently is, add WebAssembly to
what it disables, and later consider having two new directives
which do each individually or something.

In all cases I throw an EvalError *before* other WebAssembly
errors would be produced.

Note that, as for eval, reporting doesn't work and is tracked by
https://webkit.org/b/111869

* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::JSGlobalObject):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::webAssemblyEnabled):
(JSC::JSGlobalObject::webAssemblyDisabledErrorMessage):
(JSC::JSGlobalObject::setWebAssemblyEnabled):
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::create):
* wasm/js/JSWebAssemblyMemory.cpp:
(JSC::JSWebAssemblyMemory::create):
* wasm/js/JSWebAssemblyMemory.h:
* wasm/js/JSWebAssemblyTable.cpp:
(JSC::JSWebAssemblyTable::create):
* wasm/js/WebAssemblyMemoryConstructor.cpp:
(JSC::constructJSWebAssemblyMemory):

Source/WebCore:

This does the basic separation of eval-blocked and
WebAssembly-blocked, but currently only blocks neither or both. I
think we'll eventually consider allowing one to be blocked but not
the other, so this separation makes sense and means that when we
want to do the change it'll be tiny. At a minimum we want a
different error message, which this patch provides (a lot of the
code ties blocking to the error message).

Tests: http/tests/security/contentSecurityPolicy/WebAssembly-allowed.html
       http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-about-blank-iframe.html
       http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-external-script.html
       http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-subframe.html
       http/tests/security/contentSecurityPolicy/WebAssembly-blocked.html

* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::enableWebAssembly):
(WebCore::ScriptController::disableWebAssembly):
* bindings/js/ScriptController.h:
* bindings/js/WorkerScriptController.cpp:
(WebCore::WorkerScriptController::disableWebAssembly):
* bindings/js/WorkerScriptController.h:
* dom/Document.cpp:
(WebCore::Document::disableWebAssembly):
* dom/Document.h:
* dom/ScriptExecutionContext.h:
* page/csp/ContentSecurityPolicy.cpp:
(WebCore::ContentSecurityPolicy::didCreateWindowProxy):
(WebCore::ContentSecurityPolicy::applyPolicyToScriptExecutionContext):
* page/csp/ContentSecurityPolicy.h:
* page/csp/ContentSecurityPolicyDirectiveList.cpp:
(WebCore::ContentSecurityPolicyDirectiveList::create):
* page/csp/ContentSecurityPolicyDirectiveList.h:
(WebCore::ContentSecurityPolicyDirectiveList::webAssemblyDisabledErrorMessage):
(WebCore::ContentSecurityPolicyDirectiveList::setWebAssemblyDisabledErrorMessage):
* workers/WorkerGlobalScope.cpp:
(WebCore::WorkerGlobalScope::disableWebAssembly):
* workers/WorkerGlobalScope.h:

LayoutTests:

These tests are basically the same as eval-blocked, but with
WebAssembly APIs instead of eval.

Disable all of them on iOS simulator which doesn't support
WebAssembly (whereas iOS does).

* http/tests/security/contentSecurityPolicy/WebAssembly-allowed-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/WebAssembly-allowed.html: Added.
* http/tests/security/contentSecurityPolicy/WebAssembly-blocked-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-about-blank-iframe-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-about-blank-iframe.html: Added.
* http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-external-script-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-external-script.html: Added.
* http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-subframe-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-subframe.html: Added.
* http/tests/security/contentSecurityPolicy/WebAssembly-blocked.html: Added.
* http/tests/security/contentSecurityPolicy/resources/WebAssembly-blocked-in-external-script.js: Added.
* platform/ios-simulator/TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@218951 268f45cc-cd09-0410-ab3c-d52691b4dbfc
35 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/security/contentSecurityPolicy/WebAssembly-allowed-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/WebAssembly-allowed.html [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/WebAssembly-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-about-blank-iframe-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-about-blank-iframe.html [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-external-script-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-external-script.html [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-subframe-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-subframe.html [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/WebAssembly-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/resources/WebAssembly-blocked-in-external-script.js [new file with mode: 0644]
LayoutTests/platform/ios-simulator/TestExpectations
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/ScriptController.cpp
Source/WebCore/bindings/js/ScriptController.h
Source/WebCore/bindings/js/WorkerScriptController.cpp
Source/WebCore/bindings/js/WorkerScriptController.h
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/ScriptExecutionContext.h
Source/WebCore/page/csp/ContentSecurityPolicy.cpp
Source/WebCore/page/csp/ContentSecurityPolicy.h
Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp
Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h
Source/WebCore/workers/WorkerGlobalScope.cpp
Source/WebCore/workers/WorkerGlobalScope.h