nacl_process_host.cc revision f2477e01787aa58f445919b809d89e252beef54f
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/browser/nacl_process_host.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/base_switches.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
14a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "base/file_util.h"
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/process/launch.h"
19bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/process_iterator.h"
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/rand_util.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "components/nacl/browser/nacl_browser.h"
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/browser/nacl_host_message_filter.h"
31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "components/nacl/common/nacl_cmd_line.h"
32a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "components/nacl/common/nacl_host_messages.h"
33a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "components/nacl/common/nacl_messages.h"
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "components/nacl/common/nacl_process_type.h"
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/nacl/common/nacl_switches.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_child_process_host.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_ppapi_host.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/child_process_data.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/child_process_host.h"
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/common/content_switches.h"
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/process_type.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_switches.h"
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "native_client/src/shared/imc/nacl_imc_c.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/tcp_listen_socket.h"
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ppapi/host/host_factory.h"
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/host/ppapi_host.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/shared_impl/ppapi_nacl_channel_args.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel_posix.h"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h"
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/browser/nacl_broker_service_win.h"
62a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "components/nacl/common/nacl_debug_exception_handler_win.h"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/sandbox_init.h"
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/sandboxed_process_launcher_delegate.h"
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::ChildProcessData;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::ChildProcessHost;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::proxy::SerializedHandle;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_WIN)
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace {
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Looks for the largest contiguous unallocated region of address
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// space and returns it via |*out_addr| and |*out_size|.
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void FindAddressSpace(base::ProcessHandle process,
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                      char** out_addr, size_t* out_size) {
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *out_addr = NULL;
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *out_size = 0;
823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char* addr = 0;
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  while (true) {
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    MEMORY_BASIC_INFORMATION info;
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    size_t result = VirtualQueryEx(process, static_cast<void*>(addr),
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   &info, sizeof(info));
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (result < sizeof(info))
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (info.State == MEM_FREE && info.RegionSize > *out_size) {
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *out_addr = addr;
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *out_size = info.RegionSize;
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    addr += info.RegionSize;
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace nacl {
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Allocates |size| bytes of address space in the given process at a
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// randomised address.
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void* AllocateAddressSpaceASLR(base::ProcessHandle process, size_t size) {
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char* addr;
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  size_t avail_size;
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FindAddressSpace(process, &addr, &avail_size);
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (avail_size < size)
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return NULL;
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  size_t offset = base::RandGenerator(avail_size - size);
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const int kPageSize = 0x10000;
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void* request_addr =
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      reinterpret_cast<void*>(reinterpret_cast<uint64>(addr + offset)
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              & ~(kPageSize - 1));
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return VirtualAllocEx(process, request_addr, size,
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                        MEM_RESERVE, PAGE_NOACCESS);
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace nacl
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif  // defined(OS_WIN)
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RunningOnWOW64() {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (base::win::OSInfo::GetInstance()->wow64_status() ==
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::win::OSInfo::WOW64_ENABLED);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NOTE: changes to this class need to be reviewed by the security team.
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class NaClSandboxedProcessLauncherDelegate
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public content::SandboxedProcessLauncherDelegate {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NaClSandboxedProcessLauncherDelegate() {}
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~NaClSandboxedProcessLauncherDelegate() {}
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void PostSpawnTarget(base::ProcessHandle process) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // For Native Client sel_ldr processes on 32-bit Windows, reserve 1 GB of
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // address space to prevent later failure due to address space fragmentation
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // from .dll loading. The NaCl process will attempt to locate this space by
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // scanning the address space using VirtualQuery.
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(bbudge) Handle the --no-sandbox case.
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // http://code.google.com/p/nativeclient/issues/detail?id=2131
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const SIZE_T kNaClSandboxSize = 1 << 30;
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!nacl::AllocateAddressSpaceASLR(process, kNaClSandboxSize)) {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(WARNING) << "Failed to reserve address space for Native Client";
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // OS_WIN
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetCloseOnExec(NaClHandle fd) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = fcntl(fd, F_GETFD);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_NE(flags, -1);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(rc, 0);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShareHandleToSelLdr(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ProcessHandle processh,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NaClHandle sourceh,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool close_source,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<nacl::FileDescriptor> *handles_for_sel_ldr) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE channel;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = DUPLICATE_SAME_ACCESS;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (close_source)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= DUPLICATE_CLOSE_SOURCE;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!DuplicateHandle(GetCurrentProcess(),
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       reinterpret_cast<HANDLE>(sourceh),
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       processh,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       &channel,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       0,  // Unused given DUPLICATE_SAME_ACCESS.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       FALSE,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       flags)) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "DuplicateHandle() failed";
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handles_for_sel_ldr->push_back(
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<nacl::FileDescriptor>(channel));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nacl::FileDescriptor channel;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel.fd = sourceh;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel.auto_close = close_source;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handles_for_sel_ldr->push_back(channel);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ppapi::PpapiPermissions GetNaClPermissions(uint32 permission_bits) {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only allow NaCl plugins to request certain permissions. We don't want
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a compromised renderer to be able to start a nacl plugin with e.g. Flash
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // permissions which may expand the surface area of the sandbox.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint32 masked_bits = permission_bits & ppapi::PERMISSION_DEV;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ppapi::PpapiPermissions::GetForCommandLine(masked_bits);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace nacl {
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct NaClProcessHost::NaClInternal {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NaClHandle socket_for_renderer;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NaClHandle socket_for_sel_ldr;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NaClInternal()
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : socket_for_renderer(NACL_INVALID_HANDLE),
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      socket_for_sel_ldr(NACL_INVALID_HANDLE) { }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClProcessHost::PluginListener::PluginListener(NaClProcessHost* host)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : host_(host) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClProcessHost::PluginListener::OnMessageReceived(
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& msg) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return host_->OnUntrustedMessageForwarded(msg);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClProcessHost::NaClProcessHost(const GURL& manifest_url,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 int render_view_id,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 uint32 permission_bits,
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 bool uses_irt,
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 bool enable_dyncode_syscalls,
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                 bool enable_exception_handling,
2313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 bool enable_crash_throttling,
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 bool off_the_record,
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 const base::FilePath& profile_directory)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : manifest_url_(manifest_url),
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      permissions_(GetNaClPermissions(permission_bits)),
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      process_launched_by_broker_(false),
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reply_msg_(NULL),
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      debug_exception_handler_requested_(false),
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      internal_(new NaClInternal()),
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this),
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      uses_irt_(uses_irt),
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      enable_debug_stub_(false),
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      enable_dyncode_syscalls_(enable_dyncode_syscalls),
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      enable_exception_handling_(enable_exception_handling),
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      enable_crash_throttling_(enable_crash_throttling),
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      off_the_record_(off_the_record),
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile_directory_(profile_directory),
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ipc_plugin_listener_(this),
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_view_id_(render_view_id) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_.reset(content::BrowserChildProcessHost::Create(
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PROCESS_TYPE_NACL_LOADER, this));
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the display name so the user knows what plugin the process is running.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We aren't on the UI thread so getting the pref locale for language
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // formatting isn't possible, so IDN will be lost, but this is probably OK
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for this use case.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_->SetName(net::FormatUrl(manifest_url_, std::string()));
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enable_debug_stub_ = CommandLine::ForCurrentProcess()->HasSwitch(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switches::kEnableNaClDebug);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClProcessHost::~NaClProcessHost() {
268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Report exit status only if the process was successfully started.
269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (process_->GetData().handle != base::kNullProcessHandle) {
270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int exit_code = 0;
271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    process_->GetTerminationStatus(false /* known_dead */, &exit_code);
272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    std::string message =
273424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::StringPrintf("NaCl process exited with status %i (0x%x)",
274424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                           exit_code, exit_code);
275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (exit_code == 0) {
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      VLOG(1) << message;
277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else {
278424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      LOG(ERROR) << message;
279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (internal_->socket_for_renderer != NACL_INVALID_HANDLE) {
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (NaClClose(internal_->socket_for_renderer) != 0) {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED() << "NaClClose() failed";
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (internal_->socket_for_sel_ldr != NACL_INVALID_HANDLE) {
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (NaClClose(internal_->socket_for_sel_ldr) != 0) {
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED() << "NaClClose() failed";
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reply_msg_) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The process failed to launch for some reason.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't keep the renderer hanging.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_msg_->set_reply_error();
2987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    nacl_host_message_filter_->Send(reply_msg_);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (process_launched_by_broker_) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NaClBrokerService::GetInstance()->OnLoaderDied();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void NaClProcessHost::OnProcessCrashed(int exit_status) {
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (enable_crash_throttling_ &&
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !CommandLine::ForCurrentProcess()->HasSwitch(
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          switches::kDisablePnaclCrashThrottling)) {
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NaClBrowser::GetInstance()->OnProcessCrashed();
3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is called at browser startup.
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void NaClProcessHost::EarlyStartup() {
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClBrowser::GetInstance()->EarlyStartup();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Open the IRT file early to make sure that it isn't replaced out from
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // under us by autoupdate.
322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClBrowser::GetInstance()->EnsureIrtAvailable();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine* cmd = CommandLine::ForCurrentProcess();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN(
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "NaCl.nacl-gdb",
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !cmd->GetSwitchValuePath(switches::kNaClGdb).empty());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN(
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "NaCl.nacl-gdb-script",
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !cmd->GetSwitchValuePath(switches::kNaClGdbScript).empty());
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN(
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "NaCl.enable-nacl-debug",
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmd->HasSwitch(switches::kEnableNaClDebug));
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClBrowser::GetDelegate()->SetDebugPatterns(
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmd->GetSwitchValueASCII(switches::kNaClDebugMask));
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClProcessHost::Launch(
3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    NaClHostMessageFilter* nacl_host_message_filter,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC::Message* reply_msg,
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const base::FilePath& manifest_path) {
3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  nacl_host_message_filter_ = nacl_host_message_filter;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reply_msg_ = reply_msg;
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  manifest_path_ = manifest_path;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Do not launch the requested NaCl module if NaCl is marked "unstable" due
3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // to too many crashes within a given time period.
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (enable_crash_throttling_ &&
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !CommandLine::ForCurrentProcess()->HasSwitch(
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          switches::kDisablePnaclCrashThrottling) &&
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      NaClBrowser::GetInstance()->IsThrottled()) {
3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SendErrorToRenderer("Process creation was throttled due to excessive"
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                        " crashes");
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    delete this;
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const CommandLine* cmd = CommandLine::ForCurrentProcess();
359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#if defined(OS_WIN)
360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (cmd->HasSwitch(switches::kEnableNaClDebug) &&
361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      !cmd->HasSwitch(switches::kNoSandbox)) {
362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // We don't switch off sandbox automatically for security reasons.
363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    SendErrorToRenderer("NaCl's GDB debug stub requires --no-sandbox flag"
364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        " on Windows. See crbug.com/265624.");
365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    delete this;
366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif
369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (cmd->HasSwitch(switches::kNaClGdb) &&
370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      !cmd->HasSwitch(switches::kEnableNaClDebug)) {
371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    LOG(WARNING) << "--nacl-gdb flag requires --enable-nacl-debug flag";
372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start getting the IRT open asynchronously while we launch the NaCl process.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We'll make sure this actually finished in StartWithLaunchedProcess, below.
376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClBrowser* nacl_browser = NaClBrowser::GetInstance();
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nacl_browser->EnsureAllResourcesAvailable();
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nacl_browser->IsOk()) {
379ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    SendErrorToRenderer("could not find all the resources needed"
380ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        " to launch the process");
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rather than creating a socket pair in the renderer, and passing
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one side through the browser to sel_ldr, socket pairs are created
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the browser and then passed to the renderer and sel_ldr.
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is mainly for the benefit of Windows, where sockets cannot
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be passed in messages, but are copied via DuplicateHandle().
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This means the sandboxed renderer cannot send handles to the
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // browser process.
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NaClHandle pair[2];
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create a connected socket
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NaClSocketPair(pair) == -1) {
397ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    SendErrorToRenderer("NaClSocketPair() failed");
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete this;
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  internal_->socket_for_renderer = pair[0];
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  internal_->socket_for_sel_ldr = pair[1];
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetCloseOnExec(pair[0]);
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetCloseOnExec(pair[1]);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Launch the process
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!LaunchSelLdr()) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClProcessHost::OnChannelConnected(int32 peer_pid) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CommandLine::ForCurrentProcess()->GetSwitchValuePath(
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          switches::kNaClGdb).empty()) {
4157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    LaunchNaClGdb();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_launched_by_broker_ = true;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_->SetHandle(handle);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!StartWithLaunchedProcess())
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker(bool success) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::Message* reply = attach_debug_exception_handler_reply_msg_.release();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClProcessMsg_AttachDebugExceptionHandler::WriteReplyParams(reply, success);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(reply);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Needed to handle sync messages in OnMessageRecieved.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClProcessHost::Send(IPC::Message* msg) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return process_->Send(msg);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool NaClProcessHost::LaunchNaClGdb() {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
4417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::FilePath nacl_gdb =
4427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      CommandLine::ForCurrentProcess()->GetSwitchValuePath(switches::kNaClGdb);
4437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CommandLine cmd_line(nacl_gdb);
4447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#else
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine::StringType nacl_gdb =
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CommandLine::ForCurrentProcess()->GetSwitchValueNative(
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          switches::kNaClGdb);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine::StringVector argv;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't support spaces inside arguments in --nacl-gdb switch.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(nacl_gdb, static_cast<CommandLine::CharType>(' '), &argv);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine cmd_line(argv);
4527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line.AppendArg("--eval-command");
4547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::FilePath::StringType irt_path(
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      NaClBrowser::GetInstance()->GetIrtFilePath().value());
4567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Avoid back slashes because nacl-gdb uses posix escaping rules on Windows.
4577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // See issue https://code.google.com/p/nativeclient/issues/detail?id=3482.
4587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::replace(irt_path.begin(), irt_path.end(), '\\', '/');
4597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  cmd_line.AppendArgNative(FILE_PATH_LITERAL("nacl-irt \"") + irt_path +
4607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                           FILE_PATH_LITERAL("\""));
461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!manifest_path_.empty()) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd_line.AppendArg("--eval-command");
463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::FilePath::StringType manifest_path_value(manifest_path_.value());
4647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    std::replace(manifest_path_value.begin(), manifest_path_value.end(),
4657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                 '\\', '/');
4667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    cmd_line.AppendArgNative(FILE_PATH_LITERAL("nacl-manifest \"") +
4677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                             manifest_path_value + FILE_PATH_LITERAL("\""));
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line.AppendArg("--eval-command");
4707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  cmd_line.AppendArg("target remote :4014");
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath script = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switches::kNaClGdbScript);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!script.empty()) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd_line.AppendArg("--command");
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd_line.AppendArgNative(script.value());
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::LaunchProcess(cmd_line, base::LaunchOptions(), NULL);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClProcessHost::LaunchSelLdr() {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string channel_id = process_->GetHost()->CreateChannel();
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (channel_id.empty()) {
483ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    SendErrorToRenderer("CreateChannel() failed");
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine::StringType nacl_loader_prefix;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nacl_loader_prefix = CommandLine::ForCurrentProcess()->GetSwitchValueNative(
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switches::kNaClLoaderCmdPrefix);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_POSIX)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build command line for nacl.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The Native Client process needs to be able to allocate a 1GB contiguous
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // region to use as the client environment's virtual address space. ASLR
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (PIE) interferes with this by making it possible that no gap large enough
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to accomodate this request will exist in the child process' address
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // space. Disable PIE for NaCl processes. See http://crbug.com/90221 and
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://code.google.com/p/nativeclient/issues/detail?id=2043.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = ChildProcessHost::CHILD_NO_PIE;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = nacl_loader_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           ChildProcessHost::CHILD_NORMAL;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = ChildProcessHost::CHILD_NORMAL;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath exe_path = ChildProcessHost::GetChildPath(flags);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exe_path.empty())
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Windows 64-bit NaCl loader is called nacl64.exe instead of chrome.exe
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (RunningOnWOW64()) {
517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!NaClBrowser::GetInstance()->GetNaCl64ExePath(&exe_path)) {
518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      SendErrorToRenderer("could not get path to nacl64.exe");
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<CommandLine> cmd_line(new CommandLine(exe_path));
525f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CopyNaClCommandLineArguments(cmd_line.get());
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line->AppendSwitchASCII(switches::kProcessType,
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              switches::kNaClLoaderProcess);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (NaClBrowser::GetDelegate()->DialogsAreSuppressed())
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd_line->AppendSwitch(switches::kNoErrorDialogs);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nacl_loader_prefix.empty())
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd_line->PrependWrapper(nacl_loader_prefix);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Windows we might need to start the broker process to launch a new loader
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (RunningOnWOW64()) {
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!NaClBrokerService::GetInstance()->LaunchLoader(
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            weak_factory_.GetWeakPtr(), channel_id)) {
541ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      SendErrorToRenderer("broker service did not launch process");
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    process_->Launch(new NaClSandboxedProcessLauncherDelegate,
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     cmd_line.release());
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_->Launch(nacl_loader_prefix.empty(),  // use_zygote
55058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   base::EnvironmentMap(),
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   cmd_line.release());
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate,
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnQueryKnownToValidate)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnSetKnownToValidate)
56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClProcessMsg_ResolveFileToken,
56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    OnResolveFileToken)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClProcessMsg_AttachDebugExceptionHandler,
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    OnAttachDebugExceptionHandler)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelCreated,
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnPpapiChannelCreated)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClProcessHost::OnProcessLaunched() {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!StartWithLaunchedProcess())
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called when the NaClBrowser singleton has been fully initialized.
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClProcessHost::OnResourcesReady() {
584f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClBrowser* nacl_browser = NaClBrowser::GetInstance();
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!nacl_browser->IsReady()) {
586ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    SendErrorToRenderer("could not acquire shared resources needed by NaCl");
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete this;
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (!SendStart()) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClProcessHost::ReplyToRenderer(
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::ChannelHandle& channel_handle) {
5957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(OS_WIN)
5967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If we are on 64-bit Windows, the NaCl process's sandbox is
5977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // managed by a different process from the renderer's sandbox.  We
5987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // need to inform the renderer's sandbox about the NaCl process so
5997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // that the renderer can send handles to the NaCl process using
6007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // BrokerDuplicateHandle().
6017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (RunningOnWOW64()) {
6027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!content::BrokerAddTargetPeer(process_->GetData().handle)) {
603ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      SendErrorToRenderer("BrokerAddTargetPeer() failed");
6047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return false;
6057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
6067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
6077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
6087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FileDescriptor handle_for_renderer;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Copy the handle into the renderer process.
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HANDLE handle_in_renderer;
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!DuplicateHandle(base::GetCurrentProcessHandle(),
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       reinterpret_cast<HANDLE>(
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           internal_->socket_for_renderer),
6167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       nacl_host_message_filter_->PeerHandle(),
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       &handle_in_renderer,
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       0,  // Unused given DUPLICATE_SAME_ACCESS.
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       FALSE,
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
621ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    SendErrorToRenderer("DuplicateHandle() failed");
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  handle_for_renderer = reinterpret_cast<FileDescriptor>(
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handle_in_renderer);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // No need to dup the imc_handle - we don't pass it anywhere else so
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // it cannot be closed.
629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FileDescriptor imc_handle;
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  imc_handle.fd = internal_->socket_for_renderer;
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  imc_handle.auto_close = true;
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handle_for_renderer = imc_handle;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ChildProcessData& data = process_->GetData();
636ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SendMessageToRenderer(
637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      NaClLaunchResult(handle_for_renderer,
638ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                             channel_handle,
639ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                             base::GetProcId(data.handle),
640ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                             data.id),
641ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      std::string() /* error_message */);
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  internal_->socket_for_renderer = NACL_INVALID_HANDLE;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
646ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid NaClProcessHost::SendErrorToRenderer(const std::string& error_message) {
647ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  LOG(ERROR) << "NaCl process launch failed: " << error_message;
648f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SendMessageToRenderer(NaClLaunchResult(), error_message);
649ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
650ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
651ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid NaClProcessHost::SendMessageToRenderer(
652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const NaClLaunchResult& result,
653ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& error_message) {
654ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(nacl_host_message_filter_);
655ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(reply_msg_);
656ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (nacl_host_message_filter_ != NULL && reply_msg_ != NULL) {
657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    NaClHostMsg_LaunchNaCl::WriteReplyParams(
658ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        reply_msg_, result, error_message);
659ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    nacl_host_message_filter_->Send(reply_msg_);
660ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    nacl_host_message_filter_ = NULL;
661ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    reply_msg_ = NULL;
662ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
663ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
664ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TCP port we chose for NaCl debug stub. It can be any other number.
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDebugStubPort = 4014;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
669424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)net::SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() {
670f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClBrowser* nacl_browser = NaClBrowser::GetInstance();
671424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::SocketDescriptor s = net::kInvalidSocket;
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We allocate currently unused TCP port for debug stub tests. The port
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // number is passed to the test via debug stub port listener.
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (nacl_browser->HasGdbDebugStubPortListener()) {
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int port;
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    s = net::TCPListenSocket::CreateAndBindAnyPort("127.0.0.1", &port);
677424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (s != net::kInvalidSocket) {
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nacl_browser->FireGdbDebugStubPortOpened(port);
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    s = net::TCPListenSocket::CreateAndBind("127.0.0.1", kDebugStubPort);
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
683424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (s == net::kInvalidSocket) {
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "failed to open socket for debug stub";
685424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return net::kInvalidSocket;
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listen(s, 1)) {
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "listen() failed on debug stub socket";
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (HANDLE_EINTR(close(s)) < 0)
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PLOG(ERROR) << "failed to close debug stub socket";
691424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return net::kInvalidSocket;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return s;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClProcessHost::StartNaClExecution() {
698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClBrowser* nacl_browser = NaClBrowser::GetInstance();
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
700f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClStartParams params;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled();
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.validation_cache_key = nacl_browser->GetValidationCacheKey();
703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  params.version = NaClBrowser::GetDelegate()->GetVersionString();
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.enable_exception_handling = enable_exception_handling_;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.enable_debug_stub = enable_debug_stub_ &&
706f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(manifest_url_);
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Enable PPAPI proxy channel creation only for renderer processes.
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.enable_ipc_proxy = enable_ppapi_proxy();
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.uses_irt = uses_irt_;
710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.enable_dyncode_syscalls = enable_dyncode_syscalls_;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ChildProcessData& data = process_->GetData();
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ShareHandleToSelLdr(data.handle,
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           internal_->socket_for_sel_ldr, true,
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &params.handles)) {
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (params.uses_irt) {
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::PlatformFile irt_file = nacl_browser->IrtFile();
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK_NE(irt_file, base::kInvalidPlatformFileValue);
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Send over the IRT file handle.  We don't close our own copy!
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!ShareHandleToSelLdr(data.handle, irt_file, false, &params.handles))
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For dynamic loading support, NaCl requires a file descriptor that
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was created in /tmp, since those created with shm_open() are not
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mappable with PROT_EXEC.  Rather than requiring an extra IPC
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // round trip out of the sandbox, we create an FD here.
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SharedMemory memory_buffer;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SharedMemoryCreateOptions options;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.size = 1;
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.executable = true;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!memory_buffer.Create(options)) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Failed to allocate memory buffer";
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
740f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FileDescriptor memory_fd;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memory_fd.fd = dup(memory_buffer.handle().fd);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (memory_fd.fd < 0) {
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Failed to dup() a file descriptor";
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memory_fd.auto_close = true;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.handles.push_back(memory_fd);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params.enable_debug_stub) {
752424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle();
753424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (server_bound_socket != net::kInvalidSocket) {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params.debug_stub_server_bound_socket =
755f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          FileDescriptor(server_bound_socket, true);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_->Send(new NaClProcessMsg_Start(params));
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  internal_->socket_for_sel_ldr = NACL_INVALID_HANDLE;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClProcessHost::SendStart() {
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!enable_ppapi_proxy()) {
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ReplyToRenderer(IPC::ChannelHandle()))
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StartNaClExecution();
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is called when NaClProcessHostMsg_PpapiChannelCreated is
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// received or PpapiHostMsg_ChannelCreated is forwarded by our plugin
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// listener.
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClProcessHost::OnPpapiChannelCreated(
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::ChannelHandle& channel_handle) {
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only renderer processes should create a channel.
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(enable_ppapi_proxy());
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the proxy channel is null, this must be the initial NaCl-Browser IPC
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // channel.
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ipc_proxy_channel_.get()) {
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(PROCESS_TYPE_NACL_LOADER, process_->GetData().process_type);
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_proxy_channel_.reset(
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new IPC::ChannelProxy(channel_handle,
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              IPC::Channel::MODE_CLIENT,
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &ipc_plugin_listener_,
7907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                              base::MessageLoopProxy::current().get()));
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create the browser ppapi host and enable PPAPI message dispatching to the
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // browser process.
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ppapi_host_.reset(content::BrowserPpapiHost::CreateExternalPluginProcess(
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ipc_proxy_channel_.get(),  // sender
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        permissions_,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        process_->GetData().handle,
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ipc_proxy_channel_.get(),
7987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        nacl_host_message_filter_->render_process_id(),
799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        render_view_id_,
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        profile_directory_));
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ppapi::PpapiNaClChannelArgs args;
8037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    args.off_the_record = nacl_host_message_filter_->off_the_record();
804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    args.permissions = permissions_;
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CommandLine* cmdline = CommandLine::ForCurrentProcess();
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(cmdline);
807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string flag_whitelist[] = {switches::kV, switches::kVModule};
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (size_t i = 0; i < arraysize(flag_whitelist); ++i) {
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string value = cmdline->GetSwitchValueASCII(flag_whitelist[i]);
810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!value.empty()) {
811c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        args.switch_names.push_back(flag_whitelist[i]);
812c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        args.switch_values.push_back(value);
813c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
815c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ppapi_host_->GetPpapiHost()->AddHostFactoryFilter(
817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        scoped_ptr<ppapi::host::HostFactory>(
818f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            NaClBrowser::GetDelegate()->CreatePpapiHostFactory(
8197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                ppapi_host_.get())));
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send a message to create the NaCl-Renderer channel. The handle is just
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a place holder.
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_proxy_channel_->Send(
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new PpapiMsg_CreateNaClChannel(
8257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            nacl_host_message_filter_->render_process_id(),
826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            args,
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            SerializedHandle(SerializedHandle::CHANNEL_HANDLE,
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             IPC::InvalidPlatformFileForTransit())));
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (reply_msg_) {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Otherwise, this must be a renderer channel.
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReplyToRenderer(channel_handle);
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Attempt to open more than 1 renderer channel is not supported.
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Shut down the NaCl process.
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process_->GetHost()->ForceShutdown();
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClProcessHost::OnUntrustedMessageForwarded(const IPC::Message& msg) {
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle messages that have been forwarded from our PluginListener.
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These messages come from untrusted code so should be handled with care.
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiHostMsg_ChannelCreated,
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnPpapiChannelCreated)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClProcessHost::StartWithLaunchedProcess() {
852f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClBrowser* nacl_browser = NaClBrowser::GetInstance();
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nacl_browser->IsReady()) {
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SendStart();
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (nacl_browser->IsOk()) {
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nacl_browser->WaitForResources(
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NaClProcessHost::OnResourcesReady,
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_factory_.GetWeakPtr()));
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
862ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    SendErrorToRenderer("previously failed to acquire shared resources");
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClProcessHost::OnQueryKnownToValidate(const std::string& signature,
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             bool* result) {
869f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClBrowser* nacl_browser = NaClBrowser::GetInstance();
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = nacl_browser->QueryKnownToValidate(signature, off_the_record_);
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClProcessHost::OnSetKnownToValidate(const std::string& signature) {
874f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NaClBrowser::GetInstance()->SetKnownToValidate(
8750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      signature, off_the_record_);
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
87890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClProcessHost::FileResolved(
87990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& file_path,
880f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    IPC::Message* reply_msg,
881f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const base::PlatformFile& file) {
882f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (file != base::kInvalidPlatformFileValue) {
88390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    IPC::PlatformFileForTransit handle = IPC::GetFileHandleForProcess(
884f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        file,
88590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        process_->GetData().handle,
88690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        true /* close_source */);
88790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    NaClProcessMsg_ResolveFileToken::WriteReplyParams(
88890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        reply_msg,
88990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        handle,
89090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        file_path);
89190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
89290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    NaClProcessMsg_ResolveFileToken::WriteReplyParams(
89390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        reply_msg,
89490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        IPC::InvalidPlatformFileForTransit(),
895f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::FilePath());
89690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
89790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Send(reply_msg);
89890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
89990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
90090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClProcessHost::OnResolveFileToken(uint64 file_token_lo,
90190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         uint64 file_token_hi,
90290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         IPC::Message* reply_msg) {
90390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Was the file registered?
90490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
90590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note that the file path cache is of bounded size, and old entries can get
90690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // evicted.  If a large number of NaCl modules are being launched at once,
90790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // resolving the file_token may fail because the path cache was thrashed
90890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // while the file_token was in flight.  In this case the query fails, and we
90990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // need to fall back to the slower path.
91090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
91190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // However: each NaCl process will consume 2-3 entries as it starts up, this
91290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // means that eviction will not happen unless you start up 33+ NaCl processes
91390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // at the same time, and this still requires worst-case timing.  As a
91490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // practical matter, no entries should be evicted prematurely.
91590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The cache itself should take ~ (150 characters * 2 bytes/char + ~60 bytes
91690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // data structure overhead) * 100 = 35k when full, so making it bigger should
91790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // not be a problem, if needed.
91890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
91990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Each NaCl process will consume 2-3 entries because the manifest and main
92090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // nexe are currently not resolved.  Shared libraries will be resolved.  They
92190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // will be loaded sequentially, so they will only consume a single entry
92290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // while the load is in flight.
92390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
92490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(ncbray): track behavior with UMA. If entries are getting evicted or
92590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // bogus keys are getting queried, this would be good to know.
92690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath file_path;
927f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!NaClBrowser::GetInstance()->GetFilePath(
9280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        file_token_lo, file_token_hi, &file_path)) {
92990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    NaClProcessMsg_ResolveFileToken::WriteReplyParams(
93090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        reply_msg,
93190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        IPC::InvalidPlatformFileForTransit(),
932f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::FilePath());
93390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Send(reply_msg);
93490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
93590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
93690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
93790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Open the file.
938f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!base::PostTaskAndReplyWithResult(
939f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          content::BrowserThread::GetBlockingPool(),
94090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          FROM_HERE,
941f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          base::Bind(OpenNaClExecutableImpl, file_path),
94290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          base::Bind(&NaClProcessHost::FileResolved,
94390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     weak_factory_.GetWeakPtr(),
94490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     file_path,
94590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     reply_msg))) {
94690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)     NaClProcessMsg_ResolveFileToken::WriteReplyParams(
94790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         reply_msg,
94890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         IPC::InvalidPlatformFileForTransit(),
949f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         base::FilePath());
95090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)     Send(reply_msg);
95190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
95290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
95390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClProcessHost::OnAttachDebugExceptionHandler(const std::string& info,
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    IPC::Message* reply_msg) {
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AttachDebugExceptionHandler(info, reply_msg)) {
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send failure message.
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NaClProcessMsg_AttachDebugExceptionHandler::WriteReplyParams(reply_msg,
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                                 false);
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClProcessHost::AttachDebugExceptionHandler(const std::string& info,
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  IPC::Message* reply_msg) {
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!enable_exception_handling_ && !enable_debug_stub_) {
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) <<
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Debug exception handler requested by NaCl process when not enabled";
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (debug_exception_handler_requested_) {
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The NaCl process should not request this multiple times.
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Multiple AttachDebugExceptionHandler requests received";
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  debug_exception_handler_requested_ = true;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ProcessId nacl_pid = base::GetProcId(process_->GetData().handle);
980f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::ProcessHandle temp_handle;
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We cannot use process_->GetData().handle because it does not have
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the necessary access rights.  We open the new handle here rather
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // than in the NaCl broker process in case the NaCl loader process
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dies before the NaCl broker process receives the message we send.
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The debug exception handler uses DebugActiveProcess() to attach,
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but this takes a PID.  We need to prevent the NaCl loader's PID
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from being reused before DebugActiveProcess() is called, and
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // holding a process handle open achieves this.
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!base::OpenProcessHandleWithAccess(
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           nacl_pid,
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           base::kProcessAccessQueryInformation |
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           base::kProcessAccessSuspendResume |
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           base::kProcessAccessTerminate |
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           base::kProcessAccessVMOperation |
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           base::kProcessAccessVMRead |
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           base::kProcessAccessVMWrite |
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           base::kProcessAccessDuplicateHandle |
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           base::kProcessAccessWaitForTermination,
999f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           &temp_handle)) {
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to get process handle";
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1003f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::win::ScopedHandle process_handle(temp_handle);
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  attach_debug_exception_handler_reply_msg_.reset(reply_msg);
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the NaCl loader is 64-bit, the process running its debug
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exception handler must be 64-bit too, so we use the 64-bit NaCl
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // broker process for this.  Otherwise, on a 32-bit system, we use
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the 32-bit browser process to run the debug exception handler.
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (RunningOnWOW64()) {
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NaClBrokerService::GetInstance()->LaunchDebugExceptionHandler(
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               weak_factory_.GetWeakPtr(), nacl_pid, process_handle, info);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NaClStartDebugExceptionHandlerThread(
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        process_handle.Take(), info,
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::MessageLoopProxy::current(),
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker,
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_factory_.GetWeakPtr()));
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1023f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1024f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace nacl
1025