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

Side by Side Diff: chrome/nacl/nacl_ipc_adapter.cc

Issue 10815087: Change NaClIPCAdapter to save translated descriptors to the rewritten message. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 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 | Annotate | Revision Log
« no previous file with comments | « chrome/nacl/nacl_ipc_adapter.h ('k') | no next file » | 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/nacl/nacl_ipc_adapter.h" 5 #include "chrome/nacl/nacl_ipc_adapter.h"
6 6
7 #include <limits.h> 7 #include <limits.h>
8 #include <string.h> 8 #include <string.h>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 class NaClIPCAdapter::RewrittenMessage 134 class NaClIPCAdapter::RewrittenMessage
135 : public base::RefCounted<RewrittenMessage> { 135 : public base::RefCounted<RewrittenMessage> {
136 public: 136 public:
137 RewrittenMessage(); 137 RewrittenMessage();
138 138
139 bool is_consumed() const { return data_read_cursor_ == data_len_; } 139 bool is_consumed() const { return data_read_cursor_ == data_len_; }
140 140
141 void SetData(const NaClIPCAdapter::NaClMessageHeader& header, 141 void SetData(const NaClIPCAdapter::NaClMessageHeader& header,
142 const void* payload, size_t payload_length); 142 const void* payload, size_t payload_length);
143 143
144 int Read(char* dest_buffer, size_t dest_buffer_size); 144 int TransferData(NaClImcTypedMsgHdr* msg);
145
146 void AddDescriptor(nacl::DescWrapper* desc) { descs_.push_back(desc); }
147
148 int desc_count() const { return static_cast<int>(descs_.size()); }
dmichael (off chromium) 2012/07/25 16:00:40 why not just use size_t for the return type?
bbudge 2012/07/25 16:54:14 Done.
145 149
146 private: 150 private:
147 friend class base::RefCounted<RewrittenMessage>; 151 friend class base::RefCounted<RewrittenMessage>;
148 ~RewrittenMessage() {} 152 ~RewrittenMessage() {}
149 153
150 scoped_array<char> data_; 154 scoped_array<char> data_;
151 size_t data_len_; 155 size_t data_len_;
152 156
153 // Offset into data where the next read will happen. This will be equal to 157 // Offset into data where the next read will happen. This will be equal to
154 // data_len_ when all data has been consumed. 158 // data_len_ when all data has been consumed.
155 size_t data_read_cursor_; 159 size_t data_read_cursor_;
160
161 // Wrapped descriptors for transfer to untrusted code.
162 ScopedVector<nacl::DescWrapper> descs_;
156 }; 163 };
157 164
158 NaClIPCAdapter::RewrittenMessage::RewrittenMessage() 165 NaClIPCAdapter::RewrittenMessage::RewrittenMessage()
159 : data_len_(0), 166 : data_len_(0),
160 data_read_cursor_(0) { 167 data_read_cursor_(0) {
161 } 168 }
162 169
163 void NaClIPCAdapter::RewrittenMessage::SetData( 170 void NaClIPCAdapter::RewrittenMessage::SetData(
164 const NaClIPCAdapter::NaClMessageHeader& header, 171 const NaClIPCAdapter::NaClMessageHeader& header,
165 const void* payload, 172 const void* payload,
166 size_t payload_length) { 173 size_t payload_length) {
167 DCHECK(!data_.get() && data_len_ == 0); 174 DCHECK(!data_.get() && data_len_ == 0);
168 size_t header_len = sizeof(NaClIPCAdapter::NaClMessageHeader); 175 size_t header_len = sizeof(NaClIPCAdapter::NaClMessageHeader);
169 data_len_ = header_len + payload_length; 176 data_len_ = header_len + payload_length;
170 data_.reset(new char[data_len_]); 177 data_.reset(new char[data_len_]);
171 178
172 memcpy(data_.get(), &header, sizeof(NaClIPCAdapter::NaClMessageHeader)); 179 memcpy(data_.get(), &header, sizeof(NaClIPCAdapter::NaClMessageHeader));
173 memcpy(&data_[header_len], payload, payload_length); 180 memcpy(&data_[header_len], payload, payload_length);
174 } 181 }
175 182
176 int NaClIPCAdapter::RewrittenMessage::Read(char* dest_buffer, 183 int NaClIPCAdapter::RewrittenMessage::TransferData(NaClImcTypedMsgHdr* msg) {
dmichael (off chromium) 2012/07/25 16:00:40 I think I liked |Read| better for the name. It's n
bbudge 2012/07/25 16:54:14 I was finding 'Read' to be confusing. But 2 agains
177 size_t dest_buffer_size) {
178 CHECK(data_len_ >= data_read_cursor_); 184 CHECK(data_len_ >= data_read_cursor_);
185 char* dest_buffer = static_cast<char*>(msg->iov[0].base);
186 size_t dest_buffer_size = msg->iov[0].length;
179 size_t bytes_to_write = std::min(dest_buffer_size, 187 size_t bytes_to_write = std::min(dest_buffer_size,
180 data_len_ - data_read_cursor_); 188 data_len_ - data_read_cursor_);
181 if (bytes_to_write == 0) 189 if (bytes_to_write == 0)
182 return 0; 190 return 0;
183 191
184 memcpy(dest_buffer, &data_[data_read_cursor_], bytes_to_write); 192 memcpy(dest_buffer, &data_[data_read_cursor_], bytes_to_write);
185 data_read_cursor_ += bytes_to_write; 193 data_read_cursor_ += bytes_to_write;
194
195 // Once all data has been consumed, transfer any file descriptors.
196 if (is_consumed()) {
197 nacl_abi_size_t desc_count = static_cast<nacl_abi_size_t>(descs_.size());
198 CHECK(desc_count <= msg->ndesc_length);
199 msg->ndesc_length = desc_count;
200 for (nacl_abi_size_t i = 0; i < desc_count; i++) {
201 // Copy the NaClDesc to the buffer and add a ref so it won't be freed
202 // when we clear our ScopedVector.
203 msg->ndescv[i] = descs_[i]->desc();
204 NaClDescRef(descs_[i]->desc());
205 }
206 descs_.clear();
207 }
186 return static_cast<int>(bytes_to_write); 208 return static_cast<int>(bytes_to_write);
187 } 209 }
188 210
189 NaClIPCAdapter::LockedData::LockedData() 211 NaClIPCAdapter::LockedData::LockedData()
190 : channel_closed_(false) { 212 : channel_closed_(false) {
191 } 213 }
192 214
193 NaClIPCAdapter::LockedData::~LockedData() { 215 NaClIPCAdapter::LockedData::~LockedData() {
194 } 216 }
195 217
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 // When the plugin gives us too much data, it's an error. 309 // When the plugin gives us too much data, it's an error.
288 ClearToBeSent(); 310 ClearToBeSent();
289 return -1; 311 return -1;
290 } 312 }
291 } 313 }
292 314
293 int NaClIPCAdapter::BlockingReceive(NaClImcTypedMsgHdr* msg) { 315 int NaClIPCAdapter::BlockingReceive(NaClImcTypedMsgHdr* msg) {
294 if (msg->iov_length != 1) 316 if (msg->iov_length != 1)
295 return -1; 317 return -1;
296 318
297 char* output_buffer = static_cast<char*>(msg->iov[0].base);
298 size_t output_buffer_size = msg->iov[0].length;
299 int retval = 0; 319 int retval = 0;
300 { 320 {
301 base::AutoLock lock(lock_); 321 base::AutoLock lock(lock_);
302 while (locked_data_.to_be_received_.empty() && 322 while (locked_data_.to_be_received_.empty() &&
303 !locked_data_.channel_closed_) 323 !locked_data_.channel_closed_)
304 cond_var_.Wait(); 324 cond_var_.Wait();
305 if (locked_data_.channel_closed_) { 325 if (locked_data_.channel_closed_) {
306 retval = -1; 326 retval = -1;
307 } else { 327 } else {
308 retval = LockedReceive(output_buffer, output_buffer_size); 328 retval = LockedReceive(msg);
309 DCHECK(retval > 0); 329 DCHECK(retval > 0);
310 } 330 }
311 int desc_count = static_cast<int>(locked_data_.nacl_descs_.size());
312 CHECK(desc_count <= NACL_ABI_IMC_DESC_MAX);
313 msg->ndesc_length = desc_count;
314 for (int i = 0; i < desc_count; i++)
315 msg->ndescv[i] = locked_data_.nacl_descs_[i]->desc();
316 } 331 }
317 cond_var_.Signal(); 332 cond_var_.Signal();
318 return retval; 333 return retval;
319 } 334 }
320 335
321 void NaClIPCAdapter::CloseChannel() { 336 void NaClIPCAdapter::CloseChannel() {
322 { 337 {
323 base::AutoLock lock(lock_); 338 base::AutoLock lock(lock_);
324 locked_data_.channel_closed_ = true; 339 locked_data_.channel_closed_ = true;
325 } 340 }
326 cond_var_.Signal(); 341 cond_var_.Signal();
327 342
328 task_runner_->PostTask(FROM_HERE, 343 task_runner_->PostTask(FROM_HERE,
329 base::Bind(&NaClIPCAdapter::CloseChannelOnIOThread, this)); 344 base::Bind(&NaClIPCAdapter::CloseChannelOnIOThread, this));
330 } 345 }
331 346
332 NaClDesc* NaClIPCAdapter::MakeNaClDesc() { 347 NaClDesc* NaClIPCAdapter::MakeNaClDesc() {
333 return MakeNaClDescCustom(this); 348 return MakeNaClDescCustom(this);
334 } 349 }
335 350
336 #if defined(OS_POSIX) 351 #if defined(OS_POSIX)
337 int NaClIPCAdapter::TakeClientFileDescriptor() { 352 int NaClIPCAdapter::TakeClientFileDescriptor() {
338 return io_thread_data_.channel_->TakeClientFileDescriptor(); 353 return io_thread_data_.channel_->TakeClientFileDescriptor();
339 } 354 }
340 #endif 355 #endif
341 356
342 bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& message) { 357 bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) {
343 { 358 {
344 base::AutoLock lock(lock_); 359 base::AutoLock lock(lock_);
345 360
346 // Clear any descriptors left from the prior message. 361 scoped_refptr<RewrittenMessage> rewritten_msg(new RewrittenMessage);
347 locked_data_.nacl_descs_.clear(); 362 locked_data_.to_be_received_.push(rewritten_msg);
dmichael (off chromium) 2012/07/25 16:00:40 Should this part maybe be at the end of SaveMessag
bbudge 2012/07/25 16:54:14 Good idea. Done.
348 363
349 PickleIterator it(message); 364 PickleIterator it(msg);
350 switch (message.type()) { 365 switch (msg.type()) {
351 case PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID: { 366 case PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID: {
352 int instance_id; 367 int instance_id;
353 int resource_id; 368 int resource_id;
354 int result_code; 369 int result_code;
355 NaClHandle sock_handle; 370 NaClHandle sock_handle;
356 NaClHandle shm_handle; 371 NaClHandle shm_handle;
357 uint32_t shm_length; 372 uint32_t shm_length;
358 if (ReadHostResource(&it, &instance_id, &resource_id) && 373 if (ReadHostResource(&it, &instance_id, &resource_id) &&
359 it.ReadInt(&result_code) && 374 it.ReadInt(&result_code) &&
360 ReadFileDescriptor(message, &it, &sock_handle) && 375 ReadFileDescriptor(msg, &it, &sock_handle) &&
361 ReadFileDescriptor(message, &it, &shm_handle) && 376 ReadFileDescriptor(msg, &it, &shm_handle) &&
362 it.ReadUInt32(&shm_length)) { 377 it.ReadUInt32(&shm_length)) {
363 // Our caller, OnMessageReceived, holds the lock for locked_data_. 378 // Import the sync socket.
364 // Import the sync socket. Use DescWrappers to simplify clean up.
365 nacl::DescWrapperFactory factory; 379 nacl::DescWrapperFactory factory;
366 scoped_ptr<nacl::DescWrapper> socket_wrapper( 380 scoped_ptr<nacl::DescWrapper> socket_wrapper(
367 factory.ImportSyncSocketHandle(sock_handle)); 381 factory.ImportSyncSocketHandle(sock_handle));
368 // Import the shared memory handle and increase its size by 4 bytes to 382 // Import the shared memory handle and increase its size by 4 bytes to
369 // accommodate the length data we write to signal the host. 383 // accommodate the length data we write at the end to signal the host.
370 scoped_ptr<nacl::DescWrapper> shm_wrapper( 384 scoped_ptr<nacl::DescWrapper> shm_wrapper(
371 factory.ImportShmHandle(shm_handle, shm_length + sizeof(uint32))); 385 factory.ImportShmHandle(shm_handle, shm_length + sizeof(uint32)));
372 if (shm_wrapper.get() && socket_wrapper.get()) { 386 if (shm_wrapper.get() && socket_wrapper.get()) {
373 locked_data_.nacl_descs_.push_back(socket_wrapper.release()); 387 rewritten_msg->AddDescriptor(socket_wrapper.release());
374 locked_data_.nacl_descs_.push_back(shm_wrapper.release()); 388 rewritten_msg->AddDescriptor(shm_wrapper.release());
375 } 389 }
376 #if defined(OS_POSIX) 390 #if defined(OS_POSIX)
377 SaveMessage(message); 391 SaveMessage(msg, rewritten_msg.get());
378 #else // defined(OS_POSIX) 392 #else
379 // On Windows we must rewrite the message to the POSIX representation. 393 // On Windows we must rewrite the message to match the POSIX form.
380 IPC::Message new_msg(message.routing_id(), 394 IPC::Message new_msg(msg.routing_id(),
381 PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID, 395 PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID,
382 message.priority()); 396 msg.priority());
383 WriteHostResource(&new_msg, instance_id, resource_id); 397 WriteHostResource(&new_msg, instance_id, resource_id);
384 new_msg.WriteInt(result_code); 398 new_msg.WriteInt(result_code);
385 WriteFileDescriptor(&new_msg, 0); // socket handle, index = 0 399 WriteFileDescriptor(&new_msg, 0); // socket handle, index = 0
386 WriteFileDescriptor(&new_msg, 1); // shm handle, index = 1 400 WriteFileDescriptor(&new_msg, 1); // shm handle, index = 1
387 new_msg.WriteUInt32(shm_length); 401 new_msg.WriteUInt32(shm_length);
388 SaveMessage(new_msg); 402 SaveMessage(new_msg, rewritten_msg.get());
389 #endif 403 #endif
390 } 404 }
391 break; 405 break;
392 } 406 }
393 default: { 407 default: {
394 SaveMessage(message); 408 SaveMessage(msg, rewritten_msg.get());
395 } 409 }
396 } 410 }
397 } 411 }
398 cond_var_.Signal(); 412 cond_var_.Signal();
399 return true; 413 return true;
400 } 414 }
401 415
402 void NaClIPCAdapter::OnChannelConnected(int32 peer_pid) { 416 void NaClIPCAdapter::OnChannelConnected(int32 peer_pid) {
403 } 417 }
404 418
405 void NaClIPCAdapter::OnChannelError() { 419 void NaClIPCAdapter::OnChannelError() {
406 CloseChannel(); 420 CloseChannel();
407 } 421 }
408 422
409 NaClIPCAdapter::~NaClIPCAdapter() { 423 NaClIPCAdapter::~NaClIPCAdapter() {
410 // Make sure the channel is deleted on the IO thread. 424 // Make sure the channel is deleted on the IO thread.
411 task_runner_->PostTask(FROM_HERE, 425 task_runner_->PostTask(FROM_HERE,
412 base::Bind(&DeleteChannel, io_thread_data_.channel_.release())); 426 base::Bind(&DeleteChannel, io_thread_data_.channel_.release()));
413 } 427 }
414 428
415 int NaClIPCAdapter::LockedReceive(char* output_buffer, 429 int NaClIPCAdapter::LockedReceive(NaClImcTypedMsgHdr* msg) {
416 size_t output_buffer_size) {
417 lock_.AssertAcquired(); 430 lock_.AssertAcquired();
418 431
419 if (locked_data_.to_be_received_.empty()) 432 if (locked_data_.to_be_received_.empty())
420 return 0; 433 return 0;
421 scoped_refptr<RewrittenMessage> current = 434 scoped_refptr<RewrittenMessage> current =
422 locked_data_.to_be_received_.front(); 435 locked_data_.to_be_received_.front();
423 436
424 int retval = current->Read(output_buffer, output_buffer_size); 437 int retval = current->TransferData(msg);
425 438
426 // When a message is entirely consumed, remove if from the waiting queue. 439 // When a message is entirely consumed, remove if from the waiting queue.
427 if (current->is_consumed()) 440 if (current->is_consumed())
428 locked_data_.to_be_received_.pop(); 441 locked_data_.to_be_received_.pop();
442
429 return retval; 443 return retval;
430 } 444 }
431 445
432 bool NaClIPCAdapter::SendCompleteMessage(const char* buffer, 446 bool NaClIPCAdapter::SendCompleteMessage(const char* buffer,
433 size_t buffer_len) { 447 size_t buffer_len) {
434 // The message will have already been validated, so we know it's large enough 448 // The message will have already been validated, so we know it's large enough
435 // for our header. 449 // for our header.
436 const NaClMessageHeader* header = 450 const NaClMessageHeader* header =
437 reinterpret_cast<const NaClMessageHeader*>(buffer); 451 reinterpret_cast<const NaClMessageHeader*>(buffer);
438 452
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 } 502 }
489 503
490 void NaClIPCAdapter::CloseChannelOnIOThread() { 504 void NaClIPCAdapter::CloseChannelOnIOThread() {
491 io_thread_data_.channel_->Close(); 505 io_thread_data_.channel_->Close();
492 } 506 }
493 507
494 void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) { 508 void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) {
495 io_thread_data_.channel_->Send(message.release()); 509 io_thread_data_.channel_->Send(message.release());
496 } 510 }
497 511
498 void NaClIPCAdapter::SaveMessage(const IPC::Message& message) { 512 void NaClIPCAdapter::SaveMessage(const IPC::Message& message,
513 RewrittenMessage* rewritten_message) {
514 lock_.AssertAcquired();
499 // There is some padding in this structure (the "padding" member is 16 515 // There is some padding in this structure (the "padding" member is 16
500 // bits but this then gets padded to 32 bits). We want to be sure not to 516 // bits but this then gets padded to 32 bits). We want to be sure not to
501 // leak data to the untrusted plugin, so zero everything out first. 517 // leak data to the untrusted plugin, so zero everything out first.
502 NaClMessageHeader header; 518 NaClMessageHeader header;
503 memset(&header, 0, sizeof(NaClMessageHeader)); 519 memset(&header, 0, sizeof(NaClMessageHeader));
504 520
505 header.payload_size = static_cast<uint32>(message.payload_size()); 521 header.payload_size = static_cast<uint32>(message.payload_size());
506 header.routing = message.routing_id(); 522 header.routing = message.routing_id();
507 header.type = message.type(); 523 header.type = message.type();
508 header.flags = message.flags(); 524 header.flags = message.flags();
509 header.num_fds = static_cast<int>(locked_data_.nacl_descs_.size()); 525 header.num_fds = rewritten_message->desc_count();
510 526
511 scoped_refptr<RewrittenMessage> dest(new RewrittenMessage); 527 rewritten_message->SetData(header, message.payload(), message.payload_size());
512 dest->SetData(header, message.payload(), message.payload_size());
513 locked_data_.to_be_received_.push(dest);
514 } 528 }
515 529
OLDNEW
« no previous file with comments | « chrome/nacl/nacl_ipc_adapter.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698