Home | History | Annotate | Download | only in syscall_broker
      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