Bug 988251 - Enable sending more than 4 file descriptors in the IPC channel (r=bent)

This commit is contained in:
Bill McCloskey 2014-07-16 23:03:03 -07:00
parent 81c8d70bcc
commit 8c69e33908
4 changed files with 25 additions and 20 deletions

View File

@ -21,16 +21,10 @@ class FileDescriptorSet : public base::RefCountedThreadSafe<FileDescriptorSet> {
FileDescriptorSet();
~FileDescriptorSet();
// This is the maximum number of descriptors per message. We need to know this
// because the control message kernel interface has to be given a buffer which
// is large enough to store all the descriptor numbers. Otherwise the kernel
// tells us that it truncated the control data and the extra descriptors are
// lost.
//
// In debugging mode, it's a fatal error to try and add more than this number
// of descriptors to a FileDescriptorSet.
// Mac and Linux both limit the number of file descriptors per message to
// slightly more than 250.
enum {
MAX_DESCRIPTORS_PER_MESSAGE = 7
MAX_DESCRIPTORS_PER_MESSAGE = 250
};
// ---------------------------------------------------------------------------

View File

@ -283,6 +283,8 @@ Channel::ChannelImpl::ChannelImpl(int fd, Mode mode, Listener* listener)
}
void Channel::ChannelImpl::Init(Mode mode, Listener* listener) {
DCHECK(kControlBufferSlopBytes >= CMSG_SPACE(0));
mode_ = mode;
is_blocked_on_write_ = false;
message_send_bytes_written_ = 0;

View File

@ -103,20 +103,27 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
// We read from the pipe into this buffer
char input_buf_[Channel::kReadBufferSize];
// We want input_cmsg_buf_ to be big enough to hold
// CMSG_SPACE(Channel::kReadBufferSize) bytes (see the comment below for an
// explanation of where Channel::kReadBufferSize comes from). However,
// CMSG_SPACE is apparently not a constant on Macs, so we can't use it in the
// array size. Consequently, we pick a number here that is at least
// CMSG_SPACE(0) on all platforms. And we assert at runtime, in
// Channel::ChannelImpl::Init, that it's big enough.
enum {
// We assume a worst case: kReadBufferSize bytes of messages, where each
// message has no payload and a full complement of descriptors.
MAX_READ_FDS = (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) *
FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE
kControlBufferSlopBytes = 32
};
// This is a control message buffer large enough to hold kMaxReadFDs
#if defined(OS_MACOSX) || defined(OS_NETBSD)
// TODO(agl): OSX appears to have non-constant CMSG macros!
char input_cmsg_buf_[1024];
#else
char input_cmsg_buf_[CMSG_SPACE(sizeof(int) * MAX_READ_FDS)];
#endif
// This is a control message buffer large enough to hold all the file
// descriptors that will be read in when reading Channel::kReadBufferSize
// bytes of data. Message::WriteFileDescriptor always writes one word of
// data for every file descriptor added to the message, so kReadBufferSize
// bytes of data can never be accompanied by more than
// kReadBufferSize / sizeof(int) file descriptors. Since a file descriptor
// takes sizeof(int) bytes, the control buffer must be
// Channel::kReadBufferSize bytes. We add kControlBufferSlopBytes bytes
// for the control header.
char input_cmsg_buf_[Channel::kReadBufferSize + kControlBufferSlopBytes];
// Large messages that span multiple pipe buffers, get built-up using
// this buffer.

View File

@ -128,6 +128,8 @@ void Message::set_received_time(int64_t time) const {
bool Message::WriteFileDescriptor(const base::FileDescriptor& descriptor) {
// We write the index of the descriptor so that we don't have to
// keep the current descriptor as extra decoding state when deserialising.
// Also, we rely on each file descriptor being accompanied by sizeof(int)
// bytes of data in the message. See the comment for input_cmsg_buf_.
WriteInt(file_descriptor_set()->size());
if (descriptor.auto_close) {
return file_descriptor_set()->AddAndAutoClose(descriptor.fd);