Bug 204355 - Make sendWithAsyncReply() safe to call from any thread
Summary: Make sendWithAsyncReply() safe to call from any thread
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit2 (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Chris Dumez
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2019-11-19 08:25 PST by Chris Dumez
Modified: 2019-11-19 10:24 PST (History)
9 users (show)

See Also:


Attachments
Patch (12.21 KB, patch)
2019-11-19 08:39 PST, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (13.88 KB, patch)
2019-11-19 09:01 PST, Chris Dumez
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Dumez 2019-11-19 08:25:23 PST
Make sendWithAsyncReply() safe to call from any thread, similarly to send().
Comment 1 Chris Dumez 2019-11-19 08:39:45 PST
Created attachment 383873 [details]
Patch
Comment 2 Alex Christensen 2019-11-19 08:45:33 PST
Comment on attachment 383873 [details]
Patch

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

> Source/WebKit/Platform/IPC/Connection.cpp:255
> +    ASSERT(asyncReplyHandlerMapLock().isHeld());

JSC often does this by passing an unused LockHolder& as a parameter.

> Source/WebKit/Platform/IPC/Connection.cpp:1145
> +    LockHolder locker(asyncReplyHandlerMapLock());
>      auto map = asyncReplyHandlerMap().take(reinterpret_cast<uintptr_t>(&connection));
>      for (auto& handler : map.values()) {

The lock should only be held during the taking from the map, not during the iterating and calling.  This needs an additional scope.

> Source/WebKit/Platform/IPC/Connection.h:204
> +    // Main thread only.

Add an assert?

> Source/WebKit/Platform/IPC/Connection.h:211
> +    // Main thread only.

ditto.

> Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm:320
> +    parentProcessConnection()->sendWithAsyncReply(Messages::WebProcessProxy::ProcessWasResumed(), [this] {

Protect this or capture a weak pointer.  This looks like a UAF waiting to happen.  Even if there's something else assuring this is safe, it wouldn't hurt.
Comment 3 Chris Dumez 2019-11-19 08:50:38 PST
Comment on attachment 383873 [details]
Patch

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

>> Source/WebKit/Platform/IPC/Connection.cpp:255
>> +    ASSERT(asyncReplyHandlerMapLock().isHeld());
> 
> JSC often does this by passing an unused LockHolder& as a parameter.

And you'd prefer that?

>> Source/WebKit/Platform/IPC/Connection.cpp:1145
>>      for (auto& handler : map.values()) {
> 
> The lock should only be held during the taking from the map, not during the iterating and calling.  This needs an additional scope.

I don't understand how that can be true.. You cannot iterate over a container that may be modified from another thread, this would not be safe.

>> Source/WebKit/Platform/IPC/Connection.h:204
>> +    // Main thread only.
> 
> Add an assert?

There are already assertions.

>> Source/WebKit/Platform/IPC/Connection.h:211
>> +    // Main thread only.
> 
> ditto.

Ditto.

>> Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm:320
>> +    parentProcessConnection()->sendWithAsyncReply(Messages::WebProcessProxy::ProcessWasResumed(), [this] {
> 
> Protect this or capture a weak pointer.  This looks like a UAF waiting to happen.  Even if there's something else assuring this is safe, it wouldn't hurt.

WebProcess is a singleton...
Comment 4 Chris Dumez 2019-11-19 08:52:12 PST
Comment on attachment 383873 [details]
Patch

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

>>> Source/WebKit/Platform/IPC/Connection.cpp:1145
>>>      for (auto& handler : map.values()) {
>> 
>> The lock should only be held during the taking from the map, not during the iterating and calling.  This needs an additional scope.
> 
> I don't understand how that can be true.. You cannot iterate over a container that may be modified from another thread, this would not be safe.

Oh since we're taking, it is safe. will fix this.
Comment 5 Chris Dumez 2019-11-19 09:01:47 PST
Created attachment 383875 [details]
Patch
Comment 6 Alex Christensen 2019-11-19 09:03:49 PST
Comment on attachment 383875 [details]
Patch

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

> Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm:320
> +    parentProcessConnection()->sendWithAsyncReply(Messages::WebProcessProxy::ProcessWasResumed(), [this] {

🤦
singleton it is.
Comment 7 Chris Dumez 2019-11-19 09:08:23 PST
(In reply to Alex Christensen from comment #6)
> Comment on attachment 383875 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=383875&action=review
> 
> > Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm:320
> > +    parentProcessConnection()->sendWithAsyncReply(Messages::WebProcessProxy::ProcessWasResumed(), [this] {
> 
> 🤦
> singleton it is.

I checked, WebProcess does not subclass CanMakeWeakPtr so nobody else had this idea yet at least :)
Comment 8 WebKit Commit Bot 2019-11-19 10:23:25 PST
Comment on attachment 383875 [details]
Patch

Clearing flags on attachment: 383875

Committed r252636: <https://trac.webkit.org/changeset/252636>
Comment 9 WebKit Commit Bot 2019-11-19 10:23:27 PST
All reviewed patches have been landed.  Closing bug.
Comment 10 Radar WebKit Bug Importer 2019-11-19 10:24:27 PST
<rdar://problem/57326449>