| 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 |