Validate navigation policy decisions to avoid crashes in continueLoadAfterNavigationP...
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 3 Feb 2019 22:48:22 +0000 (22:48 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 3 Feb 2019 22:48:22 +0000 (22:48 +0000)
commit7ba1f3b11cd28cc64924b16a9f3288032cd163d9
tree552b7920eab9c1fd6d0ad9ded70c28fc10a0f24a
parent15b9929710eb5c87b6b59e7a298bd5e58defc587
Validate navigation policy decisions to avoid crashes in continueLoadAfterNavigationPolicy
https://bugs.webkit.org/show_bug.cgi?id=194189

Reviewed by Geoffrey Garen.

Source/WebCore:

Introduced PolicyCheckIdentifier to pair each navigation policy check request with a decision,
and deployed it in PolicyChecker. The identifier is passed from WebContent process to UI process
in WebKit2, and passed it back with the policy decision.

Because PolicyCheckIdentifier embeds the process identifier from which a navigation policy is checked,
we would be able to detect when UI process had sent the decision to a wrong WebContent process.

This patch also adds release assertions to make sure history().provisionalItem() is set whenever
we're requesting a navigation policy check.

These code changes should either:
1. Fix crashes in FrameLoader::continueLoadAfterNavigationPolicy where isBackForwardLoadType would
   return true yet history().provisionalItem() is null.
2. Detect a bug that UI process can send a navigation policy decision to a wrong WebContent process.
3. Rule out the possibility that (2) exists.

* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::willSendRequest):
(WebCore::DocumentLoader::responseReceived):
* loader/EmptyClients.cpp:
(WebCore::EmptyFrameLoaderClient::dispatchDecidePolicyForNewWindowAction):
(WebCore::EmptyFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
* loader/EmptyFrameLoaderClient.h:
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::checkContentPolicy):
(WebCore::FrameLoader::loadURL):
(WebCore::FrameLoader::load):
(WebCore::FrameLoader::loadWithDocumentLoader):
(WebCore::FrameLoader::loadPostRequest):
* loader/FrameLoader.h:
* loader/FrameLoaderClient.h:
* loader/FrameLoaderTypes.h:
(WebCore::PolicyCheckIdentifier): Added.
(WebCore::PolicyCheckIdentifier::operator== const): Added.
(WebCore::PolicyCheckIdentifier::PolicyCheckIdentifier): Added.
(WebCore::PolicyCheckIdentifier::encode const): Added.
(WebCore::PolicyCheckIdentifier::decode): Added.
* loader/PolicyChecker.cpp:
(WebCore::PolicyCheckIdentifier::generate):
(WebCore::PolicyCheckIdentifier::isValidFor): Returns true if the identifer matches. Also release asserts
that the process ID is same, and that m_check is always not zero (meaning it's a generated value).
The failure of these release assertions would indicate that there is a bug in UI process, which results in
a policy decision response being sent to a wrong Web process.
(WebCore::PolicyChecker::checkNavigationPolicy): Exit early if isValidFor fails.
(WebCore::PolicyChecker::checkNewWindowPolicy):

Source/WebKit:

Pass the policy check identifier around functions and store it in PolicyDecisionSender
so that we can send it back to WebCore with the navigation policy decision.

We also store it in WebFrame in the case the policy decision had to be invalidated
before the decision was received (via WebFrame::invalidatePolicyListener).

* Scripts/webkit/messages.py:
* UIProcess/ProvisionalPageProxy.cpp:
(WebKit::ProvisionalPageProxy::decidePolicyForNavigationActionAsync):
(WebKit::ProvisionalPageProxy::decidePolicyForResponse):
* UIProcess/ProvisionalPageProxy.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::PolicyDecisionSender): Added PolicyCheckIdentifier as a member.
(WebKit::WebPageProxy::PolicyDecisionSender::create):
(WebKit::WebPageProxy::PolicyDecisionSender::send):
(WebKit::WebPageProxy::PolicyDecisionSender::PolicyDecisionSender):
(WebKit::WebPageProxy::receivedNavigationPolicyDecision):
(WebKit::WebPageProxy::decidePolicyForNavigationActionAsync):
(WebKit::WebPageProxy::decidePolicyForNavigationActionAsyncShared):
(WebKit::WebPageProxy::decidePolicyForNavigationAction):
(WebKit::WebPageProxy::decidePolicyForNavigationActionSync):
(WebKit::WebPageProxy::decidePolicyForNewWindowAction):
(WebKit::WebPageProxy::decidePolicyForResponse):
(WebKit::WebPageProxy::decidePolicyForResponseShared):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction):
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
* WebProcess/WebPage/WebFrame.cpp:
(WebKit::WebFrame::setUpPolicyListener):
(WebKit::WebFrame::invalidatePolicyListener):
(WebKit::WebFrame::didReceivePolicyDecision):
* WebProcess/WebPage/WebFrame.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::didReceivePolicyDecision):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Source/WebKitLegacy/mac:

Pass the policy check identifier around functions and store it in WebFramePolicyListener
so that we can send it back to WebCore with the navigation policy decision.

* WebCoreSupport/WebFrameLoaderClient.h:
* WebCoreSupport/WebFrameLoaderClient.mm:
(WebFrameLoaderClient::dispatchDecidePolicyForResponse):
(WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction):
(WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
(WebFrameLoaderClient::dispatchWillSubmitForm):
(WebFrameLoaderClient::setUpPolicyListener):
(-[WebFramePolicyListener initWithFrame:identifier:policyFunction:defaultPolicy:]):
(-[WebFramePolicyListener initWithFrame:identifier:policyFunction:defaultPolicy:appLinkURL:]):
(-[WebFramePolicyListener invalidate]):
(-[WebFramePolicyListener dealloc]):
(-[WebFramePolicyListener receivedPolicyDecision:]):
(-[WebFramePolicyListener initWithFrame:policyFunction:defaultPolicy:]): Deleted.
(-[WebFramePolicyListener initWithFrame:policyFunction:defaultPolicy:appLinkURL:]): Deleted.

Source/WebKitLegacy/win:

Pass the policy check identifier around functions and store it in WebFramePolicyListener
so that we can send it back to WebCore with the navigation policy decision.

* WebCoreSupport/WebFrameLoaderClient.cpp:
(WebFrameLoaderClient::dispatchDecidePolicyForResponse):
(WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction):
(WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
(WebFrameLoaderClient::dispatchWillSubmitForm):
(WebFrameLoaderClient::setUpPolicyListener):
* WebCoreSupport/WebFrameLoaderClient.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@240909 268f45cc-cd09-0410-ab3c-d52691b4dbfc
29 files changed:
Source/WebCore/ChangeLog
Source/WebCore/loader/DocumentLoader.cpp
Source/WebCore/loader/EmptyClients.cpp
Source/WebCore/loader/EmptyFrameLoaderClient.h
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/FrameLoader.h
Source/WebCore/loader/FrameLoaderClient.h
Source/WebCore/loader/FrameLoaderTypes.h
Source/WebCore/loader/PolicyChecker.cpp
Source/WebKit/ChangeLog
Source/WebKit/Scripts/webkit/messages.py
Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
Source/WebKit/UIProcess/ProvisionalPageProxy.h
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebPageProxy.messages.in
Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h
Source/WebKit/WebProcess/WebPage/WebFrame.cpp
Source/WebKit/WebProcess/WebPage/WebFrame.h
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.h
Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.mm
Source/WebKitLegacy/win/ChangeLog
Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.cpp
Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.h