OLD | NEW |
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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 "ipc/ipc_channel_posix.h" | 5 #include "ipc/ipc_channel_posix.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <stddef.h> | 9 #include <stddef.h> |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, | 247 Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, |
248 Listener* listener) | 248 Listener* listener) |
249 : mode_(mode), | 249 : mode_(mode), |
250 is_blocked_on_write_(false), | 250 is_blocked_on_write_(false), |
251 message_send_bytes_written_(0), | 251 message_send_bytes_written_(0), |
252 uses_fifo_(CommandLine::ForCurrentProcess()->HasSwitch( | 252 uses_fifo_(CommandLine::ForCurrentProcess()->HasSwitch( |
253 switches::kIPCUseFIFO)), | 253 switches::kIPCUseFIFO)), |
254 server_listen_pipe_(-1), | 254 server_listen_pipe_(-1), |
255 pipe_(-1), | 255 pipe_(-1), |
256 client_pipe_(-1), | 256 client_pipe_(-1), |
| 257 #if defined(OS_LINUX) |
| 258 fd_pipe_(-1), |
| 259 remote_fd_pipe_(-1), |
| 260 #endif |
257 listener_(listener), | 261 listener_(listener), |
258 waiting_connect_(true), | 262 waiting_connect_(true), |
259 processing_incoming_(false), | 263 processing_incoming_(false), |
260 factory_(this) { | 264 factory_(this) { |
261 if (!CreatePipe(channel_id, mode)) { | 265 if (!CreatePipe(channel_id, mode)) { |
262 // The pipe may have been closed already. | 266 // The pipe may have been closed already. |
263 LOG(WARNING) << "Unable to create pipe named \"" << channel_id << | 267 LOG(WARNING) << "Unable to create pipe named \"" << channel_id << |
264 "\" in " << (mode == MODE_SERVER ? "server" : "client") << | 268 "\" in " << (mode == MODE_SERVER ? "server" : "client") << |
265 " mode error(" << strerror(errno) << ")."; | 269 " mode error(" << strerror(errno) << ")."; |
266 } | 270 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 if (pipe_ < 0) { | 335 if (pipe_ < 0) { |
332 // Initial IPC channel. | 336 // Initial IPC channel. |
333 if (mode == MODE_SERVER) { | 337 if (mode == MODE_SERVER) { |
334 if (!SocketPair(&pipe_, &client_pipe_)) | 338 if (!SocketPair(&pipe_, &client_pipe_)) |
335 return false; | 339 return false; |
336 AddChannelSocket(pipe_name_, client_pipe_); | 340 AddChannelSocket(pipe_name_, client_pipe_); |
337 } else { | 341 } else { |
338 pipe_ = Singleton<base::GlobalDescriptors>()->Get(kPrimaryIPCChannel); | 342 pipe_ = Singleton<base::GlobalDescriptors>()->Get(kPrimaryIPCChannel); |
339 } | 343 } |
340 } else { | 344 } else { |
341 waiting_connect_ = false; | 345 waiting_connect_ = mode == MODE_SERVER; |
342 } | 346 } |
343 } | 347 } |
344 | 348 |
345 // Create the Hello message to be sent when Connect is called | 349 // Create the Hello message to be sent when Connect is called |
346 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, | 350 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, |
347 HELLO_MESSAGE_TYPE, | 351 HELLO_MESSAGE_TYPE, |
348 IPC::Message::PRIORITY_NORMAL)); | 352 IPC::Message::PRIORITY_NORMAL)); |
| 353 #if defined(OS_LINUX) |
| 354 if (!uses_fifo_) { |
| 355 // On Linux, the seccomp sandbox makes it very expensive to call |
| 356 // recvmsg() and sendmsg(). Often, we are perfectly OK with resorting to |
| 357 // read() and write(), which are cheap. |
| 358 // |
| 359 // As we cannot anticipate, when the sender will provide us with file |
| 360 // handles, we have to make the decision about whether we call read() or |
| 361 // recvmsg() before we actually make the call. The easiest option is to |
| 362 // create a dedicated socketpair() for exchanging file handles. |
| 363 if (mode == MODE_SERVER) { |
| 364 fd_pipe_ = -1; |
| 365 } else if (remote_fd_pipe_ == -1) { |
| 366 if (!SocketPair(&fd_pipe_, &remote_fd_pipe_)) { |
| 367 return false; |
| 368 } |
| 369 } |
| 370 } |
| 371 #endif |
349 if (!msg->WriteInt(base::GetCurrentProcId())) { | 372 if (!msg->WriteInt(base::GetCurrentProcId())) { |
350 Close(); | 373 Close(); |
351 return false; | 374 return false; |
352 } | 375 } |
353 | 376 |
354 output_queue_.push(msg.release()); | 377 output_queue_.push(msg.release()); |
355 return true; | 378 return true; |
356 } | 379 } |
357 | 380 |
358 bool Channel::ChannelImpl::Connect() { | 381 bool Channel::ChannelImpl::Connect() { |
(...skipping 10 matching lines...) Expand all Loading... |
369 } else { | 392 } else { |
370 if (pipe_ == -1) { | 393 if (pipe_ == -1) { |
371 return false; | 394 return false; |
372 } | 395 } |
373 MessageLoopForIO::current()->WatchFileDescriptor( | 396 MessageLoopForIO::current()->WatchFileDescriptor( |
374 pipe_, | 397 pipe_, |
375 true, | 398 true, |
376 MessageLoopForIO::WATCH_READ, | 399 MessageLoopForIO::WATCH_READ, |
377 &read_watcher_, | 400 &read_watcher_, |
378 this); | 401 this); |
379 waiting_connect_ = false; | 402 waiting_connect_ = mode_ == MODE_SERVER; |
380 } | 403 } |
381 | 404 |
382 if (!waiting_connect_) | 405 if (!waiting_connect_) |
383 return ProcessOutgoingMessages(); | 406 return ProcessOutgoingMessages(); |
384 return true; | 407 return true; |
385 } | 408 } |
386 | 409 |
387 bool Channel::ChannelImpl::ProcessIncomingMessages() { | 410 bool Channel::ChannelImpl::ProcessIncomingMessages() { |
388 ssize_t bytes_read = 0; | 411 ssize_t bytes_read = 0; |
389 | 412 |
390 struct msghdr msg = {0}; | 413 struct msghdr msg = {0}; |
391 struct iovec iov = {input_buf_, Channel::kReadBufferSize}; | 414 struct iovec iov = {input_buf_, Channel::kReadBufferSize}; |
392 | 415 |
393 msg.msg_iov = &iov; | |
394 msg.msg_iovlen = 1; | 416 msg.msg_iovlen = 1; |
395 msg.msg_control = input_cmsg_buf_; | 417 msg.msg_control = input_cmsg_buf_; |
396 | 418 |
397 for (;;) { | 419 for (;;) { |
398 msg.msg_controllen = sizeof(input_cmsg_buf_); | 420 msg.msg_iov = &iov; |
399 | 421 |
400 if (bytes_read == 0) { | 422 if (bytes_read == 0) { |
401 if (pipe_ == -1) | 423 if (pipe_ == -1) |
402 return false; | 424 return false; |
403 | 425 |
404 // Read from pipe. | 426 // Read from pipe. |
405 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data | 427 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data |
406 // is waiting on the pipe. | 428 // is waiting on the pipe. |
407 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT)); | 429 #if defined(OS_LINUX) |
408 | 430 if (fd_pipe_ >= 0) { |
| 431 bytes_read = HANDLE_EINTR(read(pipe_, input_buf_, |
| 432 Channel::kReadBufferSize)); |
| 433 msg.msg_controllen = 0; |
| 434 } else |
| 435 #endif |
| 436 { |
| 437 msg.msg_controllen = sizeof(input_cmsg_buf_); |
| 438 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT)); |
| 439 } |
409 if (bytes_read < 0) { | 440 if (bytes_read < 0) { |
410 if (errno == EAGAIN) { | 441 if (errno == EAGAIN) { |
411 return true; | 442 return true; |
412 #if defined(OS_MACOSX) | 443 #if defined(OS_MACOSX) |
413 } else if (errno == EPERM) { | 444 } else if (errno == EPERM) { |
414 // On OSX, reading from a pipe with no listener returns EPERM | 445 // On OSX, reading from a pipe with no listener returns EPERM |
415 // treat this as a special case to prevent spurious error messages | 446 // treat this as a special case to prevent spurious error messages |
416 // to the console. | 447 // to the console. |
417 return false; | 448 return false; |
418 #endif // defined(OS_MACOSX) | 449 #endif // defined(OS_MACOSX) |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 LOG(ERROR) << "IPC message is too big"; | 520 LOG(ERROR) << "IPC message is too big"; |
490 return false; | 521 return false; |
491 } | 522 } |
492 input_overflow_buf_.append(input_buf_, bytes_read); | 523 input_overflow_buf_.append(input_buf_, bytes_read); |
493 p = input_overflow_buf_.data(); | 524 p = input_overflow_buf_.data(); |
494 end = p + input_overflow_buf_.size(); | 525 end = p + input_overflow_buf_.size(); |
495 } | 526 } |
496 | 527 |
497 // A pointer to an array of |num_fds| file descriptors which includes any | 528 // A pointer to an array of |num_fds| file descriptors which includes any |
498 // fds that have spilled over from a previous read. | 529 // fds that have spilled over from a previous read. |
499 const int* fds; | 530 const int* fds = NULL; |
500 unsigned num_fds; | 531 unsigned num_fds = 0; |
501 unsigned fds_i = 0; // the index of the first unused descriptor | 532 unsigned fds_i = 0; // the index of the first unused descriptor |
502 | 533 |
503 if (input_overflow_fds_.empty()) { | 534 if (input_overflow_fds_.empty()) { |
504 fds = wire_fds; | 535 fds = wire_fds; |
505 num_fds = num_wire_fds; | 536 num_fds = num_wire_fds; |
506 } else { | 537 } else { |
507 const size_t prev_size = input_overflow_fds_.size(); | 538 if (num_wire_fds > 0) { |
508 input_overflow_fds_.resize(prev_size + num_wire_fds); | 539 const size_t prev_size = input_overflow_fds_.size(); |
509 memcpy(&input_overflow_fds_[prev_size], wire_fds, | 540 input_overflow_fds_.resize(prev_size + num_wire_fds); |
510 num_wire_fds * sizeof(int)); | 541 memcpy(&input_overflow_fds_[prev_size], wire_fds, |
| 542 num_wire_fds * sizeof(int)); |
| 543 } |
511 fds = &input_overflow_fds_[0]; | 544 fds = &input_overflow_fds_[0]; |
512 num_fds = input_overflow_fds_.size(); | 545 num_fds = input_overflow_fds_.size(); |
513 } | 546 } |
514 | 547 |
515 while (p < end) { | 548 while (p < end) { |
516 const char* message_tail = Message::FindNext(p, end); | 549 const char* message_tail = Message::FindNext(p, end); |
517 if (message_tail) { | 550 if (message_tail) { |
518 int len = static_cast<int>(message_tail - p); | 551 int len = static_cast<int>(message_tail - p); |
519 Message m(p, len); | 552 Message m(p, len); |
| 553 |
520 if (m.header()->num_fds) { | 554 if (m.header()->num_fds) { |
521 // the message has file descriptors | 555 // the message has file descriptors |
522 const char* error = NULL; | 556 const char* error = NULL; |
523 if (m.header()->num_fds > num_fds - fds_i) { | 557 if (m.header()->num_fds > num_fds - fds_i) { |
524 // the message has been completely received, but we didn't get | 558 // the message has been completely received, but we didn't get |
525 // enough file descriptors. | 559 // enough file descriptors. |
526 error = "Message needs unreceived descriptors"; | 560 #if defined(OS_LINUX) |
| 561 if (!uses_fifo_) { |
| 562 char dummy; |
| 563 struct iovec fd_pipe_iov = { &dummy, 1 }; |
| 564 msg.msg_iov = &fd_pipe_iov; |
| 565 msg.msg_controllen = sizeof(input_cmsg_buf_); |
| 566 ssize_t n = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT)); |
| 567 if (n == 1 && msg.msg_controllen > 0) { |
| 568 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; |
| 569 cmsg = CMSG_NXTHDR(&msg, cmsg)) { |
| 570 if (cmsg->cmsg_level == SOL_SOCKET && |
| 571 cmsg->cmsg_type == SCM_RIGHTS) { |
| 572 const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0); |
| 573 DCHECK(payload_len % sizeof(int) == 0); |
| 574 wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg)); |
| 575 num_wire_fds = payload_len / 4; |
| 576 |
| 577 if (msg.msg_flags & MSG_CTRUNC) { |
| 578 LOG(ERROR) << "SCM_RIGHTS message was truncated" |
| 579 << " cmsg_len:" << cmsg->cmsg_len |
| 580 << " fd:" << pipe_; |
| 581 for (unsigned i = 0; i < num_wire_fds; ++i) |
| 582 HANDLE_EINTR(close(wire_fds[i])); |
| 583 return false; |
| 584 } |
| 585 break; |
| 586 } |
| 587 } |
| 588 if (input_overflow_fds_.empty()) { |
| 589 fds = wire_fds; |
| 590 num_fds = num_wire_fds; |
| 591 } else { |
| 592 if (num_wire_fds > 0) { |
| 593 const size_t prev_size = input_overflow_fds_.size(); |
| 594 input_overflow_fds_.resize(prev_size + num_wire_fds); |
| 595 memcpy(&input_overflow_fds_[prev_size], wire_fds, |
| 596 num_wire_fds * sizeof(int)); |
| 597 } |
| 598 fds = &input_overflow_fds_[0]; |
| 599 num_fds = input_overflow_fds_.size(); |
| 600 } |
| 601 } |
| 602 } |
| 603 if (m.header()->num_fds > num_fds - fds_i) |
| 604 #endif |
| 605 error = "Message needs unreceived descriptors"; |
527 } | 606 } |
528 | 607 |
529 if (m.header()->num_fds > | 608 if (m.header()->num_fds > |
530 FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE) { | 609 FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE) { |
531 // There are too many descriptors in this message | 610 // There are too many descriptors in this message |
532 error = "Message requires an excessive number of descriptors"; | 611 error = "Message requires an excessive number of descriptors"; |
533 } | 612 } |
534 | 613 |
535 if (error) { | 614 if (error) { |
536 LOG(WARNING) << error | 615 LOG(WARNING) << error |
(...skipping 14 matching lines...) Expand all Loading... |
551 &fds[fds_i], m.header()->num_fds); | 630 &fds[fds_i], m.header()->num_fds); |
552 fds_i += m.header()->num_fds; | 631 fds_i += m.header()->num_fds; |
553 } | 632 } |
554 #ifdef IPC_MESSAGE_DEBUG_EXTRA | 633 #ifdef IPC_MESSAGE_DEBUG_EXTRA |
555 DLOG(INFO) << "received message on channel @" << this << | 634 DLOG(INFO) << "received message on channel @" << this << |
556 " with type " << m.type(); | 635 " with type " << m.type(); |
557 #endif | 636 #endif |
558 if (m.routing_id() == MSG_ROUTING_NONE && | 637 if (m.routing_id() == MSG_ROUTING_NONE && |
559 m.type() == HELLO_MESSAGE_TYPE) { | 638 m.type() == HELLO_MESSAGE_TYPE) { |
560 // The Hello message contains only the process id. | 639 // The Hello message contains only the process id. |
561 listener_->OnChannelConnected(MessageIterator(m).NextInt()); | 640 void *iter = NULL; |
| 641 int pid; |
| 642 if (!m.ReadInt(&iter, &pid)) { |
| 643 NOTREACHED(); |
| 644 } |
| 645 #if defined(OS_LINUX) |
| 646 if (mode_ == MODE_SERVER && !uses_fifo_) { |
| 647 // On Linux, the Hello message from the client to the server |
| 648 // also contains the fd_pipe_, which will be used for all |
| 649 // subsequent file descriptor passing. |
| 650 DCHECK_EQ(m.file_descriptor_set()->size(), 1); |
| 651 base::FileDescriptor descriptor; |
| 652 if (!m.ReadFileDescriptor(&iter, &descriptor)) { |
| 653 NOTREACHED(); |
| 654 } |
| 655 fd_pipe_ = descriptor.fd; |
| 656 CHECK(descriptor.auto_close); |
| 657 } |
| 658 #endif |
| 659 listener_->OnChannelConnected(pid); |
562 } else { | 660 } else { |
563 listener_->OnMessageReceived(m); | 661 listener_->OnMessageReceived(m); |
564 } | 662 } |
565 p = message_tail; | 663 p = message_tail; |
566 } else { | 664 } else { |
567 // Last message is partial. | 665 // Last message is partial. |
568 break; | 666 break; |
569 } | 667 } |
| 668 input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]); |
| 669 fds_i = 0; |
| 670 fds = &input_overflow_fds_[0]; |
| 671 num_fds = input_overflow_fds_.size(); |
570 } | 672 } |
571 input_overflow_buf_.assign(p, end - p); | 673 input_overflow_buf_.assign(p, end - p); |
572 input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]); | 674 input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]); |
573 | 675 |
574 // When the input data buffer is empty, the overflow fds should be too. If | 676 // When the input data buffer is empty, the overflow fds should be too. If |
575 // this is not the case, we probably have a rogue renderer which is trying | 677 // this is not the case, we probably have a rogue renderer which is trying |
576 // to fill our descriptor table. | 678 // to fill our descriptor table. |
577 if (input_overflow_buf_.empty() && !input_overflow_fds_.empty()) { | 679 if (input_overflow_buf_.empty() && !input_overflow_fds_.empty()) { |
578 // We close these descriptors in Close() | 680 // We close these descriptors in Close() |
579 return false; | 681 return false; |
580 } | 682 } |
581 | 683 |
582 bytes_read = 0; // Get more data. | 684 bytes_read = 0; // Get more data. |
583 } | 685 } |
584 | 686 |
585 return true; | 687 return true; |
586 } | 688 } |
587 | 689 |
588 bool Channel::ChannelImpl::ProcessOutgoingMessages() { | 690 bool Channel::ChannelImpl::ProcessOutgoingMessages() { |
589 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's | 691 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's |
590 // no connection? | 692 // no connection? |
591 is_blocked_on_write_ = false; | 693 is_blocked_on_write_ = false; |
592 | 694 |
593 if (output_queue_.empty()) | 695 if (output_queue_.empty()) { |
594 return true; | 696 return true; |
| 697 } |
595 | 698 |
596 if (pipe_ == -1) | 699 if (pipe_ == -1) { |
597 return false; | 700 return false; |
| 701 } |
598 | 702 |
599 // Write out all the messages we can till the write blocks or there are no | 703 // Write out all the messages we can till the write blocks or there are no |
600 // more outgoing messages. | 704 // more outgoing messages. |
601 while (!output_queue_.empty()) { | 705 while (!output_queue_.empty()) { |
602 Message* msg = output_queue_.front(); | 706 Message* msg = output_queue_.front(); |
603 | 707 |
| 708 #if defined(OS_LINUX) |
| 709 scoped_ptr<Message> hello; |
| 710 if (remote_fd_pipe_ != -1 && |
| 711 msg->routing_id() == MSG_ROUTING_NONE && |
| 712 msg->type() == HELLO_MESSAGE_TYPE) { |
| 713 hello.reset(new Message(MSG_ROUTING_NONE, |
| 714 HELLO_MESSAGE_TYPE, |
| 715 IPC::Message::PRIORITY_NORMAL)); |
| 716 void* iter = NULL; |
| 717 int pid; |
| 718 if (!msg->ReadInt(&iter, &pid) || |
| 719 !hello->WriteInt(pid)) { |
| 720 NOTREACHED(); |
| 721 } |
| 722 DCHECK_EQ(hello->size(), msg->size()); |
| 723 if (!hello->WriteFileDescriptor(base::FileDescriptor(remote_fd_pipe_, |
| 724 false))) { |
| 725 NOTREACHED(); |
| 726 } |
| 727 msg = hello.get(); |
| 728 DCHECK_EQ(msg->file_descriptor_set()->size(), 1); |
| 729 } |
| 730 #endif |
| 731 |
604 size_t amt_to_write = msg->size() - message_send_bytes_written_; | 732 size_t amt_to_write = msg->size() - message_send_bytes_written_; |
605 DCHECK(amt_to_write != 0); | 733 DCHECK(amt_to_write != 0); |
606 const char *out_bytes = reinterpret_cast<const char*>(msg->data()) + | 734 const char* out_bytes = reinterpret_cast<const char*>(msg->data()) + |
607 message_send_bytes_written_; | 735 message_send_bytes_written_; |
608 | 736 |
609 struct msghdr msgh = {0}; | 737 struct msghdr msgh = {0}; |
610 struct iovec iov = {const_cast<char*>(out_bytes), amt_to_write}; | 738 struct iovec iov = {const_cast<char*>(out_bytes), amt_to_write}; |
611 msgh.msg_iov = &iov; | 739 msgh.msg_iov = &iov; |
612 msgh.msg_iovlen = 1; | 740 msgh.msg_iovlen = 1; |
613 char buf[CMSG_SPACE( | 741 char buf[CMSG_SPACE( |
614 sizeof(int[FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE]))]; | 742 sizeof(int[FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE]))]; |
615 | 743 |
| 744 ssize_t bytes_written = 1; |
| 745 int fd_written = -1; |
| 746 |
616 if (message_send_bytes_written_ == 0 && | 747 if (message_send_bytes_written_ == 0 && |
617 !msg->file_descriptor_set()->empty()) { | 748 !msg->file_descriptor_set()->empty()) { |
618 // This is the first chunk of a message which has descriptors to send | 749 // This is the first chunk of a message which has descriptors to send |
619 struct cmsghdr *cmsg; | 750 struct cmsghdr *cmsg; |
620 const unsigned num_fds = msg->file_descriptor_set()->size(); | 751 const unsigned num_fds = msg->file_descriptor_set()->size(); |
621 | 752 |
622 DCHECK_LE(num_fds, FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE); | 753 DCHECK_LE(num_fds, FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE); |
623 | 754 |
624 msgh.msg_control = buf; | 755 msgh.msg_control = buf; |
625 msgh.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds); | 756 msgh.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds); |
626 cmsg = CMSG_FIRSTHDR(&msgh); | 757 cmsg = CMSG_FIRSTHDR(&msgh); |
627 cmsg->cmsg_level = SOL_SOCKET; | 758 cmsg->cmsg_level = SOL_SOCKET; |
628 cmsg->cmsg_type = SCM_RIGHTS; | 759 cmsg->cmsg_type = SCM_RIGHTS; |
629 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); | 760 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); |
630 msg->file_descriptor_set()->GetDescriptors( | 761 msg->file_descriptor_set()->GetDescriptors( |
631 reinterpret_cast<int*>(CMSG_DATA(cmsg))); | 762 reinterpret_cast<int*>(CMSG_DATA(cmsg))); |
632 msgh.msg_controllen = cmsg->cmsg_len; | 763 msgh.msg_controllen = cmsg->cmsg_len; |
633 | 764 |
634 msg->header()->num_fds = num_fds; | 765 msg->header()->num_fds = num_fds; |
| 766 |
| 767 #if defined(OS_LINUX) |
| 768 if (!uses_fifo_ && |
| 769 (msg->routing_id() != MSG_ROUTING_NONE || |
| 770 msg->type() != HELLO_MESSAGE_TYPE)) { |
| 771 // Only the Hello message sends the file descriptor with the message. |
| 772 // Subsequently, we can send file descriptors on the dedicated |
| 773 // fd_pipe_ which makes Seccomp sandbox operation more efficient. |
| 774 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; |
| 775 msgh.msg_iov = &fd_pipe_iov; |
| 776 fd_written = fd_pipe_; |
| 777 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); |
| 778 msgh.msg_iov = &iov; |
| 779 msgh.msg_controllen = 0; |
| 780 if (bytes_written > 0) { |
| 781 msg->file_descriptor_set()->CommitAll(); |
| 782 } |
| 783 } |
| 784 #endif |
635 } | 785 } |
636 | 786 |
637 ssize_t bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT)); | 787 if (bytes_written == 1) { |
| 788 fd_written = pipe_; |
| 789 #if defined(OS_LINUX) |
| 790 if (mode_ != MODE_SERVER && !uses_fifo_ && |
| 791 msg->routing_id() == MSG_ROUTING_NONE && |
| 792 msg->type() == HELLO_MESSAGE_TYPE) { |
| 793 DCHECK_EQ(msg->file_descriptor_set()->size(), 1); |
| 794 } |
| 795 if (!uses_fifo_ && !msgh.msg_controllen) { |
| 796 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); |
| 797 } else |
| 798 #endif |
| 799 { |
| 800 bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT)); |
| 801 } |
| 802 } |
638 if (bytes_written > 0) | 803 if (bytes_written > 0) |
639 msg->file_descriptor_set()->CommitAll(); | 804 msg->file_descriptor_set()->CommitAll(); |
640 | 805 |
641 if (bytes_written < 0 && errno != EAGAIN) { | 806 if (bytes_written < 0 && errno != EAGAIN) { |
642 #if defined(OS_MACOSX) | 807 #if defined(OS_MACOSX) |
643 // On OSX writing to a pipe with no listener returns EPERM. | 808 // On OSX writing to a pipe with no listener returns EPERM. |
644 if (errno == EPERM) { | 809 if (errno == EPERM) { |
645 Close(); | 810 Close(); |
646 return false; | 811 return false; |
647 } | 812 } |
648 #endif // OS_MACOSX | 813 #endif // OS_MACOSX |
649 LOG(ERROR) << "pipe error on " << pipe_ << ": " << strerror(errno); | 814 LOG(ERROR) << "pipe error on " << fd_written << ": " << strerror(errno); |
650 return false; | 815 return false; |
651 } | 816 } |
652 | 817 |
653 if (static_cast<size_t>(bytes_written) != amt_to_write) { | 818 if (static_cast<size_t>(bytes_written) != amt_to_write) { |
654 if (bytes_written > 0) { | 819 if (bytes_written > 0) { |
655 // If write() fails with EAGAIN then bytes_written will be -1. | 820 // If write() fails with EAGAIN then bytes_written will be -1. |
656 message_send_bytes_written_ += bytes_written; | 821 message_send_bytes_written_ += bytes_written; |
657 } | 822 } |
658 | 823 |
659 // Tell libevent to call us back once things are unblocked. | 824 // Tell libevent to call us back once things are unblocked. |
660 is_blocked_on_write_ = true; | 825 is_blocked_on_write_ = true; |
661 MessageLoopForIO::current()->WatchFileDescriptor( | 826 MessageLoopForIO::current()->WatchFileDescriptor( |
662 pipe_, | 827 pipe_, |
663 false, // One shot | 828 false, // One shot |
664 MessageLoopForIO::WATCH_WRITE, | 829 MessageLoopForIO::WATCH_WRITE, |
665 &write_watcher_, | 830 &write_watcher_, |
666 this); | 831 this); |
667 return true; | 832 return true; |
668 } else { | 833 } else { |
669 message_send_bytes_written_ = 0; | 834 message_send_bytes_written_ = 0; |
670 | 835 |
671 // Message sent OK! | 836 // Message sent OK! |
672 #ifdef IPC_MESSAGE_DEBUG_EXTRA | 837 #ifdef IPC_MESSAGE_DEBUG_EXTRA |
673 DLOG(INFO) << "sent message @" << msg << " on channel @" << this << | 838 DLOG(INFO) << "sent message @" << msg << " on channel @" << this << |
674 " with type " << msg->type(); | 839 " with type " << msg->type(); |
675 #endif | 840 #endif |
| 841 delete output_queue_.front(); |
676 output_queue_.pop(); | 842 output_queue_.pop(); |
677 delete msg; | |
678 } | 843 } |
679 } | 844 } |
680 return true; | 845 return true; |
681 } | 846 } |
682 | 847 |
683 bool Channel::ChannelImpl::Send(Message* message) { | 848 bool Channel::ChannelImpl::Send(Message* message) { |
684 #ifdef IPC_MESSAGE_DEBUG_EXTRA | 849 #ifdef IPC_MESSAGE_DEBUG_EXTRA |
685 DLOG(INFO) << "sending message @" << message << " on channel @" << this | 850 DLOG(INFO) << "sending message @" << message << " on channel @" << this |
686 << " with type " << message->type() | 851 << " with type " << message->type() |
687 << " (" << output_queue_.size() << " in queue)"; | 852 << " (" << output_queue_.size() << " in queue)"; |
(...skipping 15 matching lines...) Expand all Loading... |
703 } | 868 } |
704 | 869 |
705 int Channel::ChannelImpl::GetClientFileDescriptor() const { | 870 int Channel::ChannelImpl::GetClientFileDescriptor() const { |
706 return client_pipe_; | 871 return client_pipe_; |
707 } | 872 } |
708 | 873 |
709 // Called by libevent when we can read from th pipe without blocking. | 874 // Called by libevent when we can read from th pipe without blocking. |
710 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { | 875 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { |
711 bool send_server_hello_msg = false; | 876 bool send_server_hello_msg = false; |
712 if (waiting_connect_ && mode_ == MODE_SERVER) { | 877 if (waiting_connect_ && mode_ == MODE_SERVER) { |
713 // In the case of a socketpair() the server starts listening on its end | 878 if (uses_fifo_) { |
714 // of the pipe in Connect(). | 879 if (!ServerAcceptFifoConnection(server_listen_pipe_, &pipe_)) { |
715 DCHECK(uses_fifo_); | 880 Close(); |
| 881 } |
716 | 882 |
717 if (!ServerAcceptFifoConnection(server_listen_pipe_, &pipe_)) { | 883 // No need to watch the listening socket any longer since only one client |
718 Close(); | 884 // can connect. So unregister with libevent. |
| 885 server_listen_connection_watcher_.StopWatchingFileDescriptor(); |
| 886 |
| 887 // Start watching our end of the socket. |
| 888 MessageLoopForIO::current()->WatchFileDescriptor( |
| 889 pipe_, |
| 890 true, |
| 891 MessageLoopForIO::WATCH_READ, |
| 892 &read_watcher_, |
| 893 this); |
| 894 |
| 895 waiting_connect_ = false; |
| 896 } else { |
| 897 // In the case of a socketpair() the server starts listening on its end |
| 898 // of the pipe in Connect(). |
| 899 waiting_connect_ = false; |
719 } | 900 } |
720 | |
721 // No need to watch the listening socket any longer since only one client | |
722 // can connect. So unregister with libevent. | |
723 server_listen_connection_watcher_.StopWatchingFileDescriptor(); | |
724 | |
725 // Start watching our end of the socket. | |
726 MessageLoopForIO::current()->WatchFileDescriptor( | |
727 pipe_, | |
728 true, | |
729 MessageLoopForIO::WATCH_READ, | |
730 &read_watcher_, | |
731 this); | |
732 | |
733 waiting_connect_ = false; | |
734 send_server_hello_msg = true; | 901 send_server_hello_msg = true; |
735 } | 902 } |
736 | 903 |
737 if (!waiting_connect_ && fd == pipe_) { | 904 if (!waiting_connect_ && fd == pipe_) { |
738 if (!ProcessIncomingMessages()) { | 905 if (!ProcessIncomingMessages()) { |
739 Close(); | 906 Close(); |
740 listener_->OnChannelError(); | 907 listener_->OnChannelError(); |
741 } | 908 } |
742 } | 909 } |
743 | 910 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 read_watcher_.StopWatchingFileDescriptor(); | 943 read_watcher_.StopWatchingFileDescriptor(); |
777 write_watcher_.StopWatchingFileDescriptor(); | 944 write_watcher_.StopWatchingFileDescriptor(); |
778 if (pipe_ != -1) { | 945 if (pipe_ != -1) { |
779 HANDLE_EINTR(close(pipe_)); | 946 HANDLE_EINTR(close(pipe_)); |
780 pipe_ = -1; | 947 pipe_ = -1; |
781 } | 948 } |
782 if (client_pipe_ != -1) { | 949 if (client_pipe_ != -1) { |
783 Singleton<PipeMap>()->RemoveAndClose(pipe_name_); | 950 Singleton<PipeMap>()->RemoveAndClose(pipe_name_); |
784 client_pipe_ = -1; | 951 client_pipe_ = -1; |
785 } | 952 } |
| 953 #if defined(OS_LINUX) |
| 954 if (fd_pipe_ != -1) { |
| 955 HANDLE_EINTR(close(fd_pipe_)); |
| 956 fd_pipe_ = -1; |
| 957 } |
| 958 if (remote_fd_pipe_ != -1) { |
| 959 HANDLE_EINTR(close(remote_fd_pipe_)); |
| 960 remote_fd_pipe_ = -1; |
| 961 } |
| 962 #endif |
786 | 963 |
787 if (uses_fifo_) { | 964 if (uses_fifo_) { |
788 // Unlink the FIFO | 965 // Unlink the FIFO |
789 unlink(pipe_name_.c_str()); | 966 unlink(pipe_name_.c_str()); |
790 } | 967 } |
791 | 968 |
792 while (!output_queue_.empty()) { | 969 while (!output_queue_.empty()) { |
793 Message* m = output_queue_.front(); | 970 Message* m = output_queue_.front(); |
794 output_queue_.pop(); | 971 output_queue_.pop(); |
795 delete m; | 972 delete m; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 | 1005 |
829 bool Channel::Send(Message* message) { | 1006 bool Channel::Send(Message* message) { |
830 return channel_impl_->Send(message); | 1007 return channel_impl_->Send(message); |
831 } | 1008 } |
832 | 1009 |
833 int Channel::GetClientFileDescriptor() const { | 1010 int Channel::GetClientFileDescriptor() const { |
834 return channel_impl_->GetClientFileDescriptor(); | 1011 return channel_impl_->GetClientFileDescriptor(); |
835 } | 1012 } |
836 | 1013 |
837 } // namespace IPC | 1014 } // namespace IPC |
OLD | NEW |