| Index: components/nacl/browser/nacl_process_host.cc
|
| diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
|
| index 22f2f5f4554a000f4c508c60e9d18064e604e507..5634c6f97c4c33c3ae17fb985bb6bbe8aba8b512 100644
|
| --- a/components/nacl/browser/nacl_process_host.cc
|
| +++ b/components/nacl/browser/nacl_process_host.cc
|
| @@ -474,6 +474,13 @@ void NaClProcessHost::Launch(
|
| delete this;
|
| return;
|
| }
|
| +
|
| + if (!enable_ppapi_proxy()) {
|
| + SendErrorToRenderer(
|
| + "PPAPI proxy must be enabled on NaCl in Non-SFI mode.");
|
| + delete this;
|
| + return;
|
| + }
|
| } else {
|
| // Rather than creating a socket pair in the renderer, and passing
|
| // one side through the browser to sel_ldr, socket pairs are created
|
| @@ -672,37 +679,34 @@ bool NaClProcessHost::LaunchSelLdr() {
|
| }
|
|
|
| bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) {
|
| - bool handled = true;
|
| if (uses_nonsfi_mode_) {
|
| // IPC messages relating to NaCl's validation cache must not be exposed
|
| - // in Non-SFI Mode, otherwise a Non-SFI nexe could use
|
| - // SetKnownToValidate to create a hole in the SFI sandbox.
|
| - IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg)
|
| - IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated,
|
| - OnPpapiChannelsCreated)
|
| - IPC_MESSAGE_UNHANDLED(handled = false)
|
| - IPC_END_MESSAGE_MAP()
|
| - } else {
|
| - IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg)
|
| - IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate,
|
| - OnQueryKnownToValidate)
|
| - IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate,
|
| - OnSetKnownToValidate)
|
| - IPC_MESSAGE_HANDLER(NaClProcessMsg_ResolveFileToken,
|
| - OnResolveFileToken)
|
| + // in Non-SFI Mode, otherwise a Non-SFI nexe could use SetKnownToValidate
|
| + // to create a hole in the SFI sandbox.
|
| + // In Non-SFI mode, no message is expected.
|
| + return false;
|
| + }
|
| +
|
| + bool handled = true;
|
| + IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg)
|
| + IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate,
|
| + OnQueryKnownToValidate)
|
| + IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate,
|
| + OnSetKnownToValidate)
|
| + IPC_MESSAGE_HANDLER(NaClProcessMsg_ResolveFileToken,
|
| + OnResolveFileToken)
|
|
|
| #if defined(OS_WIN)
|
| - IPC_MESSAGE_HANDLER_DELAY_REPLY(
|
| - NaClProcessMsg_AttachDebugExceptionHandler,
|
| - OnAttachDebugExceptionHandler)
|
| - IPC_MESSAGE_HANDLER(NaClProcessHostMsg_DebugStubPortSelected,
|
| - OnDebugStubPortSelected)
|
| + IPC_MESSAGE_HANDLER_DELAY_REPLY(
|
| + NaClProcessMsg_AttachDebugExceptionHandler,
|
| + OnAttachDebugExceptionHandler)
|
| + IPC_MESSAGE_HANDLER(NaClProcessHostMsg_DebugStubPortSelected,
|
| + OnDebugStubPortSelected)
|
| #endif
|
| - IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated,
|
| - OnPpapiChannelsCreated)
|
| - IPC_MESSAGE_UNHANDLED(handled = false)
|
| - IPC_END_MESSAGE_MAP()
|
| - }
|
| + IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelsCreated,
|
| + OnPpapiChannelsCreated)
|
| + IPC_MESSAGE_UNHANDLED(handled = false)
|
| + IPC_END_MESSAGE_MAP()
|
| return handled;
|
| }
|
|
|
| @@ -975,9 +979,7 @@ bool NaClProcessHost::StartNaClExecution() {
|
| }
|
| }
|
|
|
| - params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(),
|
| - process_->GetData().handle);
|
| - process_->Send(new NaClProcessMsg_Start(params));
|
| + StartNaClFileResolved(params, base::FilePath(), base::File());
|
| return true;
|
| }
|
|
|
| @@ -998,45 +1000,110 @@ void NaClProcessHost::StartNaClFileResolved(
|
| params.nexe_file = IPC::TakeFileHandleForProcess(
|
| nexe_file_.Pass(), process_->GetData().handle);
|
| }
|
| +
|
| +#if defined(OS_LINUX)
|
| + // In Non-SFI mode, create socket pairs for IPC channels here, unlike in
|
| + // SFI-mode, in which those channels are created in nacl_listener.cc.
|
| + // This is for security hardening. We can then prohibit the socketpair()
|
| + // system call in nacl_helper and nacl_helper_nonsfi.
|
| + if (uses_nonsfi_mode_) {
|
| + // Note: here, because some FDs/handles for the NaCl loader process are
|
| + // already opened, they are transferred to NaCl loader process even if
|
| + // an error occurs first. It is because this is the simplest way to
|
| + // ensure that these FDs/handles don't get leaked and that the NaCl loader
|
| + // process will exit properly.
|
| + bool has_error = false;
|
| +
|
| + // Note: this check is redundant. We check this earlier.
|
| + DCHECK(params.enable_ipc_proxy);
|
| +
|
| + ScopedChannelHandle ppapi_browser_server_channel_handle;
|
| + ScopedChannelHandle ppapi_browser_client_channel_handle;
|
| + ScopedChannelHandle ppapi_renderer_server_channel_handle;
|
| + ScopedChannelHandle ppapi_renderer_client_channel_handle;
|
| + ScopedChannelHandle trusted_service_server_channel_handle;
|
| + ScopedChannelHandle trusted_service_client_channel_handle;
|
| + ScopedChannelHandle manifest_service_server_channel_handle;
|
| + ScopedChannelHandle manifest_service_client_channel_handle;
|
| +
|
| + if (!CreateChannelHandlePair(&ppapi_browser_server_channel_handle,
|
| + &ppapi_browser_client_channel_handle) ||
|
| + !CreateChannelHandlePair(&ppapi_renderer_server_channel_handle,
|
| + &ppapi_renderer_client_channel_handle) ||
|
| + !CreateChannelHandlePair(&trusted_service_server_channel_handle,
|
| + &trusted_service_client_channel_handle) ||
|
| + !CreateChannelHandlePair(&manifest_service_server_channel_handle,
|
| + &manifest_service_client_channel_handle)) {
|
| + SendErrorToRenderer("Failed to create socket pairs.");
|
| + has_error = true;
|
| + }
|
| +
|
| + if (!has_error &&
|
| + !StartPPAPIProxy(ppapi_browser_client_channel_handle.Pass())) {
|
| + SendErrorToRenderer("Failed to start browser PPAPI proxy.");
|
| + has_error = true;
|
| + }
|
| +
|
| + if (!has_error) {
|
| + // On success, send back a success message to the renderer process,
|
| + // and transfer the channel handles for the NaCl loader process to
|
| + // |params|.
|
| + ReplyToRenderer(ppapi_renderer_client_channel_handle.Pass(),
|
| + trusted_service_client_channel_handle.Pass(),
|
| + manifest_service_client_channel_handle.Pass());
|
| + params.ppapi_browser_channel_handle =
|
| + ppapi_browser_server_channel_handle.release();
|
| + params.ppapi_renderer_channel_handle =
|
| + ppapi_renderer_server_channel_handle.release();
|
| + params.trusted_service_channel_handle =
|
| + trusted_service_server_channel_handle.release();
|
| + params.manifest_service_channel_handle =
|
| + manifest_service_server_channel_handle.release();
|
| + }
|
| + }
|
| +#endif
|
| +
|
| process_->Send(new NaClProcessMsg_Start(params));
|
| }
|
|
|
| -// This method is called when NaClProcessHostMsg_PpapiChannelCreated is
|
| -// received.
|
| -void NaClProcessHost::OnPpapiChannelsCreated(
|
| - const IPC::ChannelHandle& raw_browser_channel_handle,
|
| - const IPC::ChannelHandle& raw_ppapi_renderer_channel_handle,
|
| - const IPC::ChannelHandle& raw_trusted_renderer_channel_handle,
|
| - const IPC::ChannelHandle& raw_manifest_service_channel_handle) {
|
| - ScopedChannelHandle browser_channel_handle(raw_browser_channel_handle);
|
| - ScopedChannelHandle ppapi_renderer_channel_handle(
|
| - raw_ppapi_renderer_channel_handle);
|
| - ScopedChannelHandle trusted_renderer_channel_handle(
|
| - raw_trusted_renderer_channel_handle);
|
| - ScopedChannelHandle manifest_service_channel_handle(
|
| - raw_manifest_service_channel_handle);
|
| -
|
| - if (!enable_ppapi_proxy()) {
|
| - ReplyToRenderer(ScopedChannelHandle(),
|
| - trusted_renderer_channel_handle.Pass(),
|
| - manifest_service_channel_handle.Pass());
|
| - return;
|
| +#if defined(OS_LINUX)
|
| +// static
|
| +bool NaClProcessHost::CreateChannelHandlePair(
|
| + ScopedChannelHandle* channel_handle1,
|
| + ScopedChannelHandle* channel_handle2) {
|
| + DCHECK(channel_handle1);
|
| + DCHECK(channel_handle2);
|
| +
|
| + int fd1 = -1;
|
| + int fd2 = -1;
|
| + if (!IPC::SocketPair(&fd1, &fd2)) {
|
| + return false;
|
| }
|
|
|
| + IPC::ChannelHandle handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
|
| + handle.socket = base::FileDescriptor(fd1, true);
|
| + channel_handle1->reset(handle);
|
| + handle.socket = base::FileDescriptor(fd2, true);
|
| + channel_handle2->reset(handle);
|
| + return true;
|
| +}
|
| +#endif
|
| +
|
| +bool NaClProcessHost::StartPPAPIProxy(ScopedChannelHandle channel_handle) {
|
| if (ipc_proxy_channel_.get()) {
|
| // Attempt to open more than 1 browser channel is not supported.
|
| // Shut down the NaCl process.
|
| process_->GetHost()->ForceShutdown();
|
| - return;
|
| + return false;
|
| }
|
|
|
| DCHECK_EQ(PROCESS_TYPE_NACL_LOADER, process_->GetData().process_type);
|
|
|
| - ipc_proxy_channel_ =
|
| - IPC::ChannelProxy::Create(browser_channel_handle.release(),
|
| - IPC::Channel::MODE_CLIENT,
|
| - NULL,
|
| - base::MessageLoopProxy::current().get());
|
| + ipc_proxy_channel_ = IPC::ChannelProxy::Create(
|
| + channel_handle.release(),
|
| + IPC::Channel::MODE_CLIENT,
|
| + NULL,
|
| + base::MessageLoopProxy::current().get());
|
| // Create the browser ppapi host and enable PPAPI message dispatching to the
|
| // browser process.
|
| ppapi_host_.reset(content::BrowserPpapiHost::CreateExternalPluginProcess(
|
| @@ -1076,6 +1143,38 @@ void NaClProcessHost::OnPpapiChannelsCreated(
|
|
|
| // Send a message to initialize the IPC dispatchers in the NaCl plugin.
|
| ipc_proxy_channel_->Send(new PpapiMsg_InitializeNaClDispatcher(args));
|
| + return true;
|
| +}
|
| +
|
| +// This method is called when NaClProcessHostMsg_PpapiChannelCreated is
|
| +// received.
|
| +void NaClProcessHost::OnPpapiChannelsCreated(
|
| + const IPC::ChannelHandle& raw_ppapi_browser_channel_handle,
|
| + const IPC::ChannelHandle& raw_ppapi_renderer_channel_handle,
|
| + const IPC::ChannelHandle& raw_trusted_renderer_channel_handle,
|
| + const IPC::ChannelHandle& raw_manifest_service_channel_handle) {
|
| + ScopedChannelHandle ppapi_browser_channel_handle(
|
| + raw_ppapi_browser_channel_handle);
|
| + ScopedChannelHandle ppapi_renderer_channel_handle(
|
| + raw_ppapi_renderer_channel_handle);
|
| + ScopedChannelHandle trusted_renderer_channel_handle(
|
| + raw_trusted_renderer_channel_handle);
|
| + ScopedChannelHandle manifest_service_channel_handle(
|
| + raw_manifest_service_channel_handle);
|
| +
|
| + if (enable_ppapi_proxy()) {
|
| + if (!StartPPAPIProxy(ppapi_browser_channel_handle.Pass())) {
|
| + SendErrorToRenderer("Browser PPAPI proxy could not start.");
|
| + return;
|
| + }
|
| + } else {
|
| + // If PPAPI proxy is disabled, channel handles should be invalid.
|
| + DCHECK(ppapi_browser_channel_handle.get().name.empty());
|
| + DCHECK(ppapi_renderer_channel_handle.get().name.empty());
|
| + // Invalidate, just in case.
|
| + ppapi_browser_channel_handle.reset();
|
| + ppapi_renderer_channel_handle.reset();
|
| + }
|
|
|
| // Let the renderer know that the IPC channels are established.
|
| ReplyToRenderer(ppapi_renderer_channel_handle.Pass(),
|
|
|