LCOV - code coverage report
Current view: directory - ipc/chromium/src/chrome/common - file_descriptor_set_posix.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 61 0 0.0 %
Date: 2012-06-02 Functions: 8 0 0.0 %

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

Generated by: LCOV version 1.7