summaryrefslogtreecommitdiffstats
path: root/chrome/common/file_descriptor_posix.cc
blob: 7db95140def6a92ba64fe1ceb44ff4f7f9ef9dba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/file_descriptor_posix.h"

#include "base/logging.h"

DescriptorSet::DescriptorSet()
    : next_descriptor_(0) {
}

DescriptorSet::~DescriptorSet() {
  if (next_descriptor_ == descriptors_.size())
    return;

  LOG(WARNING) << "DescriptorSet destroyed with unconsumed descriptors";
  // We close all the descriptors where the close flag is set. If this
  // message should have been transmitted, then closing those with close
  // flags set mirrors the expected behaviour.
  //
  // If this message was received with more descriptors than expected
  // (which could a DOS against the browser by a rouge renderer) then all
  // the descriptors have their close flag set and we free all the extra
  // kernel resources.
  for (unsigned i = next_descriptor_; i < descriptors_.size(); ++i) {
    if (descriptors_[i].auto_close)
      close(descriptors_[i].fd);
  }
}

void DescriptorSet::Add(int fd) {
  struct FileDescriptor sd;
  sd.fd = fd;
  sd.auto_close = false;
  descriptors_.push_back(sd);
  DCHECK(descriptors_.size() <= MAX_DESCRIPTORS_PER_MESSAGE);
}

void DescriptorSet::AddAndAutoClose(int fd) {
  struct FileDescriptor sd;
  sd.fd = fd;
  sd.auto_close = true;
  descriptors_.push_back(sd);
  DCHECK(descriptors_.size() <= MAX_DESCRIPTORS_PER_MESSAGE);
}

int DescriptorSet::NextDescriptor() {
  if (next_descriptor_ == descriptors_.size())
    return -1;

  return descriptors_[next_descriptor_++].fd;
}

void DescriptorSet::GetDescriptors(int* buffer) const {
  for (std::vector<FileDescriptor>::const_iterator
       i = descriptors_.begin(); i != descriptors_.end(); ++i) {
    *(buffer++) = i->fd;
  }
}

void DescriptorSet::CommitAll() {
  for (std::vector<FileDescriptor>::iterator
       i = descriptors_.begin(); i != descriptors_.end(); ++i) {
    if (i->auto_close)
      close(i->fd);
  }
  descriptors_.clear();
}

void DescriptorSet::SetDescriptors(const int* buffer, unsigned count) {
  DCHECK(count <= MAX_DESCRIPTORS_PER_MESSAGE);
  DCHECK(descriptors_.size() == 0);

  descriptors_.reserve(count);
  for (unsigned i = 0; i < count; ++i) {
    struct FileDescriptor sd;
    sd.fd = buffer[i];
    sd.auto_close = true;
    descriptors_.push_back(sd);
  }
}

void DescriptorSet::TakeFrom(DescriptorSet* other) {
  DCHECK(descriptors_.size() == 0);

  descriptors_.swap(other->descriptors_);
  next_descriptor_ = other->next_descriptor_;
  other->next_descriptor_ = 0;
}