Index: content/browser/security_exploit_browsertest.cc |
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc |
index c515609c576f74cf8fbc60f1a6e8de11c3a19e90..6714e9a086a737607f6947d6fdf8d1608742ee9e 100644 |
--- a/content/browser/security_exploit_browsertest.cc |
+++ b/content/browser/security_exploit_browsertest.cc |
@@ -23,6 +23,7 @@ |
#include "content/public/browser/content_browser_client.h" |
#include "content/public/browser/interstitial_page.h" |
#include "content/public/browser/interstitial_page_delegate.h" |
+#include "content/public/browser/resource_dispatcher_host.h" |
#include "content/public/browser/storage_partition.h" |
#include "content/public/common/appcache_info.h" |
#include "content/public/common/browser_side_navigation_policy.h" |
@@ -37,6 +38,7 @@ |
#include "ipc/ipc_security_test_util.h" |
#include "net/dns/mock_host_resolver.h" |
#include "net/test/embedded_test_server/embedded_test_server.h" |
+#include "net/test/url_request/url_request_slow_download_job.h" |
using IPC::IpcSecurityTestUtil; |
@@ -44,6 +46,11 @@ namespace content { |
namespace { |
+// This request id is used by tests that craft a |
+// ResourceHostMsg_RequestResource. The id is sufficiently large that it doesn't |
+// collide with ids used by previous navigation requests. |
+const int kRequestIdNotPreviouslyUsed = 10000; |
+ |
// This is a helper function for the tests which attempt to create a |
// duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects |
// with the same process and routing ids, which causes a collision. |
@@ -98,13 +105,11 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell, |
return next_rfh->render_view_host(); |
} |
-ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) { |
+ResourceHostMsg_Request CreateXHRRequest(const char* url) { |
ResourceHostMsg_Request request; |
request.method = "GET"; |
- request.url = GURL("http://bar.com/simple_page.html"); |
- request.first_party_for_cookies = GURL(origin); |
+ request.url = GURL(url); |
request.referrer_policy = blink::WebReferrerPolicyDefault; |
- request.headers = base::StringPrintf("Origin: %s\r\n", origin); |
request.load_flags = 0; |
request.origin_pid = 0; |
request.resource_type = RESOURCE_TYPE_XHR; |
@@ -120,6 +125,49 @@ ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) { |
return request; |
} |
+ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) { |
+ ResourceHostMsg_Request request = |
+ CreateXHRRequest("http://bar.com/simple_page.html"); |
+ request.first_party_for_cookies = GURL(origin); |
+ request.headers = base::StringPrintf("Origin: %s\r\n", origin); |
+ return request; |
+} |
+ |
+void TryCreateDuplicateRequestIds(Shell* shell, bool block_loaders) { |
+ NavigateToURL(shell, GURL("http://foo.com/simple_page.html")); |
+ RenderFrameHost* rfh = shell->web_contents()->GetMainFrame(); |
+ |
+ if (block_loaders) { |
+ // Test the case where loaders are placed into blocked_loaders_map_. |
+ int child_id = rfh->GetProcess()->GetID(); |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&ResourceDispatcherHost::BlockRequestsForRoute, |
+ base::Unretained(ResourceDispatcherHost::Get()), child_id, |
+ rfh->GetRoutingID())); |
+ } |
+ |
+ // URLRequestSlowDownloadJob waits for another request to kFinishDownloadUrl |
+ // to finish all pending requests. It is never sent, so the following URL |
+ // blocks indefinitely, which is good because the request stays alive and the |
+ // test can try to reuse the request id without a race. |
+ const char* blocking_url = net::URLRequestSlowDownloadJob::kUnknownSizeUrl; |
+ ResourceHostMsg_Request request(CreateXHRRequest(blocking_url)); |
+ |
+ // Use the same request id twice. |
+ RenderProcessHostWatcher process_killed( |
+ rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
+ IPC::IpcSecurityTestUtil::PwnMessageReceived( |
+ rfh->GetProcess()->GetChannel(), |
+ ResourceHostMsg_RequestResource(rfh->GetRoutingID(), |
+ kRequestIdNotPreviouslyUsed, request)); |
+ IPC::IpcSecurityTestUtil::PwnMessageReceived( |
+ rfh->GetProcess()->GetChannel(), |
+ ResourceHostMsg_RequestResource(rfh->GetRoutingID(), |
+ kRequestIdNotPreviouslyUsed, request)); |
+ process_killed.Wait(); |
+} |
+ |
} // namespace |
@@ -145,6 +193,12 @@ class SecurityExploitBrowserTest : public ContentBrowserTest { |
",EXCLUDE localhost"); |
} |
+ void SetUpOnMainThread() override { |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler)); |
+ } |
+ |
protected: |
// Tests that a given file path sent in a ViewHostMsg_RunFileChooser will |
// cause renderer to be killed. |
@@ -384,7 +438,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) { |
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
IPC::IpcSecurityTestUtil::PwnMessageReceived( |
web_rfh->GetProcess()->GetChannel(), |
- ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, |
+ ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), |
+ kRequestIdNotPreviouslyUsed, |
chrome_origin_msg)); |
web_process_killed.Wait(); |
} |
@@ -404,7 +459,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) { |
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
IPC::IpcSecurityTestUtil::PwnMessageReceived( |
web_rfh->GetProcess()->GetChannel(), |
- ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, |
+ ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), |
+ kRequestIdNotPreviouslyUsed, |
embedder_isolated_origin_msg)); |
web_process_killed.Wait(); |
SetBrowserClientForTesting(old_client); |
@@ -418,7 +474,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) { |
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
IPC::IpcSecurityTestUtil::PwnMessageReceived( |
web_rfh->GetProcess()->GetChannel(), |
- ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, |
+ ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), |
+ kRequestIdNotPreviouslyUsed, |
invalid_origin_msg)); |
web_process_killed.Wait(); |
} |
@@ -431,10 +488,20 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) { |
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
IPC::IpcSecurityTestUtil::PwnMessageReceived( |
web_rfh->GetProcess()->GetChannel(), |
- ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, |
+ ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), |
+ kRequestIdNotPreviouslyUsed, |
invalid_scheme_origin_msg)); |
web_process_killed.Wait(); |
} |
} |
+// Renderer process should not be able to create multiple requests with the same |
+// id. |
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidRequestId) { |
+ // Existing loader in pending_loaders_. |
+ TryCreateDuplicateRequestIds(shell(), false); |
+ // Existing loader in blocked_loaders_map_. |
+ TryCreateDuplicateRequestIds(shell(), true); |
+} |
+ |
} // namespace content |