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/posix/eintr_wrapper.h" 23 #include "base/process/process_metrics.h" 24 #include "build/build_config.h" 25 #include "sandbox/linux/syscall_broker/broker_channel.h" 26 #include "sandbox/linux/syscall_broker/broker_client.h" 27 #include "sandbox/linux/syscall_broker/broker_host.h" 28 29 namespace sandbox { 30 31 namespace syscall_broker { 32 33 BrokerProcess::BrokerProcess( 34 int denied_errno, 35 const std::vector<syscall_broker::BrokerFilePermission>& permissions, 36 bool fast_check_in_client, 37 bool quiet_failures_for_tests) 38 : initialized_(false), 39 fast_check_in_client_(fast_check_in_client), 40 quiet_failures_for_tests_(quiet_failures_for_tests), 41 broker_pid_(-1), 42 policy_(denied_errno, permissions) { 43 } 44 45 BrokerProcess::~BrokerProcess() { 46 if (initialized_) { 47 if (broker_client_.get()) { 48 // Closing the socket should be enough to notify the child to die, 49 // unless it has been duplicated. 50 CloseChannel(); 51 } 52 PCHECK(0 == kill(broker_pid_, SIGKILL)); 53 siginfo_t process_info; 54 // Reap the child. 55 int ret = HANDLE_EINTR(waitid(P_PID, broker_pid_, &process_info, WEXITED)); 56 PCHECK(0 == ret); 57 } 58 } 59 60 bool BrokerProcess::Init( 61 const base::Callback<bool(void)>& broker_process_init_callback) { 62 CHECK(!initialized_); 63 BrokerChannel::EndPoint ipc_reader; 64 BrokerChannel::EndPoint ipc_writer; 65 BrokerChannel::CreatePair(&ipc_reader, &ipc_writer); 66 67 #if !defined(THREAD_SANITIZER) 68 DCHECK_EQ(1, base::GetNumberOfThreads(base::GetCurrentProcessHandle())); 69 #endif 70 int child_pid = fork(); 71 if (child_pid == -1) { 72 return false; 73 } 74 if (child_pid) { 75 // We are the parent and we have just forked our broker process. 76 ipc_reader.reset(); 77 broker_pid_ = child_pid; 78 broker_client_.reset(new BrokerClient(policy_, std::move(ipc_writer), 79 fast_check_in_client_, 80 quiet_failures_for_tests_)); 81 initialized_ = true; 82 return true; 83 } else { 84 // We are the broker process. Make sure to close the writer's end so that 85 // we get notified if the client disappears. 86 ipc_writer.reset(); 87 CHECK(broker_process_init_callback.Run()); 88 BrokerHost broker_host(policy_, std::move(ipc_reader)); 89 for (;;) { 90 switch (broker_host.HandleRequest()) { 91 case BrokerHost::RequestStatus::LOST_CLIENT: 92 _exit(1); 93 case BrokerHost::RequestStatus::SUCCESS: 94 case BrokerHost::RequestStatus::FAILURE: 95 continue; 96 } 97 } 98 _exit(1); 99 } 100 NOTREACHED(); 101 return false; 102 } 103 104 void BrokerProcess::CloseChannel() { 105 broker_client_.reset(); 106 } 107 108 int BrokerProcess::Access(const char* pathname, int mode) const { 109 RAW_CHECK(initialized_); 110 return broker_client_->Access(pathname, mode); 111 } 112 113 int BrokerProcess::Open(const char* pathname, int flags) const { 114 RAW_CHECK(initialized_); 115 return broker_client_->Open(pathname, flags); 116 } 117 118 } // namespace syscall_broker 119 120 } // namespace sandbox. 121