Changeset 248024 in webkit


Ignore:
Timestamp:
Jul 30, 2019, 4:52:55 PM (6 years ago)
Author:
rniwa@webkit.org
Message:

WorkerGlobalScope::wrapCryptoKey/unwrapCryptoKey should use local heap objects for replies
https://bugs.webkit.org/show_bug.cgi?id=200179
<rdar://problem/52334658>

Reviewed by Brent Fulgham.

Based on the patch by Jiewen Tan.

WorkerGlobalScope::wrapCryptoKey and WorkerGlobalScope::unwrapCryptoKey had a bug that they could exit
the function before the main thread had finished writing to the result vector passed in to these functions
when the worker's runloop receives MessageQueueTerminated before the main thread finishes writing.

Fixed the bug by creating a new temporary Vector inside a ThreadSafeRefCounted object shared between
the main thread and the worker thread, which extends the lifetime of the Vector until when the worker thread
receives the result or when the main thread finishes writing to the Vector, whichever happens last.

Unfortunately no new tests since there is no reproducible test case, and this crash is highly racy.

  • workers/WorkerGlobalScope.cpp:

(WebCore::CryptoBufferContainer): Added.
(WebCore::CryptoBufferContainer::create): Added.
(WebCore::CryptoBufferContainer::buffer): Added.
(WebCore::WorkerGlobalScope::wrapCryptoKey):
(WebCore::WorkerGlobalScope::unwrapCryptoKey):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r248022 r248024  
     12019-07-29  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        WorkerGlobalScope::wrapCryptoKey/unwrapCryptoKey should use local heap objects for replies
     4        https://bugs.webkit.org/show_bug.cgi?id=200179
     5        <rdar://problem/52334658>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        Based on the patch by Jiewen Tan.
     10
     11        WorkerGlobalScope::wrapCryptoKey and WorkerGlobalScope::unwrapCryptoKey had a bug that they could exit
     12        the function before the main thread had finished writing to the result vector passed in to these functions
     13        when the worker's runloop receives MessageQueueTerminated before the main thread finishes writing.
     14
     15        Fixed the bug by creating a new temporary Vector inside a ThreadSafeRefCounted object shared between
     16        the main thread and the worker thread, which extends the lifetime of the Vector until when the worker thread
     17        receives the result or when the main thread finishes writing to the Vector, whichever happens last.
     18
     19        Unfortunately no new tests since there is no reproducible test case, and this crash is highly racy.
     20
     21        * workers/WorkerGlobalScope.cpp:
     22        (WebCore::CryptoBufferContainer): Added.
     23        (WebCore::CryptoBufferContainer::create): Added.
     24        (WebCore::CryptoBufferContainer::buffer): Added.
     25        (WebCore::WorkerGlobalScope::wrapCryptoKey):
     26        (WebCore::WorkerGlobalScope::unwrapCryptoKey):
     27
    1282019-07-30  Saam Barati  <sbarati@apple.com>
    229
  • trunk/Source/WebCore/workers/WorkerGlobalScope.cpp

    r246565 r248024  
    386386#if ENABLE(WEB_CRYPTO)
    387387
     388class CryptoBufferContainer : public ThreadSafeRefCounted<CryptoBufferContainer> {
     389public:
     390    static Ref<CryptoBufferContainer> create() { return adoptRef(*new CryptoBufferContainer); }
     391    Vector<uint8_t>& buffer() { return m_buffer; }
     392
     393private:
     394    Vector<uint8_t> m_buffer;
     395};
     396
    388397bool WorkerGlobalScope::wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey)
    389398{
    390399    bool result = false;
    391     bool done = false;
    392     m_thread.workerLoaderProxy().postTaskToLoader([&result, &key, &wrappedKey, &done, workerGlobalScope = this](ScriptExecutionContext& context) {
    393         result = context.wrapCryptoKey(key, wrappedKey);
     400    std::atomic<bool> done = false;
     401    auto container = CryptoBufferContainer::create();
     402    m_thread.workerLoaderProxy().postTaskToLoader([&result, key, containerRef = container.copyRef(), &done, workerGlobalScope = this](ScriptExecutionContext& context) {
     403        result = context.wrapCryptoKey(key, containerRef->buffer());
    394404        done = true;
    395405        workerGlobalScope->postTask([](ScriptExecutionContext& context) {
     
    402412        waitResult = m_thread.runLoop().runInMode(this, WorkerRunLoop::defaultMode());
    403413
     414    if (done)
     415        wrappedKey.swap(container->buffer());
    404416    return result;
    405417}
     
    407419bool WorkerGlobalScope::unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key)
    408420{
    409     bool result = false, done = false;
    410     m_thread.workerLoaderProxy().postTaskToLoader([&result, &wrappedKey, &key, &done, workerGlobalScope = this](ScriptExecutionContext& context) {
    411         result = context.unwrapCryptoKey(wrappedKey, key);
     421    bool result = false;
     422    std::atomic<bool> done = false;
     423    auto container = CryptoBufferContainer::create();
     424    m_thread.workerLoaderProxy().postTaskToLoader([&result, wrappedKey, containerRef = container.copyRef(), &done, workerGlobalScope = this](ScriptExecutionContext& context) {
     425        result = context.unwrapCryptoKey(wrappedKey, containerRef->buffer());
    412426        done = true;
    413427        workerGlobalScope->postTask([](ScriptExecutionContext& context) {
     
    420434        waitResult = m_thread.runLoop().runInMode(this, WorkerRunLoop::defaultMode());
    421435
     436    if (done)
     437        key.swap(container->buffer());
    422438    return result;
    423439}
Note: See TracChangeset for help on using the changeset viewer.