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

Side by Side Diff: ipc/ipc_message_attachment_set.cc

Issue 835873004: IPC: Generalize FileDescriptorSet to MessageAttachmentSet (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Landing Created 5 years, 11 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/ipc_message_attachment_set.h ('k') | ipc/ipc_message_attachment_set_posix_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
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ipc/file_descriptor_set_posix.h" 5 #include "ipc/ipc_message_attachment_set.h"
6
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10 6
11 #include "base/logging.h" 7 #include "base/logging.h"
12 #include "base/posix/eintr_wrapper.h" 8 #include "base/posix/eintr_wrapper.h"
13 9
14 FileDescriptorSet::FileDescriptorSet() 10 #if defined(OS_POSIX)
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14 #endif // OS_POSIX
15
16 namespace IPC {
17
18 MessageAttachmentSet::MessageAttachmentSet()
15 : consumed_descriptor_highwater_(0) { 19 : consumed_descriptor_highwater_(0) {
16 } 20 }
17 21
18 FileDescriptorSet::~FileDescriptorSet() { 22 MessageAttachmentSet::~MessageAttachmentSet() {
19 if (consumed_descriptor_highwater_ == size()) 23 if (consumed_descriptor_highwater_ == size())
20 return; 24 return;
21 25
22 // We close all the owning descriptors. If this message should have 26 // We close all the owning descriptors. If this message should have
23 // been transmitted, then closing those with close flags set mirrors 27 // been transmitted, then closing those with close flags set mirrors
24 // the expected behaviour. 28 // the expected behaviour.
25 // 29 //
26 // If this message was received with more descriptors than expected 30 // If this message was received with more descriptors than expected
27 // (which could a DOS against the browser by a rogue renderer) then all 31 // (which could a DOS against the browser by a rogue renderer) then all
28 // the descriptors have their close flag set and we free all the extra 32 // the descriptors have their close flag set and we free all the extra
29 // kernel resources. 33 // kernel resources.
30 LOG(WARNING) << "FileDescriptorSet destroyed with unconsumed descriptors: " 34 LOG(WARNING) << "MessageAttachmentSet destroyed with unconsumed descriptors: "
31 << consumed_descriptor_highwater_ << "/" << size(); 35 << consumed_descriptor_highwater_ << "/" << size();
32 } 36 }
33 37
34 bool FileDescriptorSet::AddToBorrow(base::PlatformFile fd) { 38 unsigned MessageAttachmentSet::size() const {
39 #if defined(OS_POSIX)
40 return descriptors_.size();
41 #else
42 return 0;
43 #endif
44 }
45
46 #if defined(OS_POSIX)
47
48 bool MessageAttachmentSet::AddToBorrow(base::PlatformFile fd) {
35 DCHECK_EQ(consumed_descriptor_highwater_, 0u); 49 DCHECK_EQ(consumed_descriptor_highwater_, 0u);
36 50
37 if (size() == kMaxDescriptorsPerMessage) { 51 if (size() == kMaxDescriptorsPerMessage) {
38 DLOG(WARNING) << "Cannot add file descriptor. FileDescriptorSet full."; 52 DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full.";
39 return false; 53 return false;
40 } 54 }
41 55
42 descriptors_.push_back(fd); 56 descriptors_.push_back(fd);
43 return true; 57 return true;
44 } 58 }
45 59
46 bool FileDescriptorSet::AddToOwn(base::ScopedFD fd) { 60 bool MessageAttachmentSet::AddToOwn(base::ScopedFD fd) {
47 DCHECK_EQ(consumed_descriptor_highwater_, 0u); 61 DCHECK_EQ(consumed_descriptor_highwater_, 0u);
48 62
49 if (size() == kMaxDescriptorsPerMessage) { 63 if (size() == kMaxDescriptorsPerMessage) {
50 DLOG(WARNING) << "Cannot add file descriptor. FileDescriptorSet full."; 64 DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full.";
51 return false; 65 return false;
52 } 66 }
53 67
54 descriptors_.push_back(fd.get()); 68 descriptors_.push_back(fd.get());
55 owned_descriptors_.push_back(new base::ScopedFD(fd.Pass())); 69 owned_descriptors_.push_back(new base::ScopedFD(fd.Pass()));
56 DCHECK(size() <= kMaxDescriptorsPerMessage); 70 DCHECK(size() <= kMaxDescriptorsPerMessage);
57 return true; 71 return true;
58 } 72 }
59 73
60 base::PlatformFile FileDescriptorSet::TakeDescriptorAt(unsigned index) { 74 base::PlatformFile MessageAttachmentSet::TakeDescriptorAt(unsigned index) {
61 if (index >= size()) { 75 if (index >= size()) {
62 DLOG(WARNING) << "Accessing out of bound index:" 76 DLOG(WARNING) << "Accessing out of bound index:" << index << "/" << size();
63 << index << "/" << size();
64 return -1; 77 return -1;
65 } 78 }
66 79
67
68 // We should always walk the descriptors in order, so it's reasonable to 80 // We should always walk the descriptors in order, so it's reasonable to
69 // enforce this. Consider the case where a compromised renderer sends us 81 // enforce this. Consider the case where a compromised renderer sends us
70 // the following message: 82 // the following message:
71 // 83 //
72 // ExampleMsg: 84 // ExampleMsg:
73 // num_fds:2 msg:FD(index = 1) control:SCM_RIGHTS {n, m} 85 // num_fds:2 msg:FD(index = 1) control:SCM_RIGHTS {n, m}
74 // 86 //
75 // Here the renderer sent us a message which should have a descriptor, but 87 // Here the renderer sent us a message which should have a descriptor, but
76 // actually sent two in an attempt to fill our fd table and kill us. By 88 // actually sent two in an attempt to fill our fd table and kill us. By
77 // setting the index of the descriptor in the message to 1 (it should be 89 // setting the index of the descriptor in the message to 1 (it should be
(...skipping 17 matching lines...) Expand all
95 consumed_descriptor_highwater_ = index + 1; 107 consumed_descriptor_highwater_ = index + 1;
96 108
97 base::PlatformFile file = descriptors_[index]; 109 base::PlatformFile file = descriptors_[index];
98 110
99 // TODO(morrita): In production, descriptors_.size() should be same as 111 // TODO(morrita): In production, descriptors_.size() should be same as
100 // owned_descriptors_.size() as all read descriptors are owned by Message. 112 // owned_descriptors_.size() as all read descriptors are owned by Message.
101 // We have to do this because unit test breaks this assumption. It should be 113 // We have to do this because unit test breaks this assumption. It should be
102 // changed to exercise with own-able descriptors. 114 // changed to exercise with own-able descriptors.
103 for (ScopedVector<base::ScopedFD>::const_iterator i = 115 for (ScopedVector<base::ScopedFD>::const_iterator i =
104 owned_descriptors_.begin(); 116 owned_descriptors_.begin();
105 i != owned_descriptors_.end(); 117 i != owned_descriptors_.end(); ++i) {
106 ++i) {
107 if ((*i)->get() == file) { 118 if ((*i)->get() == file) {
108 ignore_result((*i)->release()); 119 ignore_result((*i)->release());
109 break; 120 break;
110 } 121 }
111 } 122 }
112 123
113 return file; 124 return file;
114 } 125 }
115 126
116 void FileDescriptorSet::PeekDescriptors(base::PlatformFile* buffer) const { 127 void MessageAttachmentSet::PeekDescriptors(base::PlatformFile* buffer) const {
117 std::copy(descriptors_.begin(), descriptors_.end(), buffer); 128 std::copy(descriptors_.begin(), descriptors_.end(), buffer);
118 } 129 }
119 130
120 bool FileDescriptorSet::ContainsDirectoryDescriptor() const { 131 bool MessageAttachmentSet::ContainsDirectoryDescriptor() const {
121 struct stat st; 132 struct stat st;
122 133
123 for (std::vector<base::PlatformFile>::const_iterator i = descriptors_.begin(); 134 for (std::vector<base::PlatformFile>::const_iterator i = descriptors_.begin();
124 i != descriptors_.end(); 135 i != descriptors_.end(); ++i) {
125 ++i) {
126 if (fstat(*i, &st) == 0 && S_ISDIR(st.st_mode)) 136 if (fstat(*i, &st) == 0 && S_ISDIR(st.st_mode))
127 return true; 137 return true;
128 } 138 }
129 139
130 return false; 140 return false;
131 } 141 }
132 142
133 void FileDescriptorSet::CommitAll() { 143 void MessageAttachmentSet::CommitAll() {
134 descriptors_.clear(); 144 descriptors_.clear();
135 owned_descriptors_.clear(); 145 owned_descriptors_.clear();
136 consumed_descriptor_highwater_ = 0; 146 consumed_descriptor_highwater_ = 0;
137 } 147 }
138 148
139 void FileDescriptorSet::ReleaseFDsToClose( 149 void MessageAttachmentSet::ReleaseFDsToClose(
140 std::vector<base::PlatformFile>* fds) { 150 std::vector<base::PlatformFile>* fds) {
141 for (ScopedVector<base::ScopedFD>::iterator i = owned_descriptors_.begin(); 151 for (ScopedVector<base::ScopedFD>::iterator i = owned_descriptors_.begin();
142 i != owned_descriptors_.end(); 152 i != owned_descriptors_.end(); ++i) {
143 ++i) {
144 fds->push_back((*i)->release()); 153 fds->push_back((*i)->release());
145 } 154 }
146 155
147 CommitAll(); 156 CommitAll();
148 } 157 }
149 158
150 void FileDescriptorSet::AddDescriptorsToOwn(const base::PlatformFile* buffer, 159 void MessageAttachmentSet::AddDescriptorsToOwn(const base::PlatformFile* buffer,
151 unsigned count) { 160 unsigned count) {
152 DCHECK(count <= kMaxDescriptorsPerMessage); 161 DCHECK(count <= kMaxDescriptorsPerMessage);
153 DCHECK_EQ(size(), 0u); 162 DCHECK_EQ(size(), 0u);
154 DCHECK_EQ(consumed_descriptor_highwater_, 0u); 163 DCHECK_EQ(consumed_descriptor_highwater_, 0u);
155 164
156 descriptors_.reserve(count); 165 descriptors_.reserve(count);
157 owned_descriptors_.reserve(count); 166 owned_descriptors_.reserve(count);
158 for (unsigned i = 0; i < count; ++i) { 167 for (unsigned i = 0; i < count; ++i) {
159 descriptors_.push_back(buffer[i]); 168 descriptors_.push_back(buffer[i]);
160 owned_descriptors_.push_back(new base::ScopedFD(buffer[i])); 169 owned_descriptors_.push_back(new base::ScopedFD(buffer[i]));
161 } 170 }
162 } 171 }
172
173 #endif // OS_POSIX
174
175 } // namespace IPC
176
177
OLDNEW
« no previous file with comments | « ipc/ipc_message_attachment_set.h ('k') | ipc/ipc_message_attachment_set_posix_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698