OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |