Bug 210844

Summary: IPC::decodeSharedBuffer() should check the return value of SharedMemory::map()
Product: WebKit Reporter: David Kilzer (:ddkilzer) <ddkilzer>
Component: WebKit2Assignee: David Kilzer (:ddkilzer) <ddkilzer>
Status: RESOLVED FIXED    
Severity: Normal CC: cdumez, darin, ggaren, useafterfree, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: Other   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Patch v1 none

Description David Kilzer (:ddkilzer) 2020-04-21 21:44:56 PDT
IPC::decodeSharedBuffer() should check the return value of SharedMemory::map().

<rdar://problem/60773120>
Comment 1 David Kilzer (:ddkilzer) 2020-04-21 21:45:48 PDT
Created attachment 397167 [details]
Patch v1
Comment 2 Darin Adler 2020-04-21 22:17:53 PDT
Comment on attachment 397167 [details]
Patch v1

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

> Source/WebKit/Shared/WebCoreArgumentCoders.cpp:179
> +    if (!sharedMemoryBuffer)
> +        return false;

When does this situation arise? Is "return false" sufficient here? Should we be crashing instead? Or making the process that passed us this handle crash?
Comment 3 David Kilzer (:ddkilzer) 2020-04-22 08:47:45 PDT
(In reply to Darin Adler from comment #2)
> Comment on attachment 397167 [details]
> Patch v1
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=397167&action=review
> 
> > Source/WebKit/Shared/WebCoreArgumentCoders.cpp:179
> > +    if (!sharedMemoryBuffer)
> > +        return false;
> 
> When does this situation arise? Is "return false" sufficient here? Should we
> be crashing instead? Or making the process that passed us this handle crash?

There are numerous reasons that SharedMemory::map() can fail:

<https://trac.webkit.org/browser/trunk/Source/WebKit/Platform/cocoa/SharedMemoryCocoa.cpp#L212>

I think `return false` is sufficient here because callers of IPC::decodeSharedBuffer() always check their return values via WARN_UNUSED_RETURN:

static WARN_UNUSED_RETURN bool decodeSharedBuffer(Decoder& decoder, RefPtr<SharedBuffer>& buffer)

In general, decoding is a task where failures are (must be) handled since we're dealing with untrusted input.
Comment 4 Geoffrey Garen 2020-04-22 11:50:41 PDT
Comment on attachment 397167 [details]
Patch v1

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

r=me

>>> Source/WebKit/Shared/WebCoreArgumentCoders.cpp:179
>>> +        return false;
>> 
>> When does this situation arise? Is "return false" sufficient here? Should we be crashing instead? Or making the process that passed us this handle crash?
> 
> There are numerous reasons that SharedMemory::map() can fail:
> 
> <https://trac.webkit.org/browser/trunk/Source/WebKit/Platform/cocoa/SharedMemoryCocoa.cpp#L212>
> 
> I think `return false` is sufficient here because callers of IPC::decodeSharedBuffer() always check their return values via WARN_UNUSED_RETURN:
> 
> static WARN_UNUSED_RETURN bool decodeSharedBuffer(Decoder& decoder, RefPtr<SharedBuffer>& buffer)
> 
> In general, decoding is a task where failures are (must be) handled since we're dealing with untrusted input.

I think Darin is agreeing that decoding should handle failure, and then asking whether our failure handling should include killing the sender (to avoid giving a malicious sender multiple attempts at the same exploit).

I guess my take is that decodeSharedBuffer is used by lots of different clients, so it may not be appropriate for decodeSharedBuffer to kill the sender in all cases. But maybe we should audit callers of decodeSharedBuffer to consider whether they should kill the sender on failure. Here's an example I found that might want to MESSAGE_CHECK a PasteboardWebContent, which contains a SharedBuffer:

    void WebPasteboardProxy::writeWebContentToPasteboard(IPC::Connection& connection, const WebCore::PasteboardWebContent& content, const String& pasteboardName)
Comment 5 EWS 2020-04-22 12:15:04 PDT
Committed r260527: <https://trac.webkit.org/changeset/260527>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 397167 [details].
Comment 6 Darin Adler 2020-04-22 12:38:55 PDT
(In reply to Geoffrey Garen from comment #4)
> I think Darin is agreeing that decoding should handle failure, and then
> asking whether our failure handling should include killing the sender (to
> avoid giving a malicious sender multiple attempts at the same exploit).

Yes, that’s right.

> But maybe we should audit callers of decodeSharedBuffer
> to consider whether they should kill the sender on failure. Here's an
> example I found that might want to MESSAGE_CHECK a PasteboardWebContent,
> which contains a SharedBuffer:
> 
>     void WebPasteboardProxy::writeWebContentToPasteboard(IPC::Connection&
> connection, const WebCore::PasteboardWebContent& content, const String&
> pasteboardName)

Makes sense to me.

The main thing I wanted to check/question is whether the memory mapping failure should have identical handling to other types of decoding failures, since the single boolean tells about both. And whether we are taking advantage of it sufficiently to check the integrity of messages coming from the web process.