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)
5d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "components/nacl/zygote/nacl_fork_delegate_linux.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/resource.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
16bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/cpu.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/files/scoped_file.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/memory/scoped_ptr.h"
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/scoped_vector.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/pickle.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/posix/global_descriptors.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/unix_domain_socket_linux.h"
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/process/kill.h"
2858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/launch.h"
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/strings/string_split.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "build/build_config.h"
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/nacl/common/nacl_nonsfi_util.h"
33a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "components/nacl/common/nacl_paths.h"
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/nacl/common/nacl_switches.h"
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/loader/nacl_helper_linux.h"
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/common/content_descriptors.h"
37d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "content/public/common/content_switches.h"
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "sandbox/linux/suid/common/sandbox.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace {
42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Note these need to match up with their counterparts in nacl_helper_linux.c
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// and nacl_helper_bootstrap_linux.c.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNaClHelperReservedAtZero[] =
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "--reserved_at_zero=0xXXXXXXXXXXXXXXXX";
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNaClHelperRDebug[] = "--r_debug=0xXXXXXXXXXXXXXXXX";
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// This is an environment variable which controls which (if any) other
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// environment variables are passed through to NaCl processes.  e.g.,
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// NACL_ENV_PASSTHROUGH="PATH,CWD" would pass both $PATH and $CWD to the child
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// process.
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kNaClEnvPassthrough[] = "NACL_ENV_PASSTHROUGH";
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)char kNaClEnvPassthroughDelimiter = ',';
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// The following environment variables are always passed through if they exist
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// in the parent process.
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kNaClExeStderr[] = "NACL_EXE_STDERR";
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kNaClExeStdout[] = "NACL_EXE_STDOUT";
6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kNaClVerbosity[] = "NACLVERBOSITY";
6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
62bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#if defined(ARCH_CPU_X86)
63bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochbool NonZeroSegmentBaseIsSlow() {
64bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::CPU cpuid;
65bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Using a non-zero segment base is known to be very slow on Intel
66bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Atom CPUs.  See "Segmentation-based Memory Protection Mechanism
67bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // on Intel Atom Microarchitecture: Coding Optimizations" (Leonardo
68bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Potenza, Intel).
69bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  //
70bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // The following list of CPU model numbers is taken from:
71bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // "Intel 64 and IA-32 Architectures Software Developer's Manual"
72bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // (http://download.intel.com/products/processor/manual/325462.pdf),
73bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // "Table 35-1. CPUID Signature Values of DisplayFamily_DisplayModel"
74bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // (Volume 3C, 35-1), which contains:
75bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  //   "06_36H - Intel Atom S Processor Family
76bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  //    06_1CH, 06_26H, 06_27H, 06_35, 06_36 - Intel Atom Processor Family"
77bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (cpuid.family() == 6) {
78bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    switch (cpuid.model()) {
79bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      case 0x1c:
80bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      case 0x26:
81bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      case 0x27:
82bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      case 0x35:
83bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      case 0x36:
84bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        return true;
85bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    }
86bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
87bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  return false;
88bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
89bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#endif
90bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Send an IPC request on |ipc_channel|. The request is contained in
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// |request_pickle| and can have file descriptors attached in |attached_fds|.
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// |reply_data_buffer| must be allocated by the caller and will contain the
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// reply. The size of the reply will be written to |reply_size|.
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// This code assumes that only one thread can write to |ipc_channel| to make
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// requests.
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool SendIPCRequestAndReadReply(int ipc_channel,
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                const std::vector<int>& attached_fds,
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                const Pickle& request_pickle,
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                char* reply_data_buffer,
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                size_t reply_data_buffer_size,
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                ssize_t* reply_size) {
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_LE(static_cast<size_t>(kNaClMaxIPCMessageLength),
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            reply_data_buffer_size);
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(reply_size);
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!UnixDomainSocket::SendMsg(ipc_channel, request_pickle.data(),
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 request_pickle.size(), attached_fds)) {
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    LOG(ERROR) << "SendIPCRequestAndReadReply: SendMsg failed";
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Then read the remote reply.
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ScopedVector<base::ScopedFD> received_fds;
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const ssize_t msg_len =
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      UnixDomainSocket::RecvMsg(ipc_channel, reply_data_buffer,
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                reply_data_buffer_size, &received_fds);
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (msg_len <= 0) {
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    LOG(ERROR) << "SendIPCRequestAndReadReply: RecvMsg failed";
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *reply_size = msg_len;
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
126d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}  // namespace.
127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace nacl {
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AddNaClZygoteForkDelegates(
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ScopedVector<content::ZygoteForkDelegate>* delegates) {
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  delegates->push_back(new NaClForkDelegate(false /* nonsfi_mode */));
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  delegates->push_back(new NaClForkDelegate(true /* nonsfi_mode */));
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)NaClForkDelegate::NaClForkDelegate(bool nonsfi_mode)
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : nonsfi_mode_(nonsfi_mode), status_(kNaClHelperUnused), fd_(-1) {
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
139ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid NaClForkDelegate::Init(const int sandboxdesc,
1410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                            const bool enable_layer1_sandbox) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "NaClForkDelegate::Init()";
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Only launch the non-SFI helper process if non-SFI mode is enabled.
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (nonsfi_mode_ && !IsNonSFIModeEnabled()) {
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client(
1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      sandbox::SetuidSandboxClient::Create());
1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // For communications between the NaCl loader process and
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // the SUID sandbox.
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int nacl_sandbox_descriptor =
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::GlobalDescriptors::kBaseDescriptor + kSandboxIPCChannel;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Confirm a hard-wired assumption.
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_EQ(sandboxdesc, nacl_sandbox_descriptor);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int fds[2];
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PCHECK(0 == socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds));
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FileHandleMappingVector fds_to_map;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor));
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  fds_to_map.push_back(std::make_pair(sandboxdesc, nacl_sandbox_descriptor));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool use_nacl_bootstrap = false;
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // For non-SFI mode, we do not use fixed address space.
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!nonsfi_mode_) {
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Using nacl_helper_bootstrap is not necessary on x86-64 because
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // NaCl's x86-64 sandbox is not zero-address-based.  Starting
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // nacl_helper through nacl_helper_bootstrap works on x86-64, but it
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // leaves nacl_helper_bootstrap mapped at a fixed address at the
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // bottom of the address space, which is undesirable because it
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // effectively defeats ASLR.
174bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#if defined(ARCH_CPU_X86_64)
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    use_nacl_bootstrap = false;
176bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#elif defined(ARCH_CPU_X86)
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Performance vs. security trade-off: We prefer using a
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // non-zero-address-based sandbox on x86-32 because it provides some
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // ASLR and so is more secure.  However, on Atom CPUs, using a
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // non-zero segment base is very slow, so we use a zero-based
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // sandbox on those.
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    use_nacl_bootstrap = NonZeroSegmentBaseIsSlow();
183bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#else
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    use_nacl_bootstrap = true;
185bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#endif
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
187bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status_ = kNaClHelperUnused;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath helper_exe;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath helper_bootstrap_exe;
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!PathService::Get(nacl::FILE_NACL_HELPER, &helper_exe)) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status_ = kNaClHelperMissing;
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (use_nacl_bootstrap &&
194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch             !PathService::Get(nacl::FILE_NACL_HELPER_BOOTSTRAP,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               &helper_bootstrap_exe)) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status_ = kNaClHelperBootstrapMissing;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (RunningOnValgrind()) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status_ = kNaClHelperValgrind;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
200d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    CommandLine::StringVector argv_to_launch;
201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    {
202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      CommandLine cmd_line(CommandLine::NO_PROGRAM);
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (use_nacl_bootstrap)
204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        cmd_line.SetProgram(helper_bootstrap_exe);
205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      else
206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        cmd_line.SetProgram(helper_exe);
207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // Append any switches that need to be forwarded to the NaCl helper.
209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      static const char* kForwardSwitches[] = {
210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        switches::kDisableSeccompFilterSandbox,
211a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        switches::kNaClDangerousNoSandboxNonSfi,
212d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        switches::kNoSandbox,
213d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      };
214d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      const CommandLine& current_cmd_line = *CommandLine::ForCurrentProcess();
215d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      cmd_line.CopySwitchesFrom(current_cmd_line, kForwardSwitches,
216d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                arraysize(kForwardSwitches));
217d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
218d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // The command line needs to be tightly controlled to use
219d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // |helper_bootstrap_exe|. So from now on, argv_to_launch should be
220d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // modified directly.
221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      argv_to_launch = cmd_line.argv();
222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    }
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (use_nacl_bootstrap) {
224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // Arguments to the bootstrap helper which need to be at the start
225d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // of the command line, right after the helper's path.
226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      CommandLine::StringVector bootstrap_prepend;
227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      bootstrap_prepend.push_back(helper_exe.value());
228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      bootstrap_prepend.push_back(kNaClHelperReservedAtZero);
229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      bootstrap_prepend.push_back(kNaClHelperRDebug);
230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      argv_to_launch.insert(argv_to_launch.begin() + 1,
231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            bootstrap_prepend.begin(),
232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            bootstrap_prepend.end());
233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::LaunchOptions options;
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::ScopedFD dummy_fd;
2380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (enable_layer1_sandbox) {
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // NaCl needs to keep tight control of the cmd_line, so prepend the
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // setuid sandbox wrapper manually.
2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      base::FilePath sandbox_path =
2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          setuid_sandbox_client->GetSandboxBinaryPath();
2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      argv_to_launch.insert(argv_to_launch.begin(), sandbox_path.value());
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      setuid_sandbox_client->SetupLaunchOptions(
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          &options, &fds_to_map, &dummy_fd);
2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      setuid_sandbox_client->SetupLaunchEnvironment();
2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options.fds_to_remap = &fds_to_map;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The NaCl processes spawned may need to exceed the ambient soft limit
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // on RLIMIT_AS to allocate the untrusted address space and its guard
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // regions.  The nacl_helper itself cannot just raise its own limit,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because the existing limit may prevent the initial exec of
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // nacl_helper_bootstrap from succeeding, with its large address space
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // reservation.
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::vector<int> max_these_limits;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    max_these_limits.push_back(RLIMIT_AS);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options.maximize_rlimits = &max_these_limits;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // To avoid information leaks in Non-SFI mode, clear the environment for
26246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // the NaCl Helper process.
26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    options.clear_environ = true;
26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    AddPassthroughEnvToOptions(&options);
26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!base::LaunchProcess(argv_to_launch, options, NULL))
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      status_ = kNaClHelperLaunchFailed;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // parent and error cases are handled below
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (enable_layer1_sandbox) {
271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Sanity check that dummy_fd was kept alive for LaunchProcess.
272010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DCHECK(dummy_fd.is_valid());
273010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IGNORE_EINTR(close(fds[1])) != 0)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "close(fds[1]) failed";
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status_ == kNaClHelperUnused) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ssize_t kExpectedLength = strlen(kNaClHelperStartupAck);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char buf[kExpectedLength];
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait for ack from nacl_helper, indicating it is ready to help
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ssize_t nread = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nread == kExpectedLength &&
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcmp(buf, kNaClHelperStartupAck, nread) == 0) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // all is well
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      status_ = kNaClHelperSuccess;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fd_ = fds[0];
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status_ = kNaClHelperAckFailed;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Bad NaCl helper startup ack (" << nread << " bytes)";
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(bradchen): Make this LOG(ERROR) when the NaCl helper
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // becomes the default.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd_ = -1;
297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IGNORE_EINTR(close(fds[0])) != 0)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "close(fds[0]) failed";
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClForkDelegate::InitialUMA(std::string* uma_name,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int* uma_sample,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int* uma_boundary_value) {
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *uma_name = nonsfi_mode_ ? "NaCl.Client.HelperNonSFI.InitState"
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           : "NaCl.Client.Helper.InitState";
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *uma_sample = status_;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *uma_boundary_value = kNaClHelperStatusBoundary;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClForkDelegate::~NaClForkDelegate() {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // side effect of close: delegate process will terminate
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status_ == kNaClHelperSuccess) {
313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (IGNORE_EINTR(close(fd_)) != 0)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "close(fd_) failed";
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClForkDelegate::CanHelp(const std::string& process_type,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               std::string* uma_name,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               int* uma_sample,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               int* uma_boundary_value) {
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We can only help with a specific process type depending on nonsfi_mode_.
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const char* helpable_process_type = nonsfi_mode_
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          ? switches::kNaClLoaderNonSfiProcess
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          : switches::kNaClLoaderProcess;
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (process_type != helpable_process_type)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *uma_name = nonsfi_mode_ ? "NaCl.Client.HelperNonSFI.StateOnFork"
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           : "NaCl.Client.Helper.StateOnFork";
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *uma_sample = status_;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *uma_boundary_value = kNaClHelperStatusBoundary;
3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochpid_t NaClForkDelegate::Fork(const std::string& process_type,
3360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                             const std::vector<int>& fds,
3370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                             const std::string& channel_id) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "NaClForkDelegate::Fork";
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(fds.size() == kNumPassedFDs);
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (status_ != kNaClHelperSuccess) {
3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    LOG(ERROR) << "Cannot launch NaCl process: nacl_helper failed to start";
3441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return -1;
3451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // First, send a remote fork request.
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Pickle write_pickle;
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  write_pickle.WriteInt(nacl::kNaClForkRequest);
350e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // TODO(hamaji): When we split the helper binary for non-SFI mode
351e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // from nacl_helper, stop sending this information.
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  write_pickle.WriteBool(nonsfi_mode_);
3530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  write_pickle.WriteString(channel_id);
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char reply_buf[kNaClMaxIPCMessageLength];
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ssize_t reply_size = 0;
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool got_reply =
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      SendIPCRequestAndReadReply(fd_, fds, write_pickle,
3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 reply_buf, sizeof(reply_buf), &reply_size);
3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!got_reply) {
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    LOG(ERROR) << "Could not perform remote fork.";
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Now see if the other end managed to fork.
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Pickle reply_pickle(reply_buf, reply_size);
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PickleIterator iter(reply_pickle);
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  pid_t nacl_child;
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!iter.ReadInt(&nacl_child)) {
3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    LOG(ERROR) << "NaClForkDelegate::Fork: pickle failed";
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  VLOG(1) << "nacl_child is " << nacl_child;
3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return nacl_child;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool NaClForkDelegate::GetTerminationStatus(pid_t pid, bool known_dead,
3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            base::TerminationStatus* status,
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            int* exit_code) {
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  VLOG(1) << "NaClForkDelegate::GetTerminationStatus";
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(status);
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(exit_code);
3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Pickle write_pickle;
385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  write_pickle.WriteInt(nacl::kNaClGetTerminationStatusRequest);
3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  write_pickle.WriteInt(pid);
3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  write_pickle.WriteBool(known_dead);
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const std::vector<int> empty_fds;
3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char reply_buf[kNaClMaxIPCMessageLength];
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ssize_t reply_size = 0;
3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool got_reply =
3933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      SendIPCRequestAndReadReply(fd_, empty_fds, write_pickle,
3943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 reply_buf, sizeof(reply_buf), &reply_size);
3953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!got_reply) {
3963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    LOG(ERROR) << "Could not perform remote GetTerminationStatus.";
3973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Pickle reply_pickle(reply_buf, reply_size);
4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PickleIterator iter(reply_pickle);
4023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int termination_status;
4033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!iter.ReadInt(&termination_status) ||
4043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      termination_status < 0 ||
4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      termination_status >= base::TERMINATION_STATUS_MAX_ENUM) {
4063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    LOG(ERROR) << "GetTerminationStatus: pickle failed";
4073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
4083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int remote_exit_code;
4113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!iter.ReadInt(&remote_exit_code)) {
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    LOG(ERROR) << "GetTerminationStatus: pickle failed";
4133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *status = static_cast<base::TerminationStatus>(termination_status);
4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *exit_code = remote_exit_code;
4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
42146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static
42246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void NaClForkDelegate::AddPassthroughEnvToOptions(
42346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::LaunchOptions* options) {
42446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<base::Environment> env(base::Environment::Create());
42546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::string pass_through_string;
42646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::vector<std::string> pass_through_vars;
42746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (env->GetVar(kNaClEnvPassthrough, &pass_through_string)) {
42846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::SplitString(
42946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        pass_through_string, kNaClEnvPassthroughDelimiter, &pass_through_vars);
43046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
43146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pass_through_vars.push_back(kNaClExeStderr);
43246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pass_through_vars.push_back(kNaClExeStdout);
43346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pass_through_vars.push_back(kNaClVerbosity);
4346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  pass_through_vars.push_back(sandbox::kSandboxEnvironmentApiRequest);
43546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (size_t i = 0; i < pass_through_vars.size(); ++i) {
43646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::string temp;
43746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (env->GetVar(pass_through_vars[i].c_str(), &temp))
43846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      options->environ[pass_through_vars[i]] = temp;
43946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
44046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
44146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace nacl
443