Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: ipc/file_descriptor_set_posix.cc

Issue 155905: Separates ipc code from common (http://crbug.com/16829) (Closed)
Patch Set: Fixes reference to 'common_message_traits' it's actually 'common_param_traits' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ipc/file_descriptor_set_posix.h ('k') | ipc/file_descriptor_set_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "ipc/file_descriptor_set_posix.h"
6
7 #include "base/eintr_wrapper.h"
8 #include "base/logging.h"
9
10 FileDescriptorSet::FileDescriptorSet()
11 : consumed_descriptor_highwater_(0) {
12 }
13
14 FileDescriptorSet::~FileDescriptorSet() {
15 if (consumed_descriptor_highwater_ == descriptors_.size())
16 return;
17
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.
22 //
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));
31 }
32 }
33
34 bool FileDescriptorSet::Add(int fd) {
35 if (descriptors_.size() == MAX_DESCRIPTORS_PER_MESSAGE)
36 return false;
37
38 struct base::FileDescriptor sd;
39 sd.fd = fd;
40 sd.auto_close = false;
41 descriptors_.push_back(sd);
42 return true;
43 }
44
45 bool FileDescriptorSet::AddAndAutoClose(int fd) {
46 if (descriptors_.size() == MAX_DESCRIPTORS_PER_MESSAGE)
47 return false;
48
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;
55 }
56
57 int FileDescriptorSet::GetDescriptorAt(unsigned index) const {
58 if (index >= descriptors_.size())
59 return -1;
60
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:
64 //
65 // ExampleMsg:
66 // num_fds:2 msg:FD(index = 1) control:SCM_RIGHTS {n, m}
67 //
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.
73 //
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.
76 //
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;
82
83 if (index != consumed_descriptor_highwater_)
84 return -1;
85
86 consumed_descriptor_highwater_ = index + 1;
87 return descriptors_[index].fd;
88 }
89
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;
94 }
95 }
96
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));
102 }
103 descriptors_.clear();
104 consumed_descriptor_highwater_ = 0;
105 }
106
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);
111
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);
118 }
119 }
OLDNEW
« no previous file with comments | « ipc/file_descriptor_set_posix.h ('k') | ipc/file_descriptor_set_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698