summaryrefslogtreecommitdiffstats
path: root/content/common
diff options
context:
space:
mode:
Diffstat (limited to 'content/common')
-rw-r--r--content/common/child_process_host.cc71
-rw-r--r--content/common/child_process_host.h48
-rw-r--r--content/common/plugin_carbon_interpose_constants_mac.cc2
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