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/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