From 8be1ff11dc1fae61146dbcfaa38e12314d290dca Mon Sep 17 00:00:00 2001 From: gzobqq Date: Tue, 1 Mar 2016 09:12:01 -0800 Subject: [PATCH] Disallow was_within_same_page = true for a cross-process navigation. BUG=590284 CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_site_isolation Review URL: https://codereview.chromium.org/1738233002 Cr-Commit-Position: refs/heads/master@{#378461} --- content/browser/frame_host/navigator_impl.cc | 13 ++++++++ .../frame_host/navigator_impl_unittest.cc | 30 +++++++++++++++++++ content/test/test_render_frame_host.cc | 4 ++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index 5dad578ed1f396..a176ebc6c12b9e 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc @@ -457,6 +457,19 @@ void NavigatorImpl::DidNavigate( bool is_navigation_within_page = controller_->IsURLInPageNavigation( params.url, params.was_within_same_page, render_frame_host); + + // If a frame claims it navigated within page, it must be the current frame, + // not a pending one. + if (is_navigation_within_page && + render_frame_host != + render_frame_host->frame_tree_node() + ->render_manager() + ->current_frame_host()) { + bad_message::ReceivedBadMessage(render_frame_host->GetProcess(), + bad_message::NC_IN_PAGE_NAVIGATION); + is_navigation_within_page = false; + } + if (ui::PageTransitionIsMainFrame(params.transition)) { if (delegate_) { // When overscroll navigation gesture is enabled, a screenshot of the page diff --git a/content/browser/frame_host/navigator_impl_unittest.cc b/content/browser/frame_host/navigator_impl_unittest.cc index 880e971e2cfb5e..698ccde082240d 100644 --- a/content/browser/frame_host/navigator_impl_unittest.cc +++ b/content/browser/frame_host/navigator_impl_unittest.cc @@ -1191,4 +1191,34 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, } } +namespace { +void SetWithinPage(const GURL& url, + FrameHostMsg_DidCommitProvisionalLoad_Params* params) { + params->was_within_same_page = true; + params->url = url; +} +} + +// A renderer process might try and claim that a cross site navigation was +// within the same page by setting was_within_same_page = true for +// FrameHostMsg_DidCommitProvisionalLoad. Such case should be detected on the +// browser side and the renderer process should be killed. +TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteClaimWithinPage) { + const GURL kUrl1("http://www.chromium.org/"); + const GURL kUrl2("http://www.google.com/"); + + contents()->NavigateAndCommit(kUrl1); + FrameTreeNode* node = main_test_rfh()->frame_tree_node(); + + // Navigate to a different site. + int entry_id = RequestNavigation(node, kUrl2); + main_test_rfh()->PrepareForCommit(); + + // Claim that the navigation was within same page. + int bad_msg_count = process()->bad_msg_count(); + GetSpeculativeRenderFrameHost(node)->SendNavigateWithModificationCallback( + 0, entry_id, true, kUrl2, base::Bind(SetWithinPage, kUrl1)); + EXPECT_EQ(process()->bad_msg_count(), bad_msg_count + 1); +} + } // namespace content diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index f158dbcc40fb58..d805f38ea7c283 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc @@ -271,10 +271,12 @@ void TestRenderFrameHost::SendNavigateWithParameters( ui::PageTransition transition, int response_code, const ModificationCallback& callback) { + if (!IsBrowserSideNavigationEnabled()) + OnDidStartLoading(true); + // DidStartProvisionalLoad may delete the pending entry that holds |url|, // so we keep a copy of it to use below. GURL url_copy(url); - OnDidStartLoading(true); OnDidStartProvisionalLoad(url_copy, base::TimeTicks::Now()); FrameHostMsg_DidCommitProvisionalLoad_Params params;