1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "sandbox/linux/syscall_broker/broker_process.h" 6 7 #include <fcntl.h> 8 #include <signal.h> 9 #include <sys/stat.h> 10 #include <sys/syscall.h> 11 #include <sys/types.h> 12 #include <sys/wait.h> 13 #include <unistd.h> 14 15 #include <algorithm> 16 #include <string> 17 #include <utility> 18 #include <vector> 19 20 #include "base/callback.h" 21 #include "base/logging.h" 22 #include "base/memory/scoped_ptr.h" 23 #include "base/posix/eintr_wrapper.h" 24 #include "base/process/process_metrics.h" 25 #include "build/build_config.h" 26 #include "sandbox/linux/syscall_broker/broker_channel.h" 27 #include "sandbox/linux/syscall_broker/broker_client.h" 28 #include "sandbox/linux/syscall_broker/broker_host.h" 29 30 namespace sandbox { 31 32 namespace syscall_broker { 33 34 BrokerProcess::BrokerProcess( 35 int denied_errno, 36 const std::vector<syscall_broker::BrokerFilePermission>& permissions, 37 bool fast_check_in_client, 38 bool quiet_failures_for_tests) 39 : initialized_(false), 40 fast_check_in_client_(fast_check_in_client), 41 quiet_failures_for_tests_(quiet_failures_for_tests), 42 broker_pid_(-1), 43 policy_(denied_errno, permissions) { 44 } 45 46 BrokerProcess::~BrokerProcess() { 47 if (initialized_) { 48 if (broker_client_.get()) { 49 // Closing the socket should be enough to notify the child to die, 50 // unless it has been duplicated. 51 CloseChannel(); 52 } 53 PCHECK(0 == kill(broker_pid_, SIGKILL)); 54 siginfo_t process_info; 55 // Reap the child. 56 int ret = HANDLE_EINTR(waitid(P_PID, broker_pid_, &process_info, WEXITED)); 57 PCHECK(0 == ret); 58 } 59 } 60 61 bool BrokerProcess::Init( 62 const base::Callback<bool(void)>& broker_process_init_callback) { 63 CHECK(!initialized_); 64 BrokerChannel::EndPoint ipc_reader; 65 BrokerChannel::EndPoint ipc_writer; 66 BrokerChannel::CreatePair(&ipc_reader, &ipc_writer); 67 68 #if !defined(THREAD_SANITIZER) 69 DCHECK_EQ(1, base::GetNumberOfThreads(base::GetCurrentProcessHandle())); 70 #endif 71 int child_pid = fork(); 72 if (child_pid == -1) { 73 return false; 74 } 75 if (child_pid) { 76 // We are the parent and we have just forked our broker process. 77 ipc_reader.reset(); 78 broker_pid_ = child_pid; 79 broker_client_.reset(new BrokerClient(policy_, std::move(ipc_writer), 80 fast_check_in_client_, 81 quiet_failures_for_tests_)); 82 initialized_ = true; 83 return true; 84 } else { 85 // We are the broker process. Make sure to close the writer's end so that 86 // we get notified if the client disappears. 87 ipc_writer.reset(); 88 CHECK(broker_process_init_callback.Run()); 89 BrokerHost broker_host(policy_, std::move(ipc_reader)); 90 for (;;) { 91 switch (broker_host.HandleRequest()) { 92 case BrokerHost::RequestStatus::LOST_CLIENT: 93 _exit(1); 94 case BrokerHost::RequestStatus::SUCCESS: 95 case BrokerHost::RequestStatus::FAILURE: 96 continue; 97 } 98 } 99 _exit(1); 100 } 101 NOTREACHED(); 102 return false; 103 } 104 105 void BrokerProcess::CloseChannel() { 106 broker_client_.reset(); 107 } 108 109 int BrokerProcess::Access(const char* pathname, int mode) const { 110 RAW_CHECK(initialized_); 111 return broker_client_->Access(pathname, mode); 112 } 113 114 int BrokerProcess::Open(const char* pathname, int flags) const { 115 RAW_CHECK(initialized_); 116 return broker_client_->Open(pathname, flags); 117 } 118 119 } // namespace syscall_broker 120 121 } // namespace sandbox. 122