OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/nacl/loader/nacl_ipc_adapter.h" | 5 #include "components/nacl/loader/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" |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/location.h" | 12 #include "base/location.h" |
13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
14 #include "base/memory/shared_memory.h" | 14 #include "base/memory/shared_memory.h" |
15 #include "base/task_runner_util.h" | 15 #include "base/task_runner_util.h" |
| 16 #include "base/tuple.h" |
16 #include "build/build_config.h" | 17 #include "build/build_config.h" |
17 #include "ipc/ipc_channel.h" | 18 #include "ipc/ipc_channel.h" |
18 #include "ipc/ipc_platform_file.h" | 19 #include "ipc/ipc_platform_file.h" |
19 #include "native_client/src/public/nacl_desc.h" | 20 #include "native_client/src/public/nacl_desc.h" |
20 #include "native_client/src/trusted/desc/nacl_desc_base.h" | 21 #include "native_client/src/trusted/desc/nacl_desc_base.h" |
21 #include "native_client/src/trusted/desc/nacl_desc_custom.h" | 22 #include "native_client/src/trusted/desc/nacl_desc_custom.h" |
22 #include "native_client/src/trusted/desc/nacl_desc_imc_shm.h" | 23 #include "native_client/src/trusted/desc/nacl_desc_imc_shm.h" |
23 #include "native_client/src/trusted/desc/nacl_desc_io.h" | 24 #include "native_client/src/trusted/desc/nacl_desc_io.h" |
24 #include "native_client/src/trusted/desc/nacl_desc_quota.h" | 25 #include "native_client/src/trusted/desc/nacl_desc_quota.h" |
25 #include "native_client/src/trusted/desc/nacl_desc_quota_interface.h" | 26 #include "native_client/src/trusted/desc/nacl_desc_quota_interface.h" |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 } | 320 } |
320 | 321 |
321 NaClIPCAdapter::IOThreadData::IOThreadData() { | 322 NaClIPCAdapter::IOThreadData::IOThreadData() { |
322 } | 323 } |
323 | 324 |
324 NaClIPCAdapter::IOThreadData::~IOThreadData() { | 325 NaClIPCAdapter::IOThreadData::~IOThreadData() { |
325 } | 326 } |
326 | 327 |
327 NaClIPCAdapter::NaClIPCAdapter(const IPC::ChannelHandle& handle, | 328 NaClIPCAdapter::NaClIPCAdapter(const IPC::ChannelHandle& handle, |
328 base::TaskRunner* runner, | 329 base::TaskRunner* runner, |
329 ResolveFileTokenCallback resolve_file_token_cb) | 330 ResolveFileTokenCallback resolve_file_token_cb, |
| 331 OpenResourceCallback open_resource_cb) |
330 : lock_(), | 332 : lock_(), |
331 cond_var_(&lock_), | 333 cond_var_(&lock_), |
332 task_runner_(runner), | 334 task_runner_(runner), |
333 resolve_file_token_cb_(resolve_file_token_cb), | 335 resolve_file_token_cb_(resolve_file_token_cb), |
| 336 open_resource_cb_(open_resource_cb), |
334 locked_data_() { | 337 locked_data_() { |
335 io_thread_data_.channel_ = IPC::Channel::CreateServer(handle, this); | 338 io_thread_data_.channel_ = IPC::Channel::CreateServer(handle, this); |
336 // Note, we can not PostTask for ConnectChannelOnIOThread here. If we did, | 339 // Note, we can not PostTask for ConnectChannelOnIOThread here. If we did, |
337 // and that task ran before this constructor completes, the reference count | 340 // and that task ran before this constructor completes, the reference count |
338 // would go to 1 and then to 0 because of the Task, before we've been returned | 341 // would go to 1 and then to 0 because of the Task, before we've been returned |
339 // to the owning scoped_refptr, which is supposed to give us our first | 342 // to the owning scoped_refptr, which is supposed to give us our first |
340 // ref-count. | 343 // ref-count. |
341 } | 344 } |
342 | 345 |
343 NaClIPCAdapter::NaClIPCAdapter(scoped_ptr<IPC::Channel> channel, | 346 NaClIPCAdapter::NaClIPCAdapter(scoped_ptr<IPC::Channel> channel, |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 // descriptor received, we send the file token to the browser in | 500 // descriptor received, we send the file token to the browser in |
498 // exchange for a new file descriptor and file path information. | 501 // exchange for a new file descriptor and file path information. |
499 // That file descriptor can be used to construct a NaClDesc with | 502 // That file descriptor can be used to construct a NaClDesc with |
500 // identity-based validation caching. | 503 // identity-based validation caching. |
501 // | 504 // |
502 // We do not use file descriptors from the renderer with validation | 505 // We do not use file descriptors from the renderer with validation |
503 // caching; a compromised renderer should not be able to run | 506 // caching; a compromised renderer should not be able to run |
504 // arbitrary code in a plugin process. | 507 // arbitrary code in a plugin process. |
505 DCHECK(!resolve_file_token_cb_.is_null()); | 508 DCHECK(!resolve_file_token_cb_.is_null()); |
506 | 509 |
507 // resolve_file_token_cb_ must be invoked from the main thread. | 510 // resolve_file_token_cb_ must be invoked from the I/O thread. |
508 resolve_file_token_cb_.Run( | 511 resolve_file_token_cb_.Run( |
509 token_lo, | 512 token_lo, |
510 token_hi, | 513 token_hi, |
511 base::Bind(&NaClIPCAdapter::OnFileTokenResolved, | 514 base::Bind(&NaClIPCAdapter::SaveOpenResourceMessage, |
512 this, | 515 this, |
513 msg)); | 516 msg)); |
514 | 517 |
515 // In this case, we don't release the message to NaCl untrusted code | 518 // In this case, we don't release the message to NaCl untrusted code |
516 // immediately. We defer it until we get an async message back from the | 519 // immediately. We defer it until we get an async message back from the |
517 // browser process. | 520 // browser process. |
518 return true; | 521 return true; |
519 } | 522 } |
520 } | 523 } |
521 return RewriteMessage(msg, type); | 524 return RewriteMessage(msg, type); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 // The file descriptor is at index 0. There's only ever one file | 622 // The file descriptor is at index 0. There's only ever one file |
620 // descriptor provided for this message type, so this will be correct. | 623 // descriptor provided for this message type, so this will be correct. |
621 new_msg->WriteInt(0); | 624 new_msg->WriteInt(0); |
622 | 625 |
623 // Write empty file tokens. | 626 // Write empty file tokens. |
624 new_msg->WriteUInt64(0); // token_lo | 627 new_msg->WriteUInt64(0); // token_lo |
625 new_msg->WriteUInt64(0); // token_hi | 628 new_msg->WriteUInt64(0); // token_hi |
626 return new_msg.Pass(); | 629 return new_msg.Pass(); |
627 } | 630 } |
628 | 631 |
629 void NaClIPCAdapter::OnFileTokenResolved(const IPC::Message& orig_msg, | 632 void NaClIPCAdapter::SaveOpenResourceMessage( |
630 IPC::PlatformFileForTransit ipc_fd, | 633 const IPC::Message& orig_msg, |
631 base::FilePath file_path) { | 634 IPC::PlatformFileForTransit ipc_fd, |
| 635 base::FilePath file_path) { |
632 // The path where an invalid ipc_fd is returned isn't currently | 636 // The path where an invalid ipc_fd is returned isn't currently |
633 // covered by any tests. | 637 // covered by any tests. |
634 if (ipc_fd == IPC::InvalidPlatformFileForTransit()) { | 638 if (ipc_fd == IPC::InvalidPlatformFileForTransit()) { |
635 // The file token didn't resolve successfully, so we give the | 639 // The file token didn't resolve successfully, so we give the |
636 // original FD to the client without making a validated NaClDesc. | 640 // original FD to the client without making a validated NaClDesc. |
637 // However, we must rewrite the message to clear the file tokens. | 641 // However, we must rewrite the message to clear the file tokens. |
638 PickleIterator iter = IPC::SyncMessage::GetDataIterator(&orig_msg); | 642 PickleIterator iter = IPC::SyncMessage::GetDataIterator(&orig_msg); |
639 ppapi::proxy::SerializedHandle sh; | 643 ppapi::proxy::SerializedHandle sh; |
640 | 644 |
641 // We know that this can be read safely; see the original read in | 645 // We know that this can be read safely; see the original read in |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 | 786 |
783 void NaClIPCAdapter::CloseChannelOnIOThread() { | 787 void NaClIPCAdapter::CloseChannelOnIOThread() { |
784 io_thread_data_.channel_->Close(); | 788 io_thread_data_.channel_->Close(); |
785 } | 789 } |
786 | 790 |
787 void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) { | 791 void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) { |
788 int id = IPC::SyncMessage::GetMessageId(*message.get()); | 792 int id = IPC::SyncMessage::GetMessageId(*message.get()); |
789 DCHECK(io_thread_data_.pending_sync_msgs_.find(id) == | 793 DCHECK(io_thread_data_.pending_sync_msgs_.find(id) == |
790 io_thread_data_.pending_sync_msgs_.end()); | 794 io_thread_data_.pending_sync_msgs_.end()); |
791 | 795 |
| 796 // Handle PpapiHostMsg_OpenResource locally without sending an IPC to the |
| 797 // renderer when possible. |
| 798 PpapiHostMsg_OpenResource::Schema::SendParam send_params; |
| 799 if (!open_resource_cb_.is_null() && |
| 800 message->type() == PpapiHostMsg_OpenResource::ID && |
| 801 PpapiHostMsg_OpenResource::ReadSendParam(message.get(), &send_params)) { |
| 802 const std::string key = get<0>(send_params); |
| 803 // Both open_resource_cb_ and SaveOpenResourceMessage must be invoked |
| 804 // from the I/O thread. |
| 805 if (open_resource_cb_.Run( |
| 806 *message.get(), key, |
| 807 base::Bind(&NaClIPCAdapter::SaveOpenResourceMessage, this))) { |
| 808 // The callback sent a reply to the untrusted side. |
| 809 return; |
| 810 } |
| 811 } |
| 812 |
792 if (message->is_sync()) | 813 if (message->is_sync()) |
793 io_thread_data_.pending_sync_msgs_[id] = message->type(); | 814 io_thread_data_.pending_sync_msgs_[id] = message->type(); |
794 io_thread_data_.channel_->Send(message.release()); | 815 io_thread_data_.channel_->Send(message.release()); |
795 } | 816 } |
796 | 817 |
797 void NaClIPCAdapter::SaveMessage(const IPC::Message& msg, | 818 void NaClIPCAdapter::SaveMessage(const IPC::Message& msg, |
798 RewrittenMessage* rewritten_msg) { | 819 RewrittenMessage* rewritten_msg) { |
799 lock_.AssertAcquired(); | 820 lock_.AssertAcquired(); |
800 // There is some padding in this structure (the "padding" member is 16 | 821 // There is some padding in this structure (the "padding" member is 16 |
801 // bits but this then gets padded to 32 bits). We want to be sure not to | 822 // bits but this then gets padded to 32 bits). We want to be sure not to |
802 // leak data to the untrusted plugin, so zero everything out first. | 823 // leak data to the untrusted plugin, so zero everything out first. |
803 NaClMessageHeader header; | 824 NaClMessageHeader header; |
804 memset(&header, 0, sizeof(NaClMessageHeader)); | 825 memset(&header, 0, sizeof(NaClMessageHeader)); |
805 | 826 |
806 header.payload_size = static_cast<uint32>(msg.payload_size()); | 827 header.payload_size = static_cast<uint32>(msg.payload_size()); |
807 header.routing = msg.routing_id(); | 828 header.routing = msg.routing_id(); |
808 header.type = msg.type(); | 829 header.type = msg.type(); |
809 header.flags = msg.flags(); | 830 header.flags = msg.flags(); |
810 header.num_fds = static_cast<uint16>(rewritten_msg->desc_count()); | 831 header.num_fds = static_cast<uint16>(rewritten_msg->desc_count()); |
811 | 832 |
812 rewritten_msg->SetData(header, msg.payload(), msg.payload_size()); | 833 rewritten_msg->SetData(header, msg.payload(), msg.payload_size()); |
813 locked_data_.to_be_received_.push(rewritten_msg); | 834 locked_data_.to_be_received_.push(rewritten_msg); |
814 } | 835 } |
815 | 836 |
816 int TranslatePepperFileReadWriteOpenFlagsForTesting(int32_t pp_open_flags) { | 837 int TranslatePepperFileReadWriteOpenFlagsForTesting(int32_t pp_open_flags) { |
817 return TranslatePepperFileReadWriteOpenFlags(pp_open_flags); | 838 return TranslatePepperFileReadWriteOpenFlags(pp_open_flags); |
818 } | 839 } |
OLD | NEW |