diff options
author | mbarbella <mbarbella@chromium.org> | 2015-03-06 13:51:14 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-06 21:51:50 +0000 |
commit | e97877bc4f3132e644c4ce88554daafcfb5a284d (patch) | |
tree | 3752949fe1d980b8ead295f85e86997159ee846e | |
parent | 4e0d1372aefe2ffd2d2be9ffc566f97a7a9d3848 (diff) | |
download | chromium_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.cc | 3 | ||||
-rw-r--r-- | chrome/chrome_common.gypi | 7 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 4 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 | ||||
-rw-r--r-- | chrome/common/external_ipc_dumper.cc | 60 | ||||
-rw-r--r-- | chrome/common/external_ipc_dumper.h | 13 | ||||
-rw-r--r-- | chrome/renderer/chrome_content_renderer_client.cc | 14 | ||||
-rw-r--r-- | ipc/ipc_channel_proxy.cc | 16 | ||||
-rw-r--r-- | ipc/ipc_channel_proxy.h | 25 | ||||
-rw-r--r-- | tools/ipc_fuzzer/dump/dump.gyp | 24 | ||||
-rw-r--r-- | tools/ipc_fuzzer/dump/message_dump.cc | 64 | ||||
-rw-r--r-- | tools/ipc_fuzzer/ipc_fuzzer.gyp | 1 |
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', |