nacl_fork_delegate_linux.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/pickle.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/posix/global_descriptors.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/unix_domain_socket_linux.h" 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/process/kill.h" 2758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/launch.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/dynamic_annotations/dynamic_annotations.h" 29a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "components/nacl/common/nacl_paths.h" 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/nacl/common/nacl_switches.h" 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/loader/nacl_helper_linux.h" 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/common/content_descriptors.h" 33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "content/public/common/content_switches.h" 340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "sandbox/linux/suid/client/setuid_sandbox_client.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace { 37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Note these need to match up with their counterparts in nacl_helper_linux.c 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// and nacl_helper_bootstrap_linux.c. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNaClHelperReservedAtZero[] = 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "--reserved_at_zero=0xXXXXXXXXXXXXXXXX"; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNaClHelperRDebug[] = "--r_debug=0xXXXXXXXXXXXXXXXX"; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 44bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#if defined(ARCH_CPU_X86) 45bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochbool NonZeroSegmentBaseIsSlow() { 46bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::CPU cpuid; 47bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Using a non-zero segment base is known to be very slow on Intel 48bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Atom CPUs. See "Segmentation-based Memory Protection Mechanism 49bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // on Intel Atom Microarchitecture: Coding Optimizations" (Leonardo 50bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Potenza, Intel). 51bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // 52bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // The following list of CPU model numbers is taken from: 53bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // "Intel 64 and IA-32 Architectures Software Developer's Manual" 54bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // (http://download.intel.com/products/processor/manual/325462.pdf), 55bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // "Table 35-1. CPUID Signature Values of DisplayFamily_DisplayModel" 56bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // (Volume 3C, 35-1), which contains: 57bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // "06_36H - Intel Atom S Processor Family 58bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // 06_1CH, 06_26H, 06_27H, 06_35, 06_36 - Intel Atom Processor Family" 59bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (cpuid.family() == 6) { 60bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch switch (cpuid.model()) { 61bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch case 0x1c: 62bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch case 0x26: 63bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch case 0x27: 64bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch case 0x35: 65bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch case 0x36: 66bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch return true; 67bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 68bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 69bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch return false; 70bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch} 71bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#endif 72bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Send an IPC request on |ipc_channel|. The request is contained in 743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// |request_pickle| and can have file descriptors attached in |attached_fds|. 753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// |reply_data_buffer| must be allocated by the caller and will contain the 763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// reply. The size of the reply will be written to |reply_size|. 773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// This code assumes that only one thread can write to |ipc_channel| to make 783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// requests. 793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool SendIPCRequestAndReadReply(int ipc_channel, 803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::vector<int>& attached_fds, 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const Pickle& request_pickle, 823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) char* reply_data_buffer, 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t reply_data_buffer_size, 843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ssize_t* reply_size) { 853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK_LE(static_cast<size_t>(kNaClMaxIPCMessageLength), 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) reply_data_buffer_size); 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(reply_size); 883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!UnixDomainSocket::SendMsg(ipc_channel, request_pickle.data(), 903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) request_pickle.size(), attached_fds)) { 913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "SendIPCRequestAndReadReply: SendMsg failed"; 923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Then read the remote reply. 963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::vector<int> received_fds; 973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const ssize_t msg_len = 983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) UnixDomainSocket::RecvMsg(ipc_channel, reply_data_buffer, 993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) reply_data_buffer_size, &received_fds); 1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (msg_len <= 0) { 1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "SendIPCRequestAndReadReply: RecvMsg failed"; 1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *reply_size = msg_len; 1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 108d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} // namespace. 109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 110ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochNaClForkDelegate::NaClForkDelegate() 111ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch : status_(kNaClHelperUnused), 112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch fd_(-1) {} 113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid NaClForkDelegate::Init(const int sandboxdesc, 1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const bool enable_layer1_sandbox) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "NaClForkDelegate::Init()"; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fds[2]; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client( 1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sandbox::SetuidSandboxClient::Create()); 1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // For communications between the NaCl loader process and 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // the SUID sandbox. 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int nacl_sandbox_descriptor = 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::GlobalDescriptors::kBaseDescriptor + kSandboxIPCChannel; 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Confirm a hard-wired assumption. 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_EQ(sandboxdesc, nacl_sandbox_descriptor); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::FileHandleMappingVector fds_to_map; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor)); 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) fds_to_map.push_back(std::make_pair(sandboxdesc, nacl_sandbox_descriptor)); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Make sure that nacl_loader is started with a dummy file descriptor. This 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // is required because the setuid sandbox will always try to close a 1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // hard-wired file descriptor. 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::ScopedFD dummy_fd(socket(PF_UNIX, SOCK_DGRAM, 0)); 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CHECK(dummy_fd.is_valid()); 1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch fds_to_map.push_back(std::make_pair( 1400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dummy_fd.get(), setuid_sandbox_client->GetUniqueToChildFileDescriptor())); 1410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 142bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Using nacl_helper_bootstrap is not necessary on x86-64 because 143bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // NaCl's x86-64 sandbox is not zero-address-based. Starting 144bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // nacl_helper through nacl_helper_bootstrap works on x86-64, but it 145bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // leaves nacl_helper_bootstrap mapped at a fixed address at the 146bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // bottom of the address space, which is undesirable because it 147bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // effectively defeats ASLR. 148bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#if defined(ARCH_CPU_X86_64) 149bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch bool kUseNaClBootstrap = false; 150bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#elif defined(ARCH_CPU_X86) 151bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Performance vs. security trade-off: We prefer using a 152bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // non-zero-address-based sandbox on x86-32 because it provides some 153bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // ASLR and so is more secure. However, on Atom CPUs, using a 154bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // non-zero segment base is very slow, so we use a zero-based 155bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // sandbox on those. 156bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch bool kUseNaClBootstrap = NonZeroSegmentBaseIsSlow(); 157bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#else 158bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch bool kUseNaClBootstrap = true; 159bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#endif 160bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = kNaClHelperUnused; 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath helper_exe; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath helper_bootstrap_exe; 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!PathService::Get(nacl::FILE_NACL_HELPER, &helper_exe)) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = kNaClHelperMissing; 166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else if (kUseNaClBootstrap && 167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch !PathService::Get(nacl::FILE_NACL_HELPER_BOOTSTRAP, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &helper_bootstrap_exe)) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = kNaClHelperBootstrapMissing; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (RunningOnValgrind()) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = kNaClHelperValgrind; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch CommandLine::StringVector argv_to_launch; 174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch { 175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch CommandLine cmd_line(CommandLine::NO_PROGRAM); 176d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (kUseNaClBootstrap) 177d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cmd_line.SetProgram(helper_bootstrap_exe); 178d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch else 179d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cmd_line.SetProgram(helper_exe); 180d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 181d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Append any switches that need to be forwarded to the NaCl helper. 182d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch static const char* kForwardSwitches[] = { 183d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switches::kDisableSeccompFilterSandbox, 184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch switches::kNaClDangerousNoSandboxNonSfi, 185d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switches::kNoSandbox, 186d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch }; 187d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const CommandLine& current_cmd_line = *CommandLine::ForCurrentProcess(); 188d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cmd_line.CopySwitchesFrom(current_cmd_line, kForwardSwitches, 189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch arraysize(kForwardSwitches)); 190d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The command line needs to be tightly controlled to use 192d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // |helper_bootstrap_exe|. So from now on, argv_to_launch should be 193d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // modified directly. 194d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch argv_to_launch = cmd_line.argv(); 195d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 196ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kUseNaClBootstrap) { 197d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Arguments to the bootstrap helper which need to be at the start 198d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // of the command line, right after the helper's path. 199d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch CommandLine::StringVector bootstrap_prepend; 200d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bootstrap_prepend.push_back(helper_exe.value()); 201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bootstrap_prepend.push_back(kNaClHelperReservedAtZero); 202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bootstrap_prepend.push_back(kNaClHelperRDebug); 203d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch argv_to_launch.insert(argv_to_launch.begin() + 1, 204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bootstrap_prepend.begin(), 205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bootstrap_prepend.end()); 206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions options; 2090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (enable_layer1_sandbox) { 2100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // NaCl needs to keep tight control of the cmd_line, so 2110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // pass NULL and prepend the setuid sandbox wrapper manually. 2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch setuid_sandbox_client->PrependWrapper(NULL /* cmd_line */, &options); 2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::FilePath sandbox_path = 2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch setuid_sandbox_client->GetSandboxBinaryPath(); 2150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch argv_to_launch.insert(argv_to_launch.begin(), sandbox_path.value()); 2160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch setuid_sandbox_client->SetupLaunchEnvironment(); 2170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.fds_to_remap = &fds_to_map; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The NaCl processes spawned may need to exceed the ambient soft limit 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on RLIMIT_AS to allocate the untrusted address space and its guard 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // regions. The nacl_helper itself cannot just raise its own limit, 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because the existing limit may prevent the initial exec of 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // nacl_helper_bootstrap from succeeding, with its large address space 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reservation. 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<int> max_these_limits; 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_these_limits.push_back(RLIMIT_AS); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.maximize_rlimits = &max_these_limits; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!base::LaunchProcess(argv_to_launch, options, NULL)) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = kNaClHelperLaunchFailed; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parent and error cases are handled below 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IGNORE_EINTR(close(fds[1])) != 0) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "close(fds[1]) failed"; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ == kNaClHelperUnused) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ssize_t kExpectedLength = strlen(kNaClHelperStartupAck); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[kExpectedLength]; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for ack from nacl_helper, indicating it is ready to help 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ssize_t nread = HANDLE_EINTR(read(fds[0], buf, sizeof(buf))); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nread == kExpectedLength && 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcmp(buf, kNaClHelperStartupAck, nread) == 0) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // all is well 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = kNaClHelperSuccess; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fd_ = fds[0]; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = kNaClHelperAckFailed; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Bad NaCl helper startup ack (" << nread << " bytes)"; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(bradchen): Make this LOG(ERROR) when the NaCl helper 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // becomes the default. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fd_ = -1; 257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IGNORE_EINTR(close(fds[0])) != 0) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "close(fds[0]) failed"; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClForkDelegate::InitialUMA(std::string* uma_name, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* uma_sample, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* uma_boundary_value) { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *uma_name = "NaCl.Client.Helper.InitState"; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *uma_sample = status_; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *uma_boundary_value = kNaClHelperStatusBoundary; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClForkDelegate::~NaClForkDelegate() { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // side effect of close: delegate process will terminate 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ == kNaClHelperSuccess) { 272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IGNORE_EINTR(close(fd_)) != 0) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "close(fd_) failed"; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClForkDelegate::CanHelp(const std::string& process_type, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* uma_name, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* uma_sample, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* uma_boundary_value) { 281e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (process_type != switches::kNaClLoaderProcess && 282e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch process_type != switches::kNaClLoaderNonSfiProcess) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *uma_name = "NaCl.Client.Helper.StateOnFork"; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *uma_sample = status_; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *uma_boundary_value = kNaClHelperStatusBoundary; 2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return true; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 290e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochpid_t NaClForkDelegate::Fork(const std::string& process_type, 2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<int>& fds, 2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::string& channel_id) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "NaClForkDelegate::Fork"; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(fds.size() == kNumPassedFDs); 2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (status_ != kNaClHelperSuccess) { 2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) LOG(ERROR) << "Cannot launch NaCl process: nacl_helper failed to start"; 2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return -1; 3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // First, send a remote fork request. 3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Pickle write_pickle; 304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) write_pickle.WriteInt(nacl::kNaClForkRequest); 305e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // TODO(hamaji): When we split the helper binary for non-SFI mode 306e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // from nacl_helper, stop sending this information. 307e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const bool uses_nonsfi_mode = 308e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch process_type == switches::kNaClLoaderNonSfiProcess; 309e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch write_pickle.WriteBool(uses_nonsfi_mode); 3100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch write_pickle.WriteString(channel_id); 3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) char reply_buf[kNaClMaxIPCMessageLength]; 3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ssize_t reply_size = 0; 3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool got_reply = 3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SendIPCRequestAndReadReply(fd_, fds, write_pickle, 3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) reply_buf, sizeof(reply_buf), &reply_size); 3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!got_reply) { 3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "Could not perform remote fork."; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Now see if the other end managed to fork. 3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Pickle reply_pickle(reply_buf, reply_size); 3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PickleIterator iter(reply_pickle); 3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pid_t nacl_child; 3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!iter.ReadInt(&nacl_child)) { 3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "NaClForkDelegate::Fork: pickle failed"; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) VLOG(1) << "nacl_child is " << nacl_child; 3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return nacl_child; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool NaClForkDelegate::GetTerminationStatus(pid_t pid, bool known_dead, 3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::TerminationStatus* status, 3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int* exit_code) { 3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) VLOG(1) << "NaClForkDelegate::GetTerminationStatus"; 3383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(status); 3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(exit_code); 3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Pickle write_pickle; 342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) write_pickle.WriteInt(nacl::kNaClGetTerminationStatusRequest); 3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) write_pickle.WriteInt(pid); 3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) write_pickle.WriteBool(known_dead); 3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::vector<int> empty_fds; 3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) char reply_buf[kNaClMaxIPCMessageLength]; 3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ssize_t reply_size = 0; 3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool got_reply = 3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SendIPCRequestAndReadReply(fd_, empty_fds, write_pickle, 3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) reply_buf, sizeof(reply_buf), &reply_size); 3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!got_reply) { 3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "Could not perform remote GetTerminationStatus."; 3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Pickle reply_pickle(reply_buf, reply_size); 3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PickleIterator iter(reply_pickle); 3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int termination_status; 3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!iter.ReadInt(&termination_status) || 3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) termination_status < 0 || 3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) termination_status >= base::TERMINATION_STATUS_MAX_ENUM) { 3633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "GetTerminationStatus: pickle failed"; 3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int remote_exit_code; 3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!iter.ReadInt(&remote_exit_code)) { 3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "GetTerminationStatus: pickle failed"; 3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 3713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *status = static_cast<base::TerminationStatus>(termination_status); 3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *exit_code = remote_exit_code; 3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 377