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

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

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