Ignore:
Timestamp:
Jun 29, 2017, 11:49:18 AM (8 years ago)
Author:
[email protected]
Message:

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:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r218861 r218951  
    442442    TemplateRegistry m_templateRegistry;
    443443
    444     bool m_evalEnabled;
     444    bool m_evalEnabled { true };
     445    bool m_webAssemblyEnabled { true };
    445446    String m_evalDisabledErrorMessage;
     447    String m_webAssemblyDisabledErrorMessage;
    446448    RuntimeFlags m_runtimeFlags;
    447     ConsoleClient* m_consoleClient;
     449    ConsoleClient* m_consoleClient { nullptr };
    448450
    449451    static JS_EXPORTDATA const GlobalObjectMethodTable s_globalObjectMethodTable;
     
    800802
    801803    bool evalEnabled() const { return m_evalEnabled; }
     804    bool webAssemblyEnabled() const { return m_webAssemblyEnabled; }
    802805    const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; }
     806    const String& webAssemblyDisabledErrorMessage() const { return m_webAssemblyDisabledErrorMessage; }
    803807    void setEvalEnabled(bool enabled, const String& errorMessage = String())
    804808    {
    805809        m_evalEnabled = enabled;
    806810        m_evalDisabledErrorMessage = errorMessage;
     811    }
     812    void setWebAssemblyEnabled(bool enabled, const String& errorMessage = String())
     813    {
     814        m_webAssemblyEnabled = enabled;
     815        m_webAssemblyDisabledErrorMessage = errorMessage;
    807816    }
    808817
Note: See TracChangeset for help on using the changeset viewer.