Index: mojo/runner/host/child_process.cc |
diff --git a/mojo/runner/host/child_process.cc b/mojo/runner/host/child_process.cc |
index 8d2ab952cf7b9bff0d1cd3feeca39bcb53b22695..7c157b68827d7ae4ab6e5089faa63c8ada0c60d8 100644 |
--- a/mojo/runner/host/child_process.cc |
+++ b/mojo/runner/host/child_process.cc |
@@ -21,6 +21,8 @@ |
#include "base/thread_task_runner_handle.h" |
#include "base/threading/thread.h" |
#include "base/threading/thread_checker.h" |
+#include "mojo/edk/embedder/embedder.h" |
+#include "mojo/edk/embedder/platform_channel_pair.h" |
#include "mojo/message_pump/message_pump_mojo.h" |
#include "mojo/public/cpp/bindings/binding.h" |
#include "mojo/public/cpp/system/core.h" |
@@ -44,6 +46,10 @@ namespace runner { |
namespace { |
+void DidCreateChannel(embedder::ChannelInfo* channel_info) { |
+ DVLOG(2) << "ChildControllerImpl::DidCreateChannel()"; |
+} |
+ |
// Blocker --------------------------------------------------------------------- |
// Blocks a thread until another thread unblocks it, at which point it unblocks |
@@ -102,6 +108,10 @@ class AppContext : public embedder::ProcessDelegate { |
~AppContext() override {} |
void Init() { |
+#if defined(OS_WIN) |
+ embedder::PreInitializeChildProcess(); |
+#endif |
+ |
// Initialize Mojo before starting any threads. |
embedder::Init(); |
@@ -193,22 +203,16 @@ class ChildControllerImpl : public ChildController { |
// etc. |
static void Init(AppContext* app_context, |
base::NativeLibrary app_library, |
- embedder::ScopedPlatformHandle platform_channel, |
+ ScopedMessagePipeHandle host_message_pipe, |
const Blocker::Unblocker& unblocker) { |
DCHECK(app_context); |
- DCHECK(platform_channel.is_valid()); |
+ DCHECK(host_message_pipe.is_valid()); |
DCHECK(!app_context->controller()); |
scoped_ptr<ChildControllerImpl> impl( |
new ChildControllerImpl(app_context, app_library, unblocker)); |
- ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel( |
- platform_channel.Pass(), |
- base::Bind(&ChildControllerImpl::DidCreateChannel, |
- base::Unretained(impl.get())), |
- base::ThreadTaskRunnerHandle::Get())); |
- |
impl->Bind(host_message_pipe.Pass()); |
app_context->set_controller(impl.Pass()); |
@@ -251,13 +255,6 @@ class ChildControllerImpl : public ChildController { |
binding_.set_connection_error_handler([this]() { OnConnectionError(); }); |
} |
- // Callback for |embedder::CreateChannel()|. |
- void DidCreateChannel(embedder::ChannelInfo* channel_info) { |
- DVLOG(2) << "ChildControllerImpl::DidCreateChannel()"; |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- channel_info_ = channel_info; |
- } |
- |
static void StartAppOnMainThread( |
base::NativeLibrary app_library, |
InterfaceRequest<Application> application_request) { |
@@ -278,6 +275,69 @@ class ChildControllerImpl : public ChildController { |
DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl); |
}; |
+#if defined(OS_LINUX) && !defined(OS_ANDROID) |
+scoped_ptr<mojo::runner::LinuxSandbox> InitializeSandbox() { |
+ using sandbox::syscall_broker::BrokerFilePermission; |
+ // Warm parts of base in the copy of base in the mojo runner. |
+ base::RandUint64(); |
+ base::SysInfo::AmountOfPhysicalMemory(); |
+ base::SysInfo::MaxSharedMemorySize(); |
+ base::SysInfo::NumberOfProcessors(); |
+ |
+ // TODO(erg,jln): Allowing access to all of /dev/shm/ makes it easy to |
+ // spy on other shared memory using processes. This is a temporary hack |
+ // so that we have some sandbox until we have proper shared memory |
+ // support integrated into mojo. |
+ std::vector<BrokerFilePermission> permissions; |
+ permissions.push_back( |
+ BrokerFilePermission::ReadWriteCreateUnlinkRecursive("/dev/shm/")); |
+ scoped_ptr<mojo::runner::LinuxSandbox> sandbox( |
+ new mojo::runner::LinuxSandbox(permissions)); |
+ sandbox->Warmup(); |
+ sandbox->EngageNamespaceSandbox(); |
+ sandbox->EngageSeccompSandbox(); |
+ sandbox->Seal(); |
+ return sandbox.Pass(); |
+} |
+#endif |
+ |
+ScopedMessagePipeHandle InitializeHostMessagePipe( |
+ embedder::ScopedPlatformHandle platform_channel, |
+ scoped_refptr<base::TaskRunner> io_task_runner) { |
+ ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel( |
+ platform_channel.Pass(), base::Bind(&DidCreateChannel), io_task_runner)); |
+ |
+#if defined(OS_WIN) |
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) { |
+ // When using the new Mojo EDK, each message pipe is backed by a platform |
+ // handle. The one platform handle that comes on the command line is used |
+ // to bind to the ChildController interface. However we also want a |
+ // platform handle to setup the communication channel by which we exchange |
+ // handles to/from tokens, which is needed for sandboxed Windows |
+ // processes. |
+ char token_serializer_handle[10]; |
+ MojoHandleSignalsState state; |
+ MojoResult rv = |
+ MojoWait(host_message_pipe.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |
+ MOJO_DEADLINE_INDEFINITE, &state); |
+ CHECK_EQ(MOJO_RESULT_OK, rv); |
+ uint32_t num_bytes = arraysize(token_serializer_handle); |
+ rv = MojoReadMessage(host_message_pipe.get().value(), |
+ token_serializer_handle, &num_bytes, nullptr, 0, |
+ MOJO_READ_MESSAGE_FLAG_NONE); |
+ CHECK_EQ(MOJO_RESULT_OK, rv); |
+ |
+ edk::ScopedPlatformHandle token_serializer_channel = |
+ edk::PlatformChannelPair::PassClientHandleFromParentProcessFromString( |
+ std::string(token_serializer_handle, num_bytes)); |
+ CHECK(token_serializer_channel.is_valid()); |
+ embedder::SetParentPipeHandle(token_serializer_channel.release().handle); |
+ } |
+#endif |
+ |
+ return host_message_pipe.Pass(); |
+} |
+ |
} // namespace |
int ChildProcessMain() { |
@@ -286,41 +346,19 @@ int ChildProcessMain() { |
*base::CommandLine::ForCurrentProcess(); |
#if defined(OS_LINUX) && !defined(OS_ANDROID) |
- using sandbox::syscall_broker::BrokerFilePermission; |
scoped_ptr<mojo::runner::LinuxSandbox> sandbox; |
#endif |
base::NativeLibrary app_library = 0; |
- if (command_line.HasSwitch(switches::kChildProcess)) { |
- // Load the application library before we engage the sandbox. |
- app_library = mojo::runner::LoadNativeApplication( |
- command_line.GetSwitchValuePath(switches::kChildProcess)); |
- |
- base::i18n::InitializeICU(); |
- CallLibraryEarlyInitialization(app_library); |
+ // Load the application library before we engage the sandbox. |
+ app_library = mojo::runner::LoadNativeApplication( |
+ command_line.GetSwitchValuePath(switches::kChildProcess)); |
+ base::i18n::InitializeICU(); |
+ CallLibraryEarlyInitialization(app_library); |
#if defined(OS_LINUX) && !defined(OS_ANDROID) |
- if (command_line.HasSwitch(switches::kEnableSandbox)) { |
- // Warm parts of base in the copy of base in the mojo runner. |
- base::RandUint64(); |
- base::SysInfo::AmountOfPhysicalMemory(); |
- base::SysInfo::MaxSharedMemorySize(); |
- base::SysInfo::NumberOfProcessors(); |
- |
- // TODO(erg,jln): Allowing access to all of /dev/shm/ makes it easy to |
- // spy on other shared memory using processes. This is a temporary hack |
- // so that we have some sandbox until we have proper shared memory |
- // support integrated into mojo. |
- std::vector<BrokerFilePermission> permissions; |
- permissions.push_back( |
- BrokerFilePermission::ReadWriteCreateUnlinkRecursive("/dev/shm/")); |
- sandbox.reset(new mojo::runner::LinuxSandbox(permissions)); |
- sandbox->Warmup(); |
- sandbox->EngageNamespaceSandbox(); |
- sandbox->EngageSeccompSandbox(); |
- sandbox->Seal(); |
- } |
+ if (command_line.HasSwitch(switches::kEnableSandbox)) |
+ sandbox = InitializeSandbox(); |
#endif |
- } |
embedder::ScopedPlatformHandle platform_channel = |
embedder::PlatformChannelPair::PassClientHandleFromParentProcess( |
@@ -331,12 +369,14 @@ int ChildProcessMain() { |
AppContext app_context; |
app_context.Init(); |
+ ScopedMessagePipeHandle host_message_pipe = InitializeHostMessagePipe( |
+ platform_channel.Pass(), app_context.io_runner()); |
Blocker blocker; |
app_context.controller_runner()->PostTask( |
FROM_HERE, |
base::Bind(&ChildControllerImpl::Init, base::Unretained(&app_context), |
- base::Unretained(app_library), base::Passed(&platform_channel), |
- blocker.GetUnblocker())); |
+ base::Unretained(app_library), |
+ base::Passed(&host_message_pipe), blocker.GetUnblocker())); |
// This will block, then run whatever the controller wants. |
blocker.Block(); |