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

Side by Side Diff: mojo/edk/system/channel_posix.cc

Issue 1985523002: [mojo-edk] Better validation of untrusted message data (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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 | « mojo/edk/system/channel.cc ('k') | mojo/edk/system/channel_win.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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "mojo/edk/system/channel.h" 5 #include "mojo/edk/system/channel.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <sys/uio.h> 8 #include <sys/uio.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <deque> 11 #include <deque>
12 #include <limits>
12 #include <memory> 13 #include <memory>
13 14
14 #include "base/bind.h" 15 #include "base/bind.h"
15 #include "base/location.h" 16 #include "base/location.h"
16 #include "base/macros.h" 17 #include "base/macros.h"
17 #include "base/memory/ref_counted.h" 18 #include "base/memory/ref_counted.h"
18 #include "base/message_loop/message_loop.h" 19 #include "base/message_loop/message_loop.h"
19 #include "base/synchronization/lock.h" 20 #include "base/synchronization/lock.h"
20 #include "base/task_runner.h" 21 #include "base/task_runner.h"
21 #include "mojo/edk/embedder/platform_channel_utils_posix.h" 22 #include "mojo/edk/embedder/platform_channel_utils_posix.h"
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 } 126 }
126 } 127 }
127 if (write_error) { 128 if (write_error) {
128 // Do not synchronously invoke OnError(). Write() may have been called by 129 // Do not synchronously invoke OnError(). Write() may have been called by
129 // the delegate and we don't want to re-enter it. 130 // the delegate and we don't want to re-enter it.
130 io_task_runner_->PostTask(FROM_HERE, 131 io_task_runner_->PostTask(FROM_HERE,
131 base::Bind(&ChannelPosix::OnError, this)); 132 base::Bind(&ChannelPosix::OnError, this));
132 } 133 }
133 } 134 }
134 135
135 ScopedPlatformHandleVectorPtr GetReadPlatformHandles( 136 bool GetReadPlatformHandles(
136 size_t num_handles, 137 size_t num_handles,
137 const void* extra_header, 138 const void* extra_header,
138 size_t extra_header_size) override { 139 size_t extra_header_size,
140 ScopedPlatformHandleVectorPtr* handles) override {
141 if (num_handles > std::numeric_limits<uint16_t>::max())
142 return false;
139 #if defined(OS_MACOSX) && !defined(OS_IOS) 143 #if defined(OS_MACOSX) && !defined(OS_IOS)
140 // On OSX, we can have mach ports which are located in the extra header 144 // On OSX, we can have mach ports which are located in the extra header
141 // section. 145 // section.
142 using MachPortsEntry = Channel::Message::MachPortsEntry; 146 using MachPortsEntry = Channel::Message::MachPortsEntry;
143 using MachPortsExtraHeader = Channel::Message::MachPortsExtraHeader; 147 using MachPortsExtraHeader = Channel::Message::MachPortsExtraHeader;
144 CHECK(extra_header_size >= 148 CHECK(extra_header_size >=
145 sizeof(MachPortsExtraHeader) + num_handles * sizeof(MachPortsEntry)); 149 sizeof(MachPortsExtraHeader) + num_handles * sizeof(MachPortsEntry));
146 const MachPortsExtraHeader* mach_ports_header = 150 const MachPortsExtraHeader* mach_ports_header =
147 reinterpret_cast<const MachPortsExtraHeader*>(extra_header); 151 reinterpret_cast<const MachPortsExtraHeader*>(extra_header);
148 size_t num_mach_ports = mach_ports_header->num_ports; 152 size_t num_mach_ports = mach_ports_header->num_ports;
149 CHECK(num_mach_ports <= num_handles); 153 CHECK(num_mach_ports <= num_handles);
150 if (incoming_platform_handles_.size() + num_mach_ports < num_handles) 154 if (incoming_platform_handles_.size() + num_mach_ports < num_handles) {
151 return nullptr; 155 handles->reset();
156 return true;
157 }
152 158
153 ScopedPlatformHandleVectorPtr handles( 159 handles->reset(new PlatformHandleVector(num_handles));
154 new PlatformHandleVector(num_handles));
155 const MachPortsEntry* mach_ports = mach_ports_header->entries; 160 const MachPortsEntry* mach_ports = mach_ports_header->entries;
156 for (size_t i = 0, mach_port_index = 0; i < num_handles; ++i) { 161 for (size_t i = 0, mach_port_index = 0; i < num_handles; ++i) {
157 if (mach_port_index < num_mach_ports && 162 if (mach_port_index < num_mach_ports &&
158 mach_ports[mach_port_index].index == i) { 163 mach_ports[mach_port_index].index == i) {
159 (*handles)[i] = PlatformHandle( 164 (*handles)->at(i) = PlatformHandle(
160 static_cast<mach_port_t>(mach_ports[mach_port_index].mach_port)); 165 static_cast<mach_port_t>(mach_ports[mach_port_index].mach_port));
161 CHECK((*handles)[i].type == PlatformHandle::Type::MACH); 166 CHECK((*handles)->at(i).type == PlatformHandle::Type::MACH);
162 // These are actually just Mach port names until they're resolved from 167 // These are actually just Mach port names until they're resolved from
163 // the remote process. 168 // the remote process.
164 (*handles)[i].type = PlatformHandle::Type::MACH_NAME; 169 (*handles)->at(i).type = PlatformHandle::Type::MACH_NAME;
165 mach_port_index++; 170 mach_port_index++;
166 } else { 171 } else {
167 CHECK(!incoming_platform_handles_.empty()); 172 CHECK(!incoming_platform_handles_.empty());
168 (*handles)[i] = incoming_platform_handles_.front(); 173 (*handles)->at(i) = incoming_platform_handles_.front();
169 incoming_platform_handles_.pop_front(); 174 incoming_platform_handles_.pop_front();
170 } 175 }
171 } 176 }
172 #else 177 #else
173 if (incoming_platform_handles_.size() < num_handles) 178 if (incoming_platform_handles_.size() < num_handles) {
174 return nullptr; 179 handles->reset();
180 return true;
181 }
175 182
176 ScopedPlatformHandleVectorPtr handles( 183 handles->reset(new PlatformHandleVector(num_handles));
177 new PlatformHandleVector(num_handles));
178 for (size_t i = 0; i < num_handles; ++i) { 184 for (size_t i = 0; i < num_handles; ++i) {
179 (*handles)[i] = incoming_platform_handles_.front(); 185 (*handles)->at(i) = incoming_platform_handles_.front();
180 incoming_platform_handles_.pop_front(); 186 incoming_platform_handles_.pop_front();
181 } 187 }
182 #endif 188 #endif
183 189
184 return handles; 190 return true;
185 } 191 }
186 192
187 private: 193 private:
188 ~ChannelPosix() override { 194 ~ChannelPosix() override {
189 DCHECK(!read_watcher_); 195 DCHECK(!read_watcher_);
190 DCHECK(!write_watcher_); 196 DCHECK(!write_watcher_);
191 for (auto handle : incoming_platform_handles_) 197 for (auto handle : incoming_platform_handles_)
192 handle.CloseIfNecessary(); 198 handle.CloseIfNecessary();
193 } 199 }
194 200
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 messages.pop_back(); 394 messages.pop_back();
389 } 395 }
390 return true; 396 return true;
391 } 397 }
392 } 398 }
393 399
394 return true; 400 return true;
395 } 401 }
396 402
397 #if defined(OS_MACOSX) 403 #if defined(OS_MACOSX)
398 void OnControlMessage(Message::Header::MessageType message_type, 404 bool OnControlMessage(Message::Header::MessageType message_type,
399 const void* payload, 405 const void* payload,
400 size_t payload_size, 406 size_t payload_size,
401 ScopedPlatformHandleVectorPtr handles) override { 407 ScopedPlatformHandleVectorPtr handles) override {
402 switch (message_type) { 408 switch (message_type) {
403 case Message::Header::MessageType::HANDLES_SENT: { 409 case Message::Header::MessageType::HANDLES_SENT: {
410 if (payload_size == 0)
411 break;
404 MessagePtr message(new Channel::Message( 412 MessagePtr message(new Channel::Message(
405 payload_size, 0, Message::Header::MessageType::HANDLES_SENT_ACK)); 413 payload_size, 0, Message::Header::MessageType::HANDLES_SENT_ACK));
406 memcpy(message->mutable_payload(), payload, payload_size); 414 memcpy(message->mutable_payload(), payload, payload_size);
407 Write(std::move(message)); 415 Write(std::move(message));
416 return true;
417 }
418
419 case Message::Header::MessageType::HANDLES_SENT_ACK: {
420 size_t num_fds = payload_size / sizeof(int);
421 if (num_fds == 0 || payload_size % sizeof(int) != 0)
422 break;
423
424 const int* fds = reinterpret_cast<const int*>(payload);
425 if (!CloseHandles(fds, num_fds))
426 break;
427 return true;
428 }
429
430 default:
408 break; 431 break;
409 }
410 case Message::Header::MessageType::HANDLES_SENT_ACK: {
411 const int* fds = reinterpret_cast<const int*>(payload);
412 size_t num_fds = payload_size / sizeof(*fds);
413 if (payload_size % sizeof(*fds) != 0 || !CloseHandles(fds, num_fds)) {
414 io_task_runner_->PostTask(FROM_HERE,
415 base::Bind(&ChannelPosix::OnError, this));
416 }
417 break;
418 }
419 default:
420 NOTREACHED();
421 } 432 }
433
434 return false;
422 } 435 }
423 436
424 // Closes handles referenced by |fds|. Returns false if |num_fds| is 0, or if 437 // Closes handles referenced by |fds|. Returns false if |num_fds| is 0, or if
425 // |fds| does not match a sequence of handles in |handles_to_close_|. 438 // |fds| does not match a sequence of handles in |handles_to_close_|.
426 bool CloseHandles(const int* fds, size_t num_fds) { 439 bool CloseHandles(const int* fds, size_t num_fds) {
427 base::AutoLock l(handles_to_close_lock_); 440 base::AutoLock l(handles_to_close_lock_);
428 if (!num_fds) 441 if (!num_fds)
429 return false; 442 return false;
430 443
431 auto start = 444 auto start =
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 // static 498 // static
486 scoped_refptr<Channel> Channel::Create( 499 scoped_refptr<Channel> Channel::Create(
487 Delegate* delegate, 500 Delegate* delegate,
488 ScopedPlatformHandle platform_handle, 501 ScopedPlatformHandle platform_handle,
489 scoped_refptr<base::TaskRunner> io_task_runner) { 502 scoped_refptr<base::TaskRunner> io_task_runner) {
490 return new ChannelPosix(delegate, std::move(platform_handle), io_task_runner); 503 return new ChannelPosix(delegate, std::move(platform_handle), io_task_runner);
491 } 504 }
492 505
493 } // namespace edk 506 } // namespace edk
494 } // namespace mojo 507 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/channel.cc ('k') | mojo/edk/system/channel_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698