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