Commit 8f1b1a70 authored by Marijn Kruisselbrink's avatar Marijn Kruisselbrink Committed by Commit Bot

Refactor ChromeSecurityExploitBrowserTest to also work with mojo blob URLs.

Or to be more precise, add a version of the CreateBlobInExtensionOrigin
test that uses the mojo blob URL code path.

Bug: 777585
Change-Id: Ife85fd3880994b2c2634dc7dbf54581ec0b7e30e
Reviewed-on: https://chromium-review.googlesource.com/882560Reviewed-by: default avatarNasko Oskov <nasko@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@chromium.org>
Reviewed-by: default avatarDaniel Murphy <dmurph@chromium.org>
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#532016}
parent 18e10dc0
...@@ -22,8 +22,11 @@ ...@@ -22,8 +22,11 @@
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h" #include "content/public/test/browser_test_utils.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "net/dns/mock_host_resolver.h" #include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/embedded_test_server.h"
#include "storage/browser/blob/blob_registry_impl.h"
#include "third_party/WebKit/common/blob/blob_url_store.mojom.h"
// The goal of these tests is to "simulate" exploited renderer processes, which // The goal of these tests is to "simulate" exploited renderer processes, which
// can send arbitrary IPC messages and confuse browser process internal state, // can send arbitrary IPC messages and confuse browser process internal state,
...@@ -211,3 +214,83 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTest, ...@@ -211,3 +214,83 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTest,
"ERR_FILE_NOT_FOUND\n", "ERR_FILE_NOT_FOUND\n",
body); body);
} }
namespace {
class BlobURLStoreInterceptor
: public blink::mojom::BlobURLStoreInterceptorForTesting {
public:
explicit BlobURLStoreInterceptor(GURL target_url) : target_url_(target_url) {}
void Intercept(
mojo::StrongAssociatedBindingPtr<blink::mojom::BlobURLStore> binding) {
url_store_ = binding->SwapImplForTesting(this);
}
blink::mojom::BlobURLStore* GetForwardingInterface() override {
return url_store_;
}
void Register(blink::mojom::BlobPtr blob,
const GURL& url,
RegisterCallback callback) override {
GetForwardingInterface()->Register(std::move(blob), target_url_,
std::move(callback));
}
private:
blink::mojom::BlobURLStore* url_store_;
GURL target_url_;
};
} // namespace
class ChromeSecurityExploitBrowserTestMojoBlobURLs
: public ChromeSecurityExploitBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
ChromeSecurityExploitBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
"MojoBlobURLs");
}
void TearDown() override {
storage::BlobRegistryImpl::SetURLStoreCreationHookForTesting(nullptr);
}
};
// Extension isolation prevents a normal renderer process from being able to
// create a "blob:chrome-extension://" resource.
IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTestMojoBlobURLs,
CreateBlobInExtensionOrigin) {
// Target an extension.
std::string target_origin = "chrome-extension://" + extension()->id();
std::string blob_path = "5881f76e-10d2-410d-8c61-ef210502acfd";
BlobURLStoreInterceptor interceptor(
GURL("blob:" + target_origin + "/" + blob_path));
auto intercept_hook = base::BindRepeating(&BlobURLStoreInterceptor::Intercept,
base::Unretained(&interceptor));
storage::BlobRegistryImpl::SetURLStoreCreationHookForTesting(&intercept_hook);
ui_test_utils::NavigateToURL(
browser(),
embedded_test_server()->GetURL("a.root-servers.net", "/title1.html"));
content::RenderFrameHost* rfh =
browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
base::HistogramTester histograms;
content::RenderProcessHostWatcher crash_observer(
rfh->GetProcess(),
content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
// The renderer should always get killed, but sometimes ExecuteScript returns
// true anyway, so just ignore the result.
ignore_result(
content::ExecuteScript(rfh, "URL.createObjectURL(new Blob(['foo']))"));
// If the process is killed, this test passes.
crash_observer.Wait();
histograms.ExpectUniqueSample("Stability.BadMessageTerminated.Content", 123,
1);
}
...@@ -43,6 +43,9 @@ using StrongAssociatedBindingPtr = ...@@ -43,6 +43,9 @@ using StrongAssociatedBindingPtr =
template <typename Interface> template <typename Interface>
class StrongAssociatedBinding { class StrongAssociatedBinding {
public: public:
using ImplPointerType =
typename AssociatedBinding<Interface>::ImplPointerType;
// Create a new StrongAssociatedBinding instance. The instance owns itself, // Create a new StrongAssociatedBinding instance. The instance owns itself,
// cleaning up only in the event of a pipe connection error. Returns a WeakPtr // cleaning up only in the event of a pipe connection error. Returns a WeakPtr
// to the new StrongAssociatedBinding instance. // to the new StrongAssociatedBinding instance.
...@@ -82,6 +85,11 @@ class StrongAssociatedBinding { ...@@ -82,6 +85,11 @@ class StrongAssociatedBinding {
// stimulus. // stimulus.
void FlushForTesting() { binding_.FlushForTesting(); } void FlushForTesting() { binding_.FlushForTesting(); }
// Allows test code to swap the interface implementation.
ImplPointerType SwapImplForTesting(ImplPointerType new_impl) {
return binding_.SwapImplForTesting(new_impl);
}
private: private:
StrongAssociatedBinding(std::unique_ptr<Interface> impl, StrongAssociatedBinding(std::unique_ptr<Interface> impl,
AssociatedInterfaceRequest<Interface> request) AssociatedInterfaceRequest<Interface> request)
......
...@@ -22,6 +22,8 @@ namespace { ...@@ -22,6 +22,8 @@ namespace {
using MemoryStrategy = BlobMemoryController::Strategy; using MemoryStrategy = BlobMemoryController::Strategy;
BlobRegistryImpl::URLStoreCreationHook* g_url_store_creation_hook = nullptr;
} // namespace } // namespace
class BlobRegistryImpl::BlobUnderConstruction { class BlobRegistryImpl::BlobUnderConstruction {
...@@ -562,9 +564,17 @@ void BlobRegistryImpl::URLStoreForOrigin( ...@@ -562,9 +564,17 @@ void BlobRegistryImpl::URLStoreForOrigin(
// that origin. // that origin.
Delegate* delegate = bindings_.dispatch_context().get(); Delegate* delegate = bindings_.dispatch_context().get();
DCHECK(delegate); DCHECK(delegate);
mojo::MakeStrongAssociatedBinding( auto binding = mojo::MakeStrongAssociatedBinding(
std::make_unique<BlobURLStoreImpl>(context_, delegate), std::make_unique<BlobURLStoreImpl>(context_, delegate),
std::move(request)); std::move(request));
if (g_url_store_creation_hook)
g_url_store_creation_hook->Run(binding);
}
// static
void BlobRegistryImpl::SetURLStoreCreationHookForTesting(
URLStoreCreationHook* hook) {
g_url_store_creation_hook = hook;
} }
} // namespace storage } // namespace storage
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_context.h"
#include "storage/browser/storage_browser_export.h" #include "storage/browser/storage_browser_export.h"
#include "third_party/WebKit/common/blob/blob_registry.mojom.h" #include "third_party/WebKit/common/blob/blob_registry.mojom.h"
...@@ -53,6 +54,10 @@ class STORAGE_EXPORT BlobRegistryImpl : public blink::mojom::BlobRegistry { ...@@ -53,6 +54,10 @@ class STORAGE_EXPORT BlobRegistryImpl : public blink::mojom::BlobRegistry {
return blobs_under_construction_.size(); return blobs_under_construction_.size();
} }
using URLStoreCreationHook = base::RepeatingCallback<void(
mojo::StrongAssociatedBindingPtr<blink::mojom::BlobURLStore>)>;
static void SetURLStoreCreationHookForTesting(URLStoreCreationHook* hook);
private: private:
class BlobUnderConstruction; class BlobUnderConstruction;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment