LCOV - code coverage report
Current view: top level - ipc/chromium/src/chrome/common - file_descriptor_set_posix.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 45 62 72.6 %
Date: 2017-07-14 16:53:18 Functions: 7 8 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       4             : // Use of this source code is governed by a BSD-style license that can be
       5             : // found in the LICENSE file.
       6             : 
       7             : #include "chrome/common/file_descriptor_set_posix.h"
       8             : 
       9             : #include "base/eintr_wrapper.h"
      10             : #include "base/logging.h"
      11             : 
      12             : #include <unistd.h>
      13             : 
      14         433 : FileDescriptorSet::FileDescriptorSet()
      15         433 :     : consumed_descriptor_highwater_(0) {
      16         433 : }
      17             : 
      18         862 : FileDescriptorSet::~FileDescriptorSet() {
      19         431 :   if (consumed_descriptor_highwater_ == descriptors_.size())
      20         431 :     return;
      21             : 
      22           0 :   CHROMIUM_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           0 :   for (unsigned i = consumed_descriptor_highwater_;
      32           0 :        i < descriptors_.size(); ++i) {
      33           0 :     if (descriptors_[i].auto_close)
      34           0 :       HANDLE_EINTR(close(descriptors_[i].fd));
      35             :   }
      36         431 : }
      37             : 
      38           0 : bool FileDescriptorSet::Add(int fd) {
      39           0 :   if (descriptors_.size() == MAX_DESCRIPTORS_PER_MESSAGE)
      40           0 :     return false;
      41             : 
      42           0 :   struct base::FileDescriptor sd;
      43           0 :   sd.fd = fd;
      44           0 :   sd.auto_close = false;
      45           0 :   descriptors_.push_back(sd);
      46           0 :   return true;
      47             : }
      48             : 
      49          55 : bool FileDescriptorSet::AddAndAutoClose(int fd) {
      50          55 :   if (descriptors_.size() == MAX_DESCRIPTORS_PER_MESSAGE)
      51           0 :     return false;
      52             : 
      53          55 :   struct base::FileDescriptor sd;
      54          55 :   sd.fd = fd;
      55          55 :   sd.auto_close = true;
      56          55 :   descriptors_.push_back(sd);
      57          55 :   DCHECK(descriptors_.size() <= MAX_DESCRIPTORS_PER_MESSAGE);
      58          55 :   return true;
      59             : }
      60             : 
      61          52 : int FileDescriptorSet::GetDescriptorAt(unsigned index) const {
      62          52 :   if (index >= descriptors_.size())
      63           0 :     return -1;
      64             : 
      65             :   // We should always walk the descriptors in order, so it's reasonable to
      66             :   // enforce this. Consider the case where a compromised renderer sends us
      67             :   // the following message:
      68             :   //
      69             :   //   ExampleMsg:
      70             :   //     num_fds:2 msg:FD(index = 1) control:SCM_RIGHTS {n, m}
      71             :   //
      72             :   // Here the renderer sent us a message which should have a descriptor, but
      73             :   // actually sent two in an attempt to fill our fd table and kill us. By
      74             :   // setting the index of the descriptor in the message to 1 (it should be
      75             :   // 0), we would record a highwater of 1 and then consider all the
      76             :   // descriptors to have been used.
      77             :   //
      78             :   // So we can either track of the use of each descriptor in a bitset, or we
      79             :   // can enforce that we walk the indexes strictly in order.
      80             :   //
      81             :   // There's one more wrinkle: When logging messages, we may reparse them. So
      82             :   // we have an exception: When the consumed_descriptor_highwater_ is at the
      83             :   // end of the array and index 0 is requested, we reset the highwater value.
      84          52 :   if (index == 0 && consumed_descriptor_highwater_ == descriptors_.size())
      85           0 :     consumed_descriptor_highwater_ = 0;
      86             : 
      87          52 :   if (index != consumed_descriptor_highwater_)
      88           0 :     return -1;
      89             : 
      90          52 :   consumed_descriptor_highwater_ = index + 1;
      91          52 :   return descriptors_[index].fd;
      92             : }
      93             : 
      94          19 : void FileDescriptorSet::GetDescriptors(int* buffer) const {
      95         107 :   for (std::vector<base::FileDescriptor>::const_iterator
      96          61 :        i = descriptors_.begin(); i != descriptors_.end(); ++i) {
      97          23 :     *(buffer++) = i->fd;
      98             :   }
      99          19 : }
     100             : 
     101         398 : void FileDescriptorSet::CommitAll() {
     102         865 :   for (std::vector<base::FileDescriptor>::iterator
     103         819 :        i = descriptors_.begin(); i != descriptors_.end(); ++i) {
     104          23 :     if (i->auto_close)
     105          23 :       HANDLE_EINTR(close(i->fd));
     106             :   }
     107         398 :   descriptors_.clear();
     108         398 :   consumed_descriptor_highwater_ = 0;
     109         398 : }
     110             : 
     111          18 : void FileDescriptorSet::SetDescriptors(const int* buffer, unsigned count) {
     112          18 :   DCHECK_LE(count, MAX_DESCRIPTORS_PER_MESSAGE);
     113          18 :   DCHECK_EQ(descriptors_.size(), 0u);
     114          18 :   DCHECK_EQ(consumed_descriptor_highwater_, 0u);
     115             : 
     116          18 :   descriptors_.reserve(count);
     117          40 :   for (unsigned i = 0; i < count; ++i) {
     118          22 :     struct base::FileDescriptor sd;
     119          22 :     sd.fd = buffer[i];
     120          22 :     sd.auto_close = true;
     121          22 :     descriptors_.push_back(sd);
     122             :   }
     123          18 : }

Generated by: LCOV version 1.13