diff options
Diffstat (limited to 'content/common')
-rw-r--r-- | content/common/child_process_host.cc | 71 | ||||
-rw-r--r-- | content/common/child_process_host.h | 48 | ||||
-rw-r--r-- | content/common/plugin_carbon_interpose_constants_mac.cc | 2 |
3 files changed, 110 insertions, 11 deletions
diff --git a/content/common/child_process_host.cc b/content/common/child_process_host.cc index 6a14750..02a5bd6 100644 --- a/content/common/child_process_host.cc +++ b/content/common/child_process_host.cc @@ -6,6 +6,7 @@ #include "base/command_line.h" #include "base/file_path.h" +#include "base/logging.h" #include "base/metrics/histogram.h" #include "base/path_service.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" @@ -19,6 +20,52 @@ #include "base/linux_util.h" #endif // OS_LINUX +#if defined(OS_MACOSX) +namespace { + +// Given |path| identifying a Mac-style child process executable path, adjusts +// it to correspond to |feature|. For a child process path such as +// ".../Chromium Helper.app/Contents/MacOS/Chromium Helper", the transformed +// path for feature "NP" would be +// ".../Chromium Helper NP.app/Contents/MacOS/Chromium Helper NP". The new +// path is returned. +FilePath TransformPathForFeature(const FilePath& path, + const std::string& feature) { + std::string basename = path.BaseName().value(); + + FilePath macos_path = path.DirName(); + const char kMacOSName[] = "MacOS"; + DCHECK_EQ(kMacOSName, macos_path.BaseName().value()); + + FilePath contents_path = macos_path.DirName(); + const char kContentsName[] = "Contents"; + DCHECK_EQ(kContentsName, contents_path.BaseName().value()); + + FilePath helper_app_path = contents_path.DirName(); + const char kAppExtension[] = ".app"; + std::string basename_app = basename; + basename_app.append(kAppExtension); + DCHECK_EQ(basename_app, helper_app_path.BaseName().value()); + + FilePath root_path = helper_app_path.DirName(); + + std::string new_basename = basename; + new_basename.append(1, ' '); + new_basename.append(feature); + std::string new_basename_app = new_basename; + new_basename_app.append(kAppExtension); + + FilePath new_path = root_path.Append(new_basename_app) + .Append(kContentsName) + .Append(kMacOSName) + .Append(new_basename); + + return new_path; +} + +} // namespace +#endif // OS_MACOSX + ChildProcessHost::ChildProcessHost() : ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)), opening_channel_(false) { @@ -39,7 +86,7 @@ void ChildProcessHost::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { } // static -FilePath ChildProcessHost::GetChildPath(bool allow_self) { +FilePath ChildProcessHost::GetChildPath(int flags) { FilePath child_path; child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath( @@ -53,13 +100,33 @@ FilePath ChildProcessHost::GetChildPath(bool allow_self) { // When running under Valgrind, forking /proc/self/exe ends up forking the // Valgrind executable, which then crashes. However, it's almost safe to // assume that the updates won't happen while testing with Valgrind tools. - if (allow_self && !RunningOnValgrind()) + if (flags & CHILD_ALLOW_SELF && !RunningOnValgrind()) return FilePath("/proc/self/exe"); #endif // On most platforms, the child executable is the same as the current // executable. PathService::Get(content::CHILD_PROCESS_EXE, &child_path); + +#if defined(OS_MACOSX) + DCHECK(!(flags & CHILD_NO_PIE && flags & CHILD_ALLOW_HEAP_EXECUTION)); + + // If needed, choose an executable with special flags set that inform the + // kernel to enable or disable specific optional process-wide features. + if (flags & CHILD_NO_PIE) { + // "NP" is "No PIE". This results in Chromium Helper NP.app or + // Google Chrome Helper NP.app. + child_path = TransformPathForFeature(child_path, "NP"); + } else if (flags & CHILD_ALLOW_HEAP_EXECUTION) { + // "EH" is "Executable Heap". A non-executable heap is only available to + // 32-bit processes on Mac OS X 10.7. Most code can and should run with a + // non-executable heap, but the "EH" feature is provided to allow code + // intolerant of a non-executable heap to work properly on 10.7. This + // results in Chromium Helper EH.app or Google Chrome Helper EH.app. + child_path = TransformPathForFeature(child_path, "EH"); + } +#endif + return child_path; } diff --git a/content/common/child_process_host.h b/content/common/child_process_host.h index 7fd7082..8637c18 100644 --- a/content/common/child_process_host.h +++ b/content/common/child_process_host.h @@ -33,6 +33,42 @@ class Message; class ChildProcessHost : public IPC::Channel::Listener, public IPC::Message::Sender { public: + + // These flags may be passed to GetChildPath in order to alter its behavior, + // causing it to return a child path more suited to a specific task. + enum { + // No special behavior requested. + CHILD_NORMAL = 0, + +#if defined(OS_LINUX) + // Indicates that the child execed after forking may be execced from + // /proc/self/exe rather than using the "real" app path. This prevents + // autoupdate from confusing us if it changes the file out from under us. + // You will generally want to set this on Linux, except when there is an + // override to the command line (for example, we're forking a renderer in + // gdb). In this case, you'd use GetChildPath to get the real executable + // file name, and then prepend the GDB command to the command line. + CHILD_ALLOW_SELF = 1 << 0, +#elif defined(OS_MACOSX) + + // Requests that the child run in a process that does not have the + // PIE (position-independent executable) bit set, effectively disabling + // ASLR. For process types that need to allocate a large contiguous + // region, ASLR may not leave a large enough "hole" for the purpose. This + // option should be used sparingly, and only when absolutely necessary. + // This option is currently incompatible with CHILD_ALLOW_HEAP_EXECUTION. + CHILD_NO_PIE = 1 << 1, + + // Requests that the child run in a process that does not protect the + // heap against execution. Normally, heap pages may be made executable + // with mprotect, so this mode should be used sparingly. It is intended + // for processes that may host plug-ins that expect an executable heap + // without having to call mprotect. This option is currently incompatible + // with CHILD_NO_PIE. + CHILD_ALLOW_HEAP_EXECUTION = 1 << 2, +#endif + }; + virtual ~ChildProcessHost(); // Returns the pathname to be used for a child process. If a subprocess @@ -40,16 +76,12 @@ class ChildProcessHost : public IPC::Channel::Listener, // the default child process pathname will be returned. On most platforms, // this will be the same as the currently-executing process. // - // The argument allow_self is used on Linux to indicate that we allow us to - // fork from /proc/self/exe rather than using the "real" app path. This - // prevents autoupdate from confusing us if it changes the file out from - // under us. You will generally want to set this to true, except when there - // is an override to the command line (for example, we're forking a renderer - // in gdb). In this case, you'd use GetChildPath to get the real executable - // file name, and then prepend the GDB command to the command line. + // The |flags| argument accepts one or more flags such as CHILD_ALLOW_SELF + // and CHILD_ALLOW_HEAP_EXECUTION as defined above. Pass only CHILD_NORMAL + // if none of these special behaviors are required. // // On failure, returns an empty FilePath. - static FilePath GetChildPath(bool allow_self); + static FilePath GetChildPath(int flags); #if defined(OS_WIN) // See comments in the cc file. This is a common hack needed for a process diff --git a/content/common/plugin_carbon_interpose_constants_mac.cc b/content/common/plugin_carbon_interpose_constants_mac.cc index 956d6fc..2ff5dd0 100644 --- a/content/common/plugin_carbon_interpose_constants_mac.cc +++ b/content/common/plugin_carbon_interpose_constants_mac.cc @@ -10,7 +10,7 @@ namespace plugin_interpose_strings { const char kDYLDInsertLibrariesKey[] = "DYLD_INSERT_LIBRARIES"; const char kInterposeLibraryPath[] = - "@executable_path/libplugin_carbon_interpose.dylib"; + "@executable_path/../../../libplugin_carbon_interpose.dylib"; } // namespace plugin_interpose_strings |