| Index: chrome/nacl/nacl_ipc_adapter.cc
|
| ===================================================================
|
| --- chrome/nacl/nacl_ipc_adapter.cc (revision 148428)
|
| +++ chrome/nacl/nacl_ipc_adapter.cc (working copy)
|
| @@ -141,8 +141,12 @@
|
| void SetData(const NaClIPCAdapter::NaClMessageHeader& header,
|
| const void* payload, size_t payload_length);
|
|
|
| - int Read(char* dest_buffer, size_t dest_buffer_size);
|
| + int Read(NaClImcTypedMsgHdr* msg);
|
|
|
| + void AddDescriptor(nacl::DescWrapper* desc) { descs_.push_back(desc); }
|
| +
|
| + size_t desc_count() const { return descs_.size(); }
|
| +
|
| private:
|
| friend class base::RefCounted<RewrittenMessage>;
|
| ~RewrittenMessage() {}
|
| @@ -153,6 +157,9 @@
|
| // Offset into data where the next read will happen. This will be equal to
|
| // data_len_ when all data has been consumed.
|
| size_t data_read_cursor_;
|
| +
|
| + // Wrapped descriptors for transfer to untrusted code.
|
| + ScopedVector<nacl::DescWrapper> descs_;
|
| };
|
|
|
| NaClIPCAdapter::RewrittenMessage::RewrittenMessage()
|
| @@ -173,9 +180,10 @@
|
| memcpy(&data_[header_len], payload, payload_length);
|
| }
|
|
|
| -int NaClIPCAdapter::RewrittenMessage::Read(char* dest_buffer,
|
| - size_t dest_buffer_size) {
|
| +int NaClIPCAdapter::RewrittenMessage::Read(NaClImcTypedMsgHdr* msg) {
|
| CHECK(data_len_ >= data_read_cursor_);
|
| + char* dest_buffer = static_cast<char*>(msg->iov[0].base);
|
| + size_t dest_buffer_size = msg->iov[0].length;
|
| size_t bytes_to_write = std::min(dest_buffer_size,
|
| data_len_ - data_read_cursor_);
|
| if (bytes_to_write == 0)
|
| @@ -183,6 +191,20 @@
|
|
|
| memcpy(dest_buffer, &data_[data_read_cursor_], bytes_to_write);
|
| data_read_cursor_ += bytes_to_write;
|
| +
|
| + // Once all data has been consumed, transfer any file descriptors.
|
| + if (is_consumed()) {
|
| + nacl_abi_size_t desc_count = static_cast<nacl_abi_size_t>(descs_.size());
|
| + CHECK(desc_count <= msg->ndesc_length);
|
| + msg->ndesc_length = desc_count;
|
| + for (nacl_abi_size_t i = 0; i < desc_count; i++) {
|
| + // Copy the NaClDesc to the buffer and add a ref so it won't be freed
|
| + // when we clear our ScopedVector.
|
| + msg->ndescv[i] = descs_[i]->desc();
|
| + NaClDescRef(descs_[i]->desc());
|
| + }
|
| + descs_.clear();
|
| + }
|
| return static_cast<int>(bytes_to_write);
|
| }
|
|
|
| @@ -294,8 +316,6 @@
|
| if (msg->iov_length != 1)
|
| return -1;
|
|
|
| - char* output_buffer = static_cast<char*>(msg->iov[0].base);
|
| - size_t output_buffer_size = msg->iov[0].length;
|
| int retval = 0;
|
| {
|
| base::AutoLock lock(lock_);
|
| @@ -305,14 +325,9 @@
|
| if (locked_data_.channel_closed_) {
|
| retval = -1;
|
| } else {
|
| - retval = LockedReceive(output_buffer, output_buffer_size);
|
| + retval = LockedReceive(msg);
|
| DCHECK(retval > 0);
|
| }
|
| - int desc_count = static_cast<int>(locked_data_.nacl_descs_.size());
|
| - CHECK(desc_count <= NACL_ABI_IMC_DESC_MAX);
|
| - msg->ndesc_length = desc_count;
|
| - for (int i = 0; i < desc_count; i++)
|
| - msg->ndescv[i] = locked_data_.nacl_descs_[i]->desc();
|
| }
|
| cond_var_.Signal();
|
| return retval;
|
| @@ -339,15 +354,14 @@
|
| }
|
| #endif
|
|
|
| -bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& message) {
|
| +bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) {
|
| {
|
| base::AutoLock lock(lock_);
|
|
|
| - // Clear any descriptors left from the prior message.
|
| - locked_data_.nacl_descs_.clear();
|
| + scoped_refptr<RewrittenMessage> rewritten_msg(new RewrittenMessage);
|
|
|
| - PickleIterator it(message);
|
| - switch (message.type()) {
|
| + PickleIterator it(msg);
|
| + switch (msg.type()) {
|
| case PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID: {
|
| int instance_id;
|
| int resource_id;
|
| @@ -357,41 +371,40 @@
|
| uint32_t shm_length;
|
| if (ReadHostResource(&it, &instance_id, &resource_id) &&
|
| it.ReadInt(&result_code) &&
|
| - ReadFileDescriptor(message, &it, &sock_handle) &&
|
| - ReadFileDescriptor(message, &it, &shm_handle) &&
|
| + ReadFileDescriptor(msg, &it, &sock_handle) &&
|
| + ReadFileDescriptor(msg, &it, &shm_handle) &&
|
| it.ReadUInt32(&shm_length)) {
|
| - // Our caller, OnMessageReceived, holds the lock for locked_data_.
|
| - // Import the sync socket. Use DescWrappers to simplify clean up.
|
| + // Import the sync socket.
|
| nacl::DescWrapperFactory factory;
|
| scoped_ptr<nacl::DescWrapper> socket_wrapper(
|
| factory.ImportSyncSocketHandle(sock_handle));
|
| // Import the shared memory handle and increase its size by 4 bytes to
|
| - // accommodate the length data we write to signal the host.
|
| + // accommodate the length data we write at the end to signal the host.
|
| scoped_ptr<nacl::DescWrapper> shm_wrapper(
|
| factory.ImportShmHandle(shm_handle, shm_length + sizeof(uint32)));
|
| if (shm_wrapper.get() && socket_wrapper.get()) {
|
| - locked_data_.nacl_descs_.push_back(socket_wrapper.release());
|
| - locked_data_.nacl_descs_.push_back(shm_wrapper.release());
|
| + rewritten_msg->AddDescriptor(socket_wrapper.release());
|
| + rewritten_msg->AddDescriptor(shm_wrapper.release());
|
| }
|
| #if defined(OS_POSIX)
|
| - SaveMessage(message);
|
| -#else // defined(OS_POSIX)
|
| - // On Windows we must rewrite the message to the POSIX representation.
|
| - IPC::Message new_msg(message.routing_id(),
|
| + SaveMessage(msg, rewritten_msg.get());
|
| +#else
|
| + // On Windows we must rewrite the message to match the POSIX form.
|
| + IPC::Message new_msg(msg.routing_id(),
|
| PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID,
|
| - message.priority());
|
| + msg.priority());
|
| WriteHostResource(&new_msg, instance_id, resource_id);
|
| new_msg.WriteInt(result_code);
|
| WriteFileDescriptor(&new_msg, 0); // socket handle, index = 0
|
| WriteFileDescriptor(&new_msg, 1); // shm handle, index = 1
|
| new_msg.WriteUInt32(shm_length);
|
| - SaveMessage(new_msg);
|
| + SaveMessage(new_msg, rewritten_msg.get());
|
| #endif
|
| }
|
| break;
|
| }
|
| default: {
|
| - SaveMessage(message);
|
| + SaveMessage(msg, rewritten_msg.get());
|
| }
|
| }
|
| }
|
| @@ -412,8 +425,7 @@
|
| base::Bind(&DeleteChannel, io_thread_data_.channel_.release()));
|
| }
|
|
|
| -int NaClIPCAdapter::LockedReceive(char* output_buffer,
|
| - size_t output_buffer_size) {
|
| +int NaClIPCAdapter::LockedReceive(NaClImcTypedMsgHdr* msg) {
|
| lock_.AssertAcquired();
|
|
|
| if (locked_data_.to_be_received_.empty())
|
| @@ -421,11 +433,12 @@
|
| scoped_refptr<RewrittenMessage> current =
|
| locked_data_.to_be_received_.front();
|
|
|
| - int retval = current->Read(output_buffer, output_buffer_size);
|
| + int retval = current->Read(msg);
|
|
|
| // When a message is entirely consumed, remove if from the waiting queue.
|
| if (current->is_consumed())
|
| locked_data_.to_be_received_.pop();
|
| +
|
| return retval;
|
| }
|
|
|
| @@ -495,21 +508,22 @@
|
| io_thread_data_.channel_->Send(message.release());
|
| }
|
|
|
| -void NaClIPCAdapter::SaveMessage(const IPC::Message& message) {
|
| +void NaClIPCAdapter::SaveMessage(const IPC::Message& msg,
|
| + RewrittenMessage* rewritten_msg) {
|
| + lock_.AssertAcquired();
|
| // There is some padding in this structure (the "padding" member is 16
|
| // bits but this then gets padded to 32 bits). We want to be sure not to
|
| // leak data to the untrusted plugin, so zero everything out first.
|
| NaClMessageHeader header;
|
| memset(&header, 0, sizeof(NaClMessageHeader));
|
|
|
| - header.payload_size = static_cast<uint32>(message.payload_size());
|
| - header.routing = message.routing_id();
|
| - header.type = message.type();
|
| - header.flags = message.flags();
|
| - header.num_fds = static_cast<int>(locked_data_.nacl_descs_.size());
|
| + header.payload_size = static_cast<uint32>(msg.payload_size());
|
| + header.routing = msg.routing_id();
|
| + header.type = msg.type();
|
| + header.flags = msg.flags();
|
| + header.num_fds = static_cast<int>(rewritten_msg->desc_count());
|
|
|
| - scoped_refptr<RewrittenMessage> dest(new RewrittenMessage);
|
| - dest->SetData(header, message.payload(), message.payload_size());
|
| - locked_data_.to_be_received_.push(dest);
|
| + rewritten_msg->SetData(header, msg.payload(), msg.payload_size());
|
| + locked_data_.to_be_received_.push(rewritten_msg);
|
| }
|
|
|
|
|