Home | History | Annotate | Download | only in ipc
      1 // Copyright (c) 2011 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 "ipc/file_descriptor_set_posix.h"
      6 
      7 #include <sys/types.h>
      8 #include <sys/stat.h>
      9 #include <unistd.h>
     10 
     11 #include "base/logging.h"
     12 #include "base/posix/eintr_wrapper.h"
     13 
     14 FileDescriptorSet::FileDescriptorSet()
     15     : consumed_descriptor_highwater_(0) {
     16 }
     17 
     18 FileDescriptorSet::~FileDescriptorSet() {
     19   if (consumed_descriptor_highwater_ == descriptors_.size())
     20     return;
     21 
     22   LOG(WARNING) << "FileDescriptorSet destroyed with unconsumed descriptors";
     23   // We close all the descriptors where the close flag is set. If this
     24   // message should have been transmitted, then closing those with close
     25   // flags set mirrors the expected behaviour.
     26   //
     27   // If this message was received with more descriptors than expected
     28   // (which could a DOS against the browser by a rogue renderer) then all
     29   // the descriptors have their close flag set and we free all the extra
     30   // kernel resources.
     31   for (unsigned i = consumed_descriptor_highwater_;
     32        i < descriptors_.size(); ++i) {
     33     if (descriptors_[i].auto_close)
     34       if (IGNORE_EINTR(close(descriptors_[i].fd)) < 0)
     35         PLOG(ERROR) << "close";
     36   }
     37 }
     38 
     39 bool FileDescriptorSet::Add(int fd) {
     40   if (descriptors_.size() == kMaxDescriptorsPerMessage) {
     41     DLOG(WARNING) << "Cannot add file descriptor. FileDescriptorSet full.";
     42     return false;
     43   }
     44 
     45   struct base::FileDescriptor sd;
     46   sd.fd = fd;
     47   sd.auto_close = false;
     48   descriptors_.push_back(sd);
     49   return true;
     50 }
     51 
     52 bool FileDescriptorSet::AddAndAutoClose(int fd) {
     53   if (descriptors_.size() == kMaxDescriptorsPerMessage) {
     54     DLOG(WARNING) << "Cannot add file descriptor. FileDescriptorSet full.";
     55     return false;
     56   }
     57 
     58   struct base::FileDescriptor sd;
     59   sd.fd = fd;
     60   sd.auto_close = true;
     61   descriptors_.push_back(sd);
     62   DCHECK(descriptors_.size() <= kMaxDescriptorsPerMessage);
     63   return true;
     64 }
     65 
     66 int FileDescriptorSet::GetDescriptorAt(unsigned index) const {
     67   if (index >= descriptors_.size())
     68     return -1;
     69 
     70   // We should always walk the descriptors in order, so it's reasonable to
     71   // enforce this. Consider the case where a compromised renderer sends us
     72   // the following message:
     73   //
     74   //   ExampleMsg:
     75   //     num_fds:2 msg:FD(index = 1) control:SCM_RIGHTS {n, m}
     76   //
     77   // Here the renderer sent us a message which should have a descriptor, but
     78   // actually sent two in an attempt to fill our fd table and kill us. By
     79   // setting the index of the descriptor in the message to 1 (it should be
     80   // 0), we would record a highwater of 1 and then consider all the
     81   // descriptors to have been used.
     82   //
     83   // So we can either track of the use of each descriptor in a bitset, or we
     84   // can enforce that we walk the indexes strictly in order.
     85   //
     86   // There's one more wrinkle: When logging messages, we may reparse them. So
     87   // we have an exception: When the consumed_descriptor_highwater_ is at the
     88   // end of the array and index 0 is requested, we reset the highwater value.
     89   if (index == 0 && consumed_descriptor_highwater_ == descriptors_.size())
     90     consumed_descriptor_highwater_ = 0;
     91 
     92   if (index != consumed_descriptor_highwater_)
     93     return -1;
     94 
     95   consumed_descriptor_highwater_ = index + 1;
     96   return descriptors_[index].fd;
     97 }
     98 
     99 void FileDescriptorSet::GetDescriptors(int* buffer) const {
    100   for (std::vector<base::FileDescriptor>::const_iterator
    101        i = descriptors_.begin(); i != descriptors_.end(); ++i) {
    102     *(buffer++) = i->fd;
    103   }
    104 }
    105 
    106 bool FileDescriptorSet::ContainsDirectoryDescriptor() const {
    107   struct stat st;
    108 
    109   for (std::vector<base::FileDescriptor>::const_iterator
    110        i = descriptors_.begin(); i != descriptors_.end(); ++i) {
    111     if (fstat(i->fd, &st) == 0 && S_ISDIR(st.st_mode))
    112       return true;
    113   }
    114 
    115   return false;
    116 }
    117 
    118 void FileDescriptorSet::CommitAll() {
    119   for (std::vector<base::FileDescriptor>::iterator
    120        i = descriptors_.begin(); i != descriptors_.end(); ++i) {
    121     if (i->auto_close)
    122       if (IGNORE_EINTR(close(i->fd)) < 0)
    123         PLOG(ERROR) << "close";
    124   }
    125   descriptors_.clear();
    126   consumed_descriptor_highwater_ = 0;
    127 }
    128 
    129 void FileDescriptorSet::ReleaseFDsToClose(std::vector<int>* fds) {
    130   for (std::vector<base::FileDescriptor>::iterator
    131        i = descriptors_.begin(); i != descriptors_.end(); ++i) {
    132     if (i->auto_close)
    133       fds->push_back(i->fd);
    134   }
    135   descriptors_.clear();
    136   consumed_descriptor_highwater_ = 0;
    137 }
    138 
    139 void FileDescriptorSet::SetDescriptors(const int* buffer, unsigned count) {
    140   DCHECK(count <= kMaxDescriptorsPerMessage);
    141   DCHECK_EQ(descriptors_.size(), 0u);
    142   DCHECK_EQ(consumed_descriptor_highwater_, 0u);
    143 
    144   descriptors_.reserve(count);
    145   for (unsigned i = 0; i < count; ++i) {
    146     struct base::FileDescriptor sd;
    147     sd.fd = buffer[i];
    148     sd.auto_close = true;
    149     descriptors_.push_back(sd);
    150   }
    151 }
    152