blob: 58dd6cae4a109ce9e9ff1f31e8acd9335c582e71 [file] [log] [blame]
pkasting@chromium.org9687a8f2011-09-01 09:50:13 +09001// Copyright (c) 2011 The Chromium Authors. All rights reserved.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
morrita33a35902015-01-15 06:17:06 +09005#include "ipc/ipc_message_attachment_set.h"
agl@chromium.orgc1e93ea2010-06-11 06:39:04 +09006
avi42ebda42015-12-22 11:39:04 +09007#include <stddef.h>
8
morrita6308f322015-01-27 07:42:54 +09009#include <algorithm>
avi42ebda42015-12-22 11:39:04 +090010
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090011#include "base/logging.h"
brettw@chromium.orgb1788fb2012-11-15 05:54:35 +090012#include "base/posix/eintr_wrapper.h"
avi42ebda42015-12-22 11:39:04 +090013#include "build/build_config.h"
morrita6308f322015-01-27 07:42:54 +090014#include "ipc/ipc_message_attachment.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090015
morrita33a35902015-01-15 06:17:06 +090016namespace IPC {
17
erikchenfdd43fe2015-07-08 07:13:11 +090018namespace {
19
20unsigned count_attachments_of_type(
21 const std::vector<scoped_refptr<MessageAttachment>>& attachments,
22 MessageAttachment::Type type) {
23 unsigned count = 0;
24 for (const scoped_refptr<MessageAttachment>& attachment : attachments) {
25 if (attachment->GetType() == type)
26 ++count;
27 }
28 return count;
29}
30
31} // namespace
32
morrita33a35902015-01-15 06:17:06 +090033MessageAttachmentSet::MessageAttachmentSet()
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090034 : consumed_descriptor_highwater_(0) {
35}
36
morrita33a35902015-01-15 06:17:06 +090037MessageAttachmentSet::~MessageAttachmentSet() {
sammc14583362016-11-23 12:17:35 +090038 if (consumed_descriptor_highwater_ == size())
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090039 return;
40
morritaab207252014-09-25 05:11:45 +090041 // We close all the owning descriptors. If this message should have
42 // been transmitted, then closing those with close flags set mirrors
43 // the expected behaviour.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090044 //
45 // If this message was received with more descriptors than expected
46 // (which could a DOS against the browser by a rogue renderer) then all
47 // the descriptors have their close flag set and we free all the extra
48 // kernel resources.
sammc14583362016-11-23 12:17:35 +090049 LOG(WARNING) << "MessageAttachmentSet destroyed with unconsumed attachments: "
50 << consumed_descriptor_highwater_ << "/" << size();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090051}
52
morrita6308f322015-01-27 07:42:54 +090053unsigned MessageAttachmentSet::num_descriptors() const {
erikchenfdd43fe2015-07-08 07:13:11 +090054 return count_attachments_of_type(attachments_,
sammc14583362016-11-23 12:17:35 +090055 MessageAttachment::Type::PLATFORM_FILE);
morrita33a35902015-01-15 06:17:06 +090056}
57
erikchenc8fa4212015-10-10 11:43:49 +090058unsigned MessageAttachmentSet::size() const {
sammc14583362016-11-23 12:17:35 +090059 return static_cast<unsigned>(attachments_.size());
erikchenc8fa4212015-10-10 11:43:49 +090060}
61
morrita7d1bfcc2015-01-31 14:45:42 +090062bool MessageAttachmentSet::AddAttachment(
erikchenc8fa4212015-10-10 11:43:49 +090063 scoped_refptr<MessageAttachment> attachment,
sammc14583362016-11-23 12:17:35 +090064 size_t* index) {
morrita7d1bfcc2015-01-31 14:45:42 +090065#if defined(OS_POSIX)
sammc14583362016-11-23 12:17:35 +090066 if (attachment->GetType() == MessageAttachment::Type::PLATFORM_FILE &&
morrita7d1bfcc2015-01-31 14:45:42 +090067 num_descriptors() == kMaxDescriptorsPerMessage) {
68 DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full.";
69 return false;
70 }
71#endif
72
erikchenc8fa4212015-10-10 11:43:49 +090073 switch (attachment->GetType()) {
sammc14583362016-11-23 12:17:35 +090074 case MessageAttachment::Type::PLATFORM_FILE:
75 case MessageAttachment::Type::MOJO_HANDLE:
76 case MessageAttachment::Type::WIN_HANDLE:
77 case MessageAttachment::Type::MACH_PORT:
Scott Graham3038c292017-06-30 10:07:10 +090078 case MessageAttachment::Type::FUCHSIA_HANDLE:
erikchenc8fa4212015-10-10 11:43:49 +090079 attachments_.push_back(attachment);
80 *index = attachments_.size() - 1;
erikchenc8fa4212015-10-10 11:43:49 +090081 return true;
82 }
83 return false;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090084}
85
erikchenc8fa4212015-10-10 11:43:49 +090086bool MessageAttachmentSet::AddAttachment(
87 scoped_refptr<MessageAttachment> attachment) {
erikchenc8fa4212015-10-10 11:43:49 +090088 size_t index;
sammc14583362016-11-23 12:17:35 +090089 return AddAttachment(attachment, &index);
erikchenc8fa4212015-10-10 11:43:49 +090090}
91
sammc14583362016-11-23 12:17:35 +090092scoped_refptr<MessageAttachment> MessageAttachmentSet::GetAttachmentAt(
93 unsigned index) {
94 if (index >= size()) {
95 DLOG(WARNING) << "Accessing out of bound index:" << index << "/" << size();
morrita6308f322015-01-27 07:42:54 +090096 return scoped_refptr<MessageAttachment>();
morritaab207252014-09-25 05:11:45 +090097 }
98
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090099 // We should always walk the descriptors in order, so it's reasonable to
100 // enforce this. Consider the case where a compromised renderer sends us
101 // the following message:
102 //
103 // ExampleMsg:
104 // num_fds:2 msg:FD(index = 1) control:SCM_RIGHTS {n, m}
105 //
106 // Here the renderer sent us a message which should have a descriptor, but
107 // actually sent two in an attempt to fill our fd table and kill us. By
108 // setting the index of the descriptor in the message to 1 (it should be
109 // 0), we would record a highwater of 1 and then consider all the
110 // descriptors to have been used.
111 //
112 // So we can either track of the use of each descriptor in a bitset, or we
113 // can enforce that we walk the indexes strictly in order.
114 //
115 // There's one more wrinkle: When logging messages, we may reparse them. So
116 // we have an exception: When the consumed_descriptor_highwater_ is at the
117 // end of the array and index 0 is requested, we reset the highwater value.
morritaab207252014-09-25 05:11:45 +0900118 // TODO(morrita): This is absurd. This "wringle" disallow to introduce clearer
119 // ownership model. Only client is NaclIPCAdapter. See crbug.com/415294
sammc14583362016-11-23 12:17:35 +0900120 if (index == 0 && consumed_descriptor_highwater_ == size()) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900121 consumed_descriptor_highwater_ = 0;
erikchenc8fa4212015-10-10 11:43:49 +0900122 }
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900123
124 if (index != consumed_descriptor_highwater_)
morrita6308f322015-01-27 07:42:54 +0900125 return scoped_refptr<MessageAttachment>();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900126
127 consumed_descriptor_highwater_ = index + 1;
morritaab207252014-09-25 05:11:45 +0900128
morrita6308f322015-01-27 07:42:54 +0900129 return attachments_[index];
130}
morritaab207252014-09-25 05:11:45 +0900131
erikchenc8fa4212015-10-10 11:43:49 +0900132void MessageAttachmentSet::CommitAllDescriptors() {
morrita1b52e4c2015-02-06 09:58:30 +0900133 attachments_.clear();
134 consumed_descriptor_highwater_ = 0;
135}
136
morrita33a35902015-01-15 06:17:06 +0900137} // namespace IPC