summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormbarbella <mbarbella@chromium.org>2015-03-06 13:51:14 -0800
committerCommit bot <commit-bot@chromium.org>2015-03-06 21:51:50 +0000
commite97877bc4f3132e644c4ce88554daafcfb5a284d (patch)
tree3752949fe1d980b8ead295f85e86997159ee846e
parent4e0d1372aefe2ffd2d2be9ffc566f97a7a9d3848 (diff)
downloadchromium_src-e97877bc4f3132e644c4ce88554daafcfb5a284d.zip
chromium_src-e97877bc4f3132e644c4ce88554daafcfb5a284d.tar.gz
chromium_src-e97877bc4f3132e644c4ce88554daafcfb5a284d.tar.bz2
Add a flag to dump IPC messages sent from the renderer to the browser.
BUG=450268 Review URL: https://codereview.chromium.org/975903002 Cr-Commit-Position: refs/heads/master@{#319514}
-rw-r--r--chrome/browser/chrome_content_browser_client.cc3
-rw-r--r--chrome/chrome_common.gypi7
-rw-r--r--chrome/common/chrome_switches.cc4
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/common/external_ipc_dumper.cc60
-rw-r--r--chrome/common/external_ipc_dumper.h13
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc14
-rw-r--r--ipc/ipc_channel_proxy.cc16
-rw-r--r--ipc/ipc_channel_proxy.h25
-rw-r--r--tools/ipc_fuzzer/dump/dump.gyp24
-rw-r--r--tools/ipc_fuzzer/dump/message_dump.cc64
-rw-r--r--tools/ipc_fuzzer/ipc_fuzzer.gyp1
12 files changed, 230 insertions, 2 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index bfa6e90..f7c3c618 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1327,7 +1327,8 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
#if defined(ENABLE_IPC_FUZZER)
static const char* const kIpcFuzzerSwitches[] = {
- switches::kIpcFuzzerTestcase,
+ switches::kIpcDumpDirectory,
+ switches::kIpcFuzzerTestcase,
};
command_line->CopySwitchesFrom(browser_command_line, kIpcFuzzerSwitches,
arraysize(kIpcFuzzerSwitches));
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 6a80c5b..f6d26aa 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -239,6 +239,10 @@
'common/importer/safari_importer_utils.h',
'common/importer/safari_importer_utils.mm',
],
+ 'chrome_common_ipc_fuzzer_sources': [
+ 'common/external_ipc_dumper.h',
+ 'common/external_ipc_dumper.cc',
+ ],
'chrome_common_service_process_sources': [
'common/service_messages.h',
'common/service_process_util.cc',
@@ -412,6 +416,9 @@
'<(DEPTH)/components/nacl.gyp:nacl_common',
],
}],
+ ['enable_ipc_fuzzer==1', {
+ 'sources': [ '<@(chrome_common_ipc_fuzzer_sources)' ],
+ }],
['enable_plugins==1', {
'dependencies': [
'<(DEPTH)/third_party/adobe/flash/flash_player.gyp:flapper_version_h',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 51286267..f09a1f9 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -735,6 +735,10 @@ const char kDisableJavaScriptHarmonyShipping[] =
// Enables experimental Harmony (ECMAScript 6) features.
const char kJavaScriptHarmony[] = "javascript-harmony";
+// Dumps IPC messages sent from renderer processes to the browser process to
+// the given directory. Used primarily to gather samples for IPC fuzzing.
+const char kIpcDumpDirectory[] = "ipc-dump-directory";
+
// Specifies the testcase used by the IPC fuzzer.
const char kIpcFuzzerTestcase[] = "ipc-fuzzer-testcase";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 448689a..214e92e 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -206,6 +206,7 @@ extern const char kInstallEphemeralAppFromWebstore[];
extern const char kInstallSupervisedUserWhitelists[];
extern const char kInstantProcess[];
extern const char kInvalidationUseGCMChannel[];
+extern const char kIpcDumpDirectory[];
extern const char kIpcFuzzerTestcase[];
extern const char kJavaScriptHarmony[];
extern const char kKeepAliveForTest[];
diff --git a/chrome/common/external_ipc_dumper.cc b/chrome/common/external_ipc_dumper.cc
new file mode 100644
index 0000000..3b9bbbb
--- /dev/null
+++ b/chrome/common/external_ipc_dumper.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/native_library.h"
+#include "base/path_service.h"
+#include "chrome/common/external_ipc_dumper.h"
+
+typedef IPC::ChannelProxy::OutgoingMessageFilter* (*GetFilterFunction)();
+typedef void (*SetDumpDirectoryFunction)(const base::FilePath&);
+
+const char kFilterEntryName[] = "GetFilter";
+const char kSetDumpDirectoryEntryName[] = "SetDumpDirectory";
+
+#if defined(OS_WIN)
+#define IPC_MESSAGE_DUMP_MODULE FILE_PATH_LITERAL("ipc_message_dump.dll")
+#else
+#define IPC_MESSAGE_DUMP_MODULE FILE_PATH_LITERAL("libipc_message_dump.so")
+#endif
+
+IPC::ChannelProxy::OutgoingMessageFilter* LoadExternalIPCDumper(
+ const base::FilePath& dump_directory) {
+ base::FilePath module_path;
+ if (!PathService::Get(base::DIR_MODULE, &module_path)) {
+ LOG(ERROR) << "Unable to get message dump module directory.";
+ return NULL;
+ }
+
+ base::FilePath library_path = module_path.Append(IPC_MESSAGE_DUMP_MODULE);
+ base::NativeLibraryLoadError load_error;
+ base::NativeLibrary library =
+ base::LoadNativeLibrary(library_path, &load_error);
+
+ if (!library) {
+ LOG(ERROR) << load_error.ToString();
+ return NULL;
+ }
+
+ SetDumpDirectoryFunction set_directory_entry_point =
+ reinterpret_cast<SetDumpDirectoryFunction>(
+ base::GetFunctionPointerFromNativeLibrary(
+ library, kSetDumpDirectoryEntryName));
+ if (!set_directory_entry_point) {
+ LOG(ERROR) << kSetDumpDirectoryEntryName
+ << " not exported by message dump module.";
+ return NULL;
+ }
+ set_directory_entry_point(dump_directory);
+
+ GetFilterFunction filter_entry_point = reinterpret_cast<GetFilterFunction>(
+ base::GetFunctionPointerFromNativeLibrary(library, kFilterEntryName));
+ if (!filter_entry_point) {
+ LOG(ERROR) << kFilterEntryName << " not exported by message dump module.";
+ return NULL;
+ }
+
+ return filter_entry_point();
+}
diff --git a/chrome/common/external_ipc_dumper.h b/chrome/common/external_ipc_dumper.h
new file mode 100644
index 0000000..fd6f6a2
--- /dev/null
+++ b/chrome/common/external_ipc_dumper.h
@@ -0,0 +1,13 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_EXTERNAL_IPC_DUMPER_H_
+#define CHROME_COMMON_EXTERNAL_IPC_DUMPER_H_
+
+#include "ipc/ipc_channel_proxy.h"
+
+IPC::ChannelProxy::OutgoingMessageFilter* LoadExternalIPCDumper(
+ const base::FilePath& dump_directory);
+
+#endif // CHROME_COMMON_EXTERNAL_IPC_DUMPER_H_
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index f7a40cb..756f342 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -127,6 +127,10 @@
#include "extensions/renderer/script_context.h"
#endif
+#if defined(ENABLE_IPC_FUZZER)
+#include "chrome/common/external_ipc_dumper.h"
+#endif
+
#if defined(ENABLE_PRINTING)
#include "chrome/renderer/printing/chrome_print_web_view_helper_delegate.h"
#include "components/printing/renderer/print_web_view_helper.h"
@@ -466,6 +470,16 @@ void ChromeContentRendererClient::RenderThreadStarted() {
WebSecurityPolicy::registerURLSchemeAsLocal(external_file_scheme);
#endif
+#if defined(ENABLE_IPC_FUZZER)
+ if (command_line->HasSwitch(switches::kIpcDumpDirectory)) {
+ base::FilePath dump_directory =
+ command_line->GetSwitchValuePath(switches::kIpcDumpDirectory);
+ IPC::ChannelProxy::OutgoingMessageFilter* filter =
+ LoadExternalIPCDumper(dump_directory);
+ thread->GetChannel()->set_outgoing_message_filter(filter);
+ }
+#endif
+
// chrome: and chrome-search: pages should not be accessible by bookmarklets
// or javascript: URLs typed in the omnibox.
WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs(
diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc
index 37be200..66b6686 100644
--- a/ipc/ipc_channel_proxy.cc
+++ b/ipc/ipc_channel_proxy.cc
@@ -252,7 +252,7 @@ void ChannelProxy::Context::AddFilter(MessageFilter* filter) {
// Called on the listener's thread
void ChannelProxy::Context::OnDispatchMessage(const Message& message) {
-#ifdef IPC_MESSAGE_LOG_ENABLED
+#if defined(IPC_MESSAGE_LOG_ENABLED)
Logging* logger = Logging::GetInstance();
std::string name;
logger->GetMessageText(message.type(), &name, &message, NULL);
@@ -337,12 +337,18 @@ scoped_ptr<ChannelProxy> ChannelProxy::Create(
ChannelProxy::ChannelProxy(Context* context)
: context_(context),
did_init_(false) {
+#if defined(ENABLE_IPC_FUZZER)
+ outgoing_message_filter_ = NULL;
+#endif
}
ChannelProxy::ChannelProxy(
Listener* listener,
const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
: context_(new Context(listener, ipc_task_runner)), did_init_(false) {
+#if defined(ENABLE_IPC_FUZZER)
+ outgoing_message_filter_ = NULL;
+#endif
}
ChannelProxy::~ChannelProxy() {
@@ -411,6 +417,14 @@ bool ChannelProxy::Send(Message* message) {
// TODO(alexeypa): add DCHECK(CalledOnValidThread()) here. Currently there are
// tests that call Send() from a wrong thread. See http://crbug.com/163523.
+#ifdef ENABLE_IPC_FUZZER
+ // In IPC fuzzing builds, it is possible to define a filter to apply to
+ // outgoing messages. It will either rewrite the message and return a new
+ // one, freeing the original, or return the message unchanged.
+ if (outgoing_message_filter())
+ message = outgoing_message_filter()->Rewrite(message);
+#endif
+
#ifdef IPC_MESSAGE_LOG_ENABLED
Logging::GetInstance()->OnSendMessage(message, context_->channel_id());
#endif
diff --git a/ipc/ipc_channel_proxy.h b/ipc/ipc_channel_proxy.h
index a660aeb..0ac2fa9 100644
--- a/ipc/ipc_channel_proxy.h
+++ b/ipc/ipc_channel_proxy.h
@@ -57,6 +57,15 @@ class SendCallbackHelper;
//
class IPC_EXPORT ChannelProxy : public Sender, public base::NonThreadSafe {
public:
+#if defined(ENABLE_IPC_FUZZER)
+ // Interface for a filter to be imposed on outgoing messages which can
+ // re-write the message. Used for testing.
+ class OutgoingMessageFilter {
+ public:
+ virtual Message* Rewrite(Message* message) = 0;
+ };
+#endif
+
// Initializes a channel proxy. The channel_handle and mode parameters are
// passed directly to the underlying IPC::Channel. The listener is called on
// the thread that creates the ChannelProxy. The filter's OnMessageReceived
@@ -112,6 +121,12 @@ class IPC_EXPORT ChannelProxy : public Sender, public base::NonThreadSafe {
void AddFilter(MessageFilter* filter);
void RemoveFilter(MessageFilter* filter);
+#if defined(ENABLE_IPC_FUZZER)
+ void set_outgoing_message_filter(OutgoingMessageFilter* filter) {
+ outgoing_message_filter_ = filter;
+ }
+#endif
+
// Set the task runner on which dispatched messages are posted. Both the new
// task runner and the existing task runner must run on the same thread, and
// must belong to the calling thread.
@@ -232,6 +247,12 @@ class IPC_EXPORT ChannelProxy : public Sender, public base::NonThreadSafe {
Context* context() { return context_.get(); }
+#if defined(ENABLE_IPC_FUZZER)
+ OutgoingMessageFilter* outgoing_message_filter() const {
+ return outgoing_message_filter_;
+ }
+#endif
+
private:
friend class IpcSecurityTestUtil;
@@ -242,6 +263,10 @@ class IPC_EXPORT ChannelProxy : public Sender, public base::NonThreadSafe {
// Whether the channel has been initialized.
bool did_init_;
+
+#if defined(ENABLE_IPC_FUZZER)
+ OutgoingMessageFilter* outgoing_message_filter_;
+#endif
};
} // namespace IPC
diff --git a/tools/ipc_fuzzer/dump/dump.gyp b/tools/ipc_fuzzer/dump/dump.gyp
new file mode 100644
index 0000000..ac64e9e
--- /dev/null
+++ b/tools/ipc_fuzzer/dump/dump.gyp
@@ -0,0 +1,24 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [
+ {
+ 'target_name': 'ipc_message_dump',
+ 'type': 'loadable_module',
+ 'dependencies': [
+ '../message_lib/message_lib.gyp:ipc_message_lib',
+ ],
+ 'sources': [
+ 'message_dump.cc',
+ ],
+ 'include_dirs': [
+ '../../..',
+ ],
+ },
+ ],
+}
diff --git a/tools/ipc_fuzzer/dump/message_dump.cc b/tools/ipc_fuzzer/dump/message_dump.cc
new file mode 100644
index 0000000..5fd5a06
--- /dev/null
+++ b/tools/ipc_fuzzer/dump/message_dump.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/files/file_path.h"
+#include "base/process/process.h"
+#include "base/strings/string_number_conversions.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "tools/ipc_fuzzer/message_lib/message_file.h"
+
+#if defined(OS_WIN)
+#define PidToStringType base::UintToString16
+#define MESSAGE_DUMP_EXPORT __declspec(dllexport)
+#else
+#define PidToStringType base::IntToString
+#define MESSAGE_DUMP_EXPORT __attribute__((visibility("default")))
+#endif
+
+namespace ipc_fuzzer {
+
+class IPCDump : public IPC::ChannelProxy::OutgoingMessageFilter {
+ public:
+ ~IPCDump() {
+ base::FilePath::StringType pid_string =
+ PidToStringType(base::Process::Current().Pid());
+ base::FilePath output_file_path =
+ dump_directory().Append(pid_string + FILE_PATH_LITERAL(".ipcdump"));
+
+ MessageFile::Write(output_file_path, messages_);
+ }
+
+ IPC::Message* Rewrite(IPC::Message* message) override {
+ messages_.push_back(new IPC::Message(*message));
+ return message;
+ }
+
+ base::FilePath dump_directory() const { return dump_directory_; }
+
+ void set_dump_directory(const base::FilePath& dump_directory) {
+ dump_directory_ = dump_directory;
+ }
+
+ private:
+ MessageVector messages_;
+ base::FilePath dump_directory_;
+};
+
+IPCDump g_ipcdump;
+
+} // namespace ipc_fuzzer
+
+// Entry point avoiding mangled names.
+extern "C" {
+MESSAGE_DUMP_EXPORT IPC::ChannelProxy::OutgoingMessageFilter* GetFilter(void);
+MESSAGE_DUMP_EXPORT void SetDumpDirectory(const base::FilePath& dump_directory);
+}
+
+IPC::ChannelProxy::OutgoingMessageFilter* GetFilter(void) {
+ return &ipc_fuzzer::g_ipcdump;
+}
+
+void SetDumpDirectory(const base::FilePath& dump_directory) {
+ ipc_fuzzer::g_ipcdump.set_dump_directory(dump_directory);
+}
diff --git a/tools/ipc_fuzzer/ipc_fuzzer.gyp b/tools/ipc_fuzzer/ipc_fuzzer.gyp
index ba431f7..916c1a7 100644
--- a/tools/ipc_fuzzer/ipc_fuzzer.gyp
+++ b/tools/ipc_fuzzer/ipc_fuzzer.gyp
@@ -11,6 +11,7 @@
'target_name': 'ipc_fuzzer',
'type': 'none',
'dependencies': [
+ 'dump/dump.gyp:ipc_message_dump',
'ipclist/ipclist.gyp:ipclist',
'mutate/mutate.gyp:ipc_fuzzer_mutate',
'mutate/mutate.gyp:ipc_fuzzer_generate',