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