channel.cc 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "mojo/core/channel.h"
  5. #include <stddef.h>
  6. #include <string.h>
  7. #include <algorithm>
  8. #include <limits>
  9. #include <utility>
  10. #include "base/check_op.h"
  11. #include "base/logging.h"
  12. #include "base/memory/nonscannable_memory.h"
  13. #include "base/memory/ptr_util.h"
  14. #include "base/memory/raw_ptr.h"
  15. #include "base/numerics/safe_math.h"
  16. #include "base/process/process_handle.h"
  17. #include "base/trace_event/typed_macros.h"
  18. #include "build/build_config.h"
  19. #include "mojo/core/configuration.h"
  20. #include "mojo/core/core.h"
  21. #include "mojo/core/embedder/features.h"
  22. #if BUILDFLAG(IS_MAC)
  23. #include "base/mac/mach_logging.h"
  24. #elif BUILDFLAG(IS_WIN)
  25. #include "base/win/win_util.h"
  26. #endif
  27. namespace mojo {
  28. namespace core {
  29. namespace {
  30. std::atomic_bool g_use_trivial_messages{false};
  31. // To ensure amortized O(1) appends, need to be >1. Most STL implementations
  32. // use 2, but it may be too much for us, and we do see OOM crashes in the
  33. // reallocation.
  34. //
  35. // TODO(1301294): Consider asking the memory allocator for a
  36. // suitable size.
  37. constexpr float kGrowthFactor = 1.5;
  38. static_assert(
  39. IsAlignedForChannelMessage(sizeof(Channel::Message::LegacyHeader)),
  40. "Invalid LegacyHeader size.");
  41. static_assert(IsAlignedForChannelMessage(sizeof(Channel::Message::Header)),
  42. "Invalid Header size.");
  43. static_assert(sizeof(Channel::Message::LegacyHeader) == 8,
  44. "LegacyHeader must be 8 bytes on ChromeOS and Android");
  45. static_assert(offsetof(Channel::Message::LegacyHeader, num_bytes) ==
  46. offsetof(Channel::Message::Header, num_bytes),
  47. "num_bytes should be at the same offset in both Header structs.");
  48. static_assert(offsetof(Channel::Message::LegacyHeader, message_type) ==
  49. offsetof(Channel::Message::Header, message_type),
  50. "message_type should be at the same offset in both Header "
  51. "structs.");
  52. const size_t kReadBufferSize = 4096;
  53. const size_t kMaxUnusedReadBufferCapacity = 4096;
  54. // TODO(rockot): Increase this if/when Channel implementations support more.
  55. // Linux: The platform imposes a limit of 253 handles per sendmsg().
  56. // Fuchsia: The zx_channel_write() API supports up to 64 handles.
  57. const size_t kMaxAttachedHandles = 64;
  58. static_assert(alignof(std::max_align_t) >= kChannelMessageAlignment, "");
  59. Channel::AlignedBuffer MakeAlignedBuffer(size_t size) {
  60. // Generic allocators (such as malloc) return a pointer that is suitably
  61. // aligned for storing any type of object with a fundamental alignment
  62. // requirement. Buffers have no additional alignment requirement beyond that.
  63. void* ptr = base::AllocNonScannable(size);
  64. // Even though the allocator is configured in such a way that it crashes
  65. // rather than return nullptr, ASAN and friends don't know about that. This
  66. // CHECK() prevents Clusterfuzz from complaining. crbug.com/1180576.
  67. CHECK(ptr);
  68. return Channel::AlignedBuffer(static_cast<char*>(ptr));
  69. }
  70. struct TrivialMessage;
  71. // The type of message always used by a Channel which backs an ipcz transport.
  72. // Most of the inherited Message interface is unused since it's only called by
  73. // the original Mojo Core implementation.
  74. struct IpczMessage : public Channel::Message {
  75. IpczMessage(base::span<const uint8_t> data,
  76. std::vector<PlatformHandle> handles)
  77. : data_(sizeof(IpczHeader) + data.size()) {
  78. size_ = data_.size();
  79. IpczHeader& header = *reinterpret_cast<IpczHeader*>(data_.data());
  80. header.size = sizeof(IpczHeader);
  81. DCHECK_LE(handles.size(), std::numeric_limits<uint16_t>::max());
  82. DCHECK_LE(data_.size(), std::numeric_limits<uint32_t>::max());
  83. header.num_handles = static_cast<uint16_t>(handles.size());
  84. header.num_bytes = static_cast<uint32_t>(data_.size());
  85. memcpy(&header + 1, data.data(), data.size());
  86. handles_.reserve(handles.size());
  87. for (PlatformHandle& handle : handles) {
  88. handles_.emplace_back(std::move(handle));
  89. }
  90. }
  91. ~IpczMessage() override = default;
  92. // Channel::Message:
  93. void SetHandles(std::vector<PlatformHandle>) override { NOTREACHED(); }
  94. void SetHandles(std::vector<PlatformHandleInTransit>) override {
  95. NOTREACHED();
  96. }
  97. std::vector<PlatformHandleInTransit> TakeHandles() override {
  98. return std::move(handles_);
  99. }
  100. size_t NumHandlesForTransit() const override { return handles_.size(); }
  101. const void* data() const override { return data_.data(); }
  102. void* mutable_data() const override {
  103. NOTREACHED();
  104. return nullptr;
  105. }
  106. size_t capacity() const override { return data_.size(); }
  107. bool ExtendPayload(size_t) override {
  108. NOTREACHED();
  109. return false;
  110. }
  111. private:
  112. std::vector<uint8_t> data_;
  113. std::vector<PlatformHandleInTransit> handles_;
  114. };
  115. // A complex message can be large or contain file handles.
  116. struct ComplexMessage : public Channel::Message {
  117. ComplexMessage() = default;
  118. ComplexMessage(size_t capacity,
  119. size_t max_handles,
  120. size_t payload_size,
  121. MessageType message_type);
  122. ComplexMessage(const ComplexMessage&) = delete;
  123. ComplexMessage& operator=(const ComplexMessage&) = delete;
  124. ~ComplexMessage() override = default;
  125. // Message impl:
  126. void SetHandles(std::vector<PlatformHandle> new_handles) override;
  127. void SetHandles(std::vector<PlatformHandleInTransit> new_handles) override;
  128. std::vector<PlatformHandleInTransit> TakeHandles() override;
  129. size_t NumHandlesForTransit() const override;
  130. const void* data() const override { return data_.get(); }
  131. void* mutable_data() const override { return data_.get(); }
  132. size_t capacity() const override;
  133. bool ExtendPayload(size_t new_payload_size) override;
  134. private:
  135. friend struct Channel::Message;
  136. friend struct TrivialMessage;
  137. // The message data buffer.
  138. Channel::AlignedBuffer data_;
  139. // The capacity of the buffer at |data_|.
  140. size_t capacity_ = 0;
  141. // Maximum number of handles which may be attached to this message.
  142. size_t max_handles_ = 0;
  143. std::vector<PlatformHandleInTransit> handle_vector_;
  144. #if BUILDFLAG(IS_WIN)
  145. // On Windows, handles are serialised into the extra header section.
  146. raw_ptr<HandleEntry> handles_ = nullptr;
  147. #elif BUILDFLAG(IS_MAC)
  148. // On OSX, handles are serialised into the extra header section.
  149. raw_ptr<MachPortsExtraHeader> mach_ports_header_ = nullptr;
  150. #endif
  151. };
  152. struct TrivialMessage : public Channel::Message {
  153. TrivialMessage(const TrivialMessage&) = delete;
  154. TrivialMessage& operator=(const TrivialMessage&) = delete;
  155. ~TrivialMessage() override = default;
  156. // TryConstruct should be used to build a TrivialMessage.
  157. static Channel::MessagePtr TryConstruct(size_t payload_size,
  158. MessageType message_type);
  159. // Message impl:
  160. const void* data() const override { return &data_[0]; }
  161. void* mutable_data() const override {
  162. return const_cast<uint8_t*>(&data_[0]);
  163. }
  164. size_t capacity() const override;
  165. bool ExtendPayload(size_t new_payload_size) override;
  166. // The following interface methods are NOT supported on a Trivial message.
  167. void SetHandles(std::vector<PlatformHandle> new_handles) override;
  168. void SetHandles(std::vector<PlatformHandleInTransit> new_handles) override;
  169. std::vector<PlatformHandleInTransit> TakeHandles() override;
  170. size_t NumHandlesForTransit() const override;
  171. private:
  172. friend struct Channel::Message;
  173. TrivialMessage() = default;
  174. alignas(sizeof(void*)) uint8_t data_[256 - sizeof(Channel::Message)];
  175. static constexpr size_t kInternalCapacity = sizeof(data_);
  176. };
  177. static_assert(sizeof(TrivialMessage) == 256,
  178. "Expected TrivialMessage to be 256 bytes");
  179. } // namespace
  180. // static
  181. Channel::MessagePtr Channel::Message::CreateMessage(size_t payload_size,
  182. size_t max_handles) {
  183. return CreateMessage(payload_size, payload_size, max_handles);
  184. }
  185. // static
  186. Channel::MessagePtr Channel::Message::CreateMessage(size_t payload_size,
  187. size_t max_handles,
  188. MessageType message_type) {
  189. return CreateMessage(payload_size, payload_size, max_handles, message_type);
  190. }
  191. // static
  192. Channel::MessagePtr Channel::Message::CreateMessage(size_t capacity,
  193. size_t payload_size,
  194. size_t max_handles) {
  195. #if defined(MOJO_CORE_LEGACY_PROTOCOL)
  196. return CreateMessage(capacity, payload_size, max_handles,
  197. Message::MessageType::NORMAL_LEGACY);
  198. #else
  199. return CreateMessage(capacity, payload_size, max_handles,
  200. Message::MessageType::NORMAL);
  201. #endif
  202. }
  203. // static
  204. Channel::MessagePtr Channel::Message::CreateMessage(size_t capacity,
  205. size_t payload_size,
  206. size_t max_handles,
  207. MessageType message_type) {
  208. if (g_use_trivial_messages &&
  209. (capacity + std::max(sizeof(Header), sizeof(LegacyHeader))) <=
  210. TrivialMessage::kInternalCapacity &&
  211. max_handles == 0) {
  212. // The TrivialMessage has a fixed capacity so if the requested capacity
  213. // plus a header can fit then we can try to construct a TrivialMessage.
  214. auto msg = TrivialMessage::TryConstruct(payload_size, message_type);
  215. if (msg) {
  216. return msg;
  217. }
  218. }
  219. return base::WrapUnique<Channel::Message>(
  220. new ComplexMessage(capacity, payload_size, max_handles, message_type));
  221. }
  222. // static
  223. Channel::MessagePtr Channel::Message::CreateIpczMessage(
  224. base::span<const uint8_t> data,
  225. std::vector<PlatformHandle> handles) {
  226. return std::make_unique<IpczMessage>(data, std::move(handles));
  227. }
  228. // static
  229. void Channel::set_use_trivial_messages(bool use_trivial_messages) {
  230. g_use_trivial_messages = use_trivial_messages;
  231. }
  232. // static
  233. Channel::MessagePtr Channel::Message::CreateRawForFuzzing(
  234. base::span<const unsigned char> data) {
  235. auto message = std::make_unique<ComplexMessage>();
  236. message->size_ = data.size();
  237. if (data.size()) {
  238. message->data_ = MakeAlignedBuffer(data.size());
  239. std::copy(data.begin(), data.end(), message->data_.get());
  240. }
  241. return base::WrapUnique<Channel::Message>(message.release());
  242. }
  243. // static
  244. Channel::MessagePtr Channel::Message::Deserialize(
  245. const void* data,
  246. size_t data_num_bytes,
  247. HandlePolicy handle_policy,
  248. base::ProcessHandle from_process) {
  249. if (data_num_bytes < sizeof(LegacyHeader))
  250. return nullptr;
  251. const LegacyHeader* legacy_header =
  252. reinterpret_cast<const LegacyHeader*>(data);
  253. if (legacy_header->num_bytes != data_num_bytes) {
  254. DLOG(ERROR) << "Decoding invalid message: " << legacy_header->num_bytes
  255. << " != " << data_num_bytes;
  256. return nullptr;
  257. }
  258. // If a message isn't explicitly identified as type NORMAL_LEGACY, it is
  259. // expected to have a full-size header.
  260. const Header* header = nullptr;
  261. if (legacy_header->message_type != MessageType::NORMAL_LEGACY)
  262. header = reinterpret_cast<const Header*>(data);
  263. uint32_t extra_header_size = 0;
  264. size_t payload_size = 0;
  265. const char* payload = nullptr;
  266. if (!header) {
  267. payload_size = data_num_bytes - sizeof(LegacyHeader);
  268. payload = static_cast<const char*>(data) + sizeof(LegacyHeader);
  269. } else {
  270. if (header->num_bytes < header->num_header_bytes ||
  271. header->num_header_bytes < sizeof(Header)) {
  272. DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < "
  273. << header->num_header_bytes;
  274. return nullptr;
  275. }
  276. extra_header_size = header->num_header_bytes - sizeof(Header);
  277. payload_size = data_num_bytes - header->num_header_bytes;
  278. payload = static_cast<const char*>(data) + header->num_header_bytes;
  279. }
  280. if (!IsAlignedForChannelMessage(extra_header_size)) {
  281. // Well-formed messages always have any extra header bytes aligned to a
  282. // |kChannelMessageAlignment| boundary.
  283. DLOG(ERROR) << "Invalid extra header size";
  284. return nullptr;
  285. }
  286. #if BUILDFLAG(IS_WIN)
  287. uint32_t max_handles = extra_header_size / sizeof(HandleEntry);
  288. #elif BUILDFLAG(IS_FUCHSIA)
  289. uint32_t max_handles = extra_header_size / sizeof(HandleInfoEntry);
  290. #elif BUILDFLAG(IS_MAC)
  291. if (extra_header_size > 0 &&
  292. extra_header_size < sizeof(MachPortsExtraHeader)) {
  293. DLOG(ERROR) << "Decoding invalid message: " << extra_header_size << " < "
  294. << sizeof(MachPortsExtraHeader);
  295. return nullptr;
  296. }
  297. uint32_t max_handles =
  298. extra_header_size == 0
  299. ? 0
  300. : (extra_header_size - sizeof(MachPortsExtraHeader)) /
  301. sizeof(MachPortsEntry);
  302. #else
  303. const uint32_t max_handles = 0;
  304. // No extra header expected. Fail if this is detected.
  305. if (extra_header_size > 0) {
  306. DLOG(ERROR) << "Decoding invalid message: unexpected extra_header_size > 0";
  307. return nullptr;
  308. }
  309. #endif // BUILDFLAG(IS_WIN)
  310. const uint16_t num_handles =
  311. header ? header->num_handles : legacy_header->num_handles;
  312. if (num_handles > max_handles || max_handles > kMaxAttachedHandles) {
  313. DLOG(ERROR) << "Decoding invalid message: " << num_handles << " > "
  314. << max_handles;
  315. return nullptr;
  316. }
  317. if (num_handles > 0 && handle_policy == HandlePolicy::kRejectHandles) {
  318. DLOG(ERROR) << "Rejecting message with unexpected handle attachments.";
  319. return nullptr;
  320. }
  321. MessagePtr message =
  322. CreateMessage(payload_size, max_handles, legacy_header->message_type);
  323. DCHECK_EQ(message->data_num_bytes(), data_num_bytes);
  324. // Copy all payload bytes.
  325. if (payload_size)
  326. memcpy(message->mutable_payload(), payload, payload_size);
  327. if (header) {
  328. DCHECK_EQ(message->extra_header_size(), extra_header_size);
  329. DCHECK_EQ(message->header()->num_header_bytes, header->num_header_bytes);
  330. if (message->extra_header_size()) {
  331. // Copy extra header bytes.
  332. memcpy(message->mutable_extra_header(),
  333. static_cast<const char*>(data) + sizeof(Header),
  334. message->extra_header_size());
  335. }
  336. message->header()->num_handles = header->num_handles;
  337. } else {
  338. message->legacy_header()->num_handles = legacy_header->num_handles;
  339. }
  340. #if BUILDFLAG(IS_WIN)
  341. std::vector<PlatformHandleInTransit> handles(num_handles);
  342. for (size_t i = 0; i < num_handles; i++) {
  343. HANDLE handle = base::win::Uint32ToHandle(
  344. static_cast<ComplexMessage*>(message.get())->handles_[i].handle);
  345. if (PlatformHandleInTransit::IsPseudoHandle(handle))
  346. return nullptr;
  347. if (from_process == base::kNullProcessHandle) {
  348. handles[i] = PlatformHandleInTransit(
  349. PlatformHandle(base::win::ScopedHandle(handle)));
  350. } else {
  351. handles[i] = PlatformHandleInTransit(
  352. PlatformHandleInTransit::TakeIncomingRemoteHandle(handle,
  353. from_process));
  354. }
  355. }
  356. message->SetHandles(std::move(handles));
  357. #endif
  358. return message;
  359. }
  360. // static
  361. void Channel::Message::ExtendPayload(MessagePtr& message,
  362. size_t new_payload_size) {
  363. if (message->ExtendPayload(new_payload_size)) {
  364. return;
  365. }
  366. // ComplexMessage will never fail to extend the payload; therefore, if we do
  367. // fail it's because the message is a TrivialMessage which has run out of
  368. // space. In which case we will upgrade the message type to a ComplexMessage.
  369. size_t capacity_without_header = message->capacity();
  370. auto m = base::WrapUnique<Channel::Message>(
  371. new ComplexMessage(new_payload_size, new_payload_size, 0,
  372. message->legacy_header()->message_type));
  373. memcpy(m->mutable_payload(), message->payload(), capacity_without_header);
  374. message.swap(m);
  375. }
  376. const void* Channel::Message::extra_header() const {
  377. DCHECK(!is_legacy_message());
  378. return reinterpret_cast<const uint8_t*>(data()) + sizeof(Header);
  379. }
  380. void* Channel::Message::mutable_extra_header() {
  381. DCHECK(!is_legacy_message());
  382. return reinterpret_cast<uint8_t*>(mutable_data()) + sizeof(Header);
  383. }
  384. size_t Channel::Message::extra_header_size() const {
  385. return header()->num_header_bytes - sizeof(Header);
  386. }
  387. void* Channel::Message::mutable_payload() {
  388. if (is_legacy_message())
  389. return static_cast<void*>(legacy_header() + 1);
  390. return reinterpret_cast<uint8_t*>(mutable_data()) +
  391. header()->num_header_bytes;
  392. }
  393. const void* Channel::Message::payload() const {
  394. if (is_legacy_message())
  395. return static_cast<const void*>(legacy_header() + 1);
  396. return reinterpret_cast<const uint8_t*>(data()) + header()->num_header_bytes;
  397. }
  398. size_t Channel::Message::payload_size() const {
  399. if (is_legacy_message())
  400. return legacy_header()->num_bytes - sizeof(LegacyHeader);
  401. return size_ - header()->num_header_bytes;
  402. }
  403. size_t Channel::Message::num_handles() const {
  404. return is_legacy_message() ? legacy_header()->num_handles
  405. : header()->num_handles;
  406. }
  407. bool Channel::Message::has_handles() const {
  408. return (is_legacy_message() ? legacy_header()->num_handles
  409. : header()->num_handles) > 0;
  410. }
  411. bool Channel::Message::is_legacy_message() const {
  412. return legacy_header()->message_type == MessageType::NORMAL_LEGACY;
  413. }
  414. Channel::Message::LegacyHeader* Channel::Message::legacy_header() const {
  415. return reinterpret_cast<LegacyHeader*>(mutable_data());
  416. }
  417. Channel::Message::Header* Channel::Message::header() const {
  418. DCHECK(!is_legacy_message());
  419. return reinterpret_cast<Header*>(mutable_data());
  420. }
  421. ComplexMessage::ComplexMessage(size_t capacity,
  422. size_t payload_size,
  423. size_t max_handles,
  424. MessageType message_type)
  425. : max_handles_(max_handles) {
  426. DCHECK_GE(capacity, payload_size);
  427. DCHECK_LE(max_handles_, kMaxAttachedHandles);
  428. const bool is_legacy_message = (message_type == MessageType::NORMAL_LEGACY);
  429. size_t extra_header_size = 0;
  430. #if BUILDFLAG(IS_WIN)
  431. // On Windows we serialize HANDLEs into the extra header space.
  432. extra_header_size = max_handles_ * sizeof(HandleEntry);
  433. #elif BUILDFLAG(IS_FUCHSIA)
  434. // On Fuchsia we serialize handle types into the extra header space.
  435. extra_header_size = max_handles_ * sizeof(HandleInfoEntry);
  436. #elif BUILDFLAG(IS_MAC)
  437. // On OSX, some of the platform handles may be mach ports, which are
  438. // serialised into the message buffer. Since there could be a mix of fds and
  439. // mach ports, we store the mach ports as an <index, port> pair (of uint32_t),
  440. // so that the original ordering of handles can be re-created.
  441. if (max_handles) {
  442. extra_header_size =
  443. sizeof(MachPortsExtraHeader) + (max_handles * sizeof(MachPortsEntry));
  444. }
  445. #endif
  446. // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes.
  447. if (!IsAlignedForChannelMessage(extra_header_size)) {
  448. extra_header_size += kChannelMessageAlignment -
  449. (extra_header_size % kChannelMessageAlignment);
  450. }
  451. DCHECK(IsAlignedForChannelMessage(extra_header_size));
  452. const size_t header_size =
  453. is_legacy_message ? sizeof(LegacyHeader) : sizeof(Header);
  454. DCHECK(extra_header_size == 0 || !is_legacy_message);
  455. capacity_ = header_size + extra_header_size + capacity;
  456. size_ = header_size + extra_header_size + payload_size;
  457. data_ = MakeAlignedBuffer(capacity_);
  458. // Only zero out the header and not the payload. Since the payload is going to
  459. // be memcpy'd, zeroing the payload is unnecessary work and a significant
  460. // performance issue when dealing with large messages. Any sanitizer errors
  461. // complaining about an uninitialized read in the payload area should be
  462. // treated as an error and fixed.
  463. memset(mutable_data(), 0, header_size + extra_header_size);
  464. DCHECK(base::IsValueInRangeForNumericType<uint32_t>(size_));
  465. legacy_header()->num_bytes = static_cast<uint32_t>(size_);
  466. DCHECK(base::IsValueInRangeForNumericType<uint16_t>(header_size +
  467. extra_header_size));
  468. legacy_header()->message_type = message_type;
  469. if (is_legacy_message) {
  470. legacy_header()->num_handles = static_cast<uint16_t>(max_handles);
  471. } else {
  472. header()->num_header_bytes =
  473. static_cast<uint16_t>(header_size + extra_header_size);
  474. }
  475. if (max_handles_ > 0) {
  476. #if BUILDFLAG(IS_WIN)
  477. handles_ = reinterpret_cast<HandleEntry*>(mutable_extra_header());
  478. // Initialize all handles to invalid values.
  479. for (size_t i = 0; i < max_handles_; ++i)
  480. handles_[i].handle = base::win::HandleToUint32(INVALID_HANDLE_VALUE);
  481. #elif BUILDFLAG(IS_MAC)
  482. mach_ports_header_ =
  483. reinterpret_cast<MachPortsExtraHeader*>(mutable_extra_header());
  484. mach_ports_header_->num_ports = 0;
  485. // Initialize all handles to invalid values.
  486. for (size_t i = 0; i < max_handles_; ++i) {
  487. mach_ports_header_->entries[i] = {0};
  488. }
  489. #endif
  490. }
  491. }
  492. size_t ComplexMessage::capacity() const {
  493. if (is_legacy_message())
  494. return capacity_ - sizeof(LegacyHeader);
  495. return capacity_ - header()->num_header_bytes;
  496. }
  497. bool ComplexMessage::ExtendPayload(size_t new_payload_size) {
  498. size_t capacity_without_header = capacity();
  499. size_t header_size = capacity_ - capacity_without_header;
  500. if (new_payload_size > capacity_without_header) {
  501. size_t new_capacity =
  502. std::max(static_cast<size_t>(capacity_without_header * kGrowthFactor),
  503. new_payload_size) +
  504. header_size;
  505. Channel::AlignedBuffer new_data = MakeAlignedBuffer(new_capacity);
  506. memcpy(new_data.get(), data_.get(), capacity_);
  507. data_ = std::move(new_data);
  508. capacity_ = new_capacity;
  509. if (max_handles_ > 0) {
  510. // We also need to update the cached extra header addresses in case the
  511. // payload buffer has been relocated.
  512. #if BUILDFLAG(IS_WIN)
  513. handles_ = reinterpret_cast<HandleEntry*>(mutable_extra_header());
  514. #elif BUILDFLAG(IS_MAC)
  515. mach_ports_header_ =
  516. reinterpret_cast<MachPortsExtraHeader*>(mutable_extra_header());
  517. #endif
  518. }
  519. }
  520. size_ = header_size + new_payload_size;
  521. DCHECK(base::IsValueInRangeForNumericType<uint32_t>(size_));
  522. legacy_header()->num_bytes = static_cast<uint32_t>(size_);
  523. return true;
  524. }
  525. void ComplexMessage::SetHandles(std::vector<PlatformHandle> new_handles) {
  526. std::vector<PlatformHandleInTransit> handles;
  527. handles.reserve(new_handles.size());
  528. for (auto& h : new_handles) {
  529. handles.emplace_back(PlatformHandleInTransit(std::move(h)));
  530. }
  531. SetHandles(std::move(handles));
  532. }
  533. void ComplexMessage::SetHandles(
  534. std::vector<PlatformHandleInTransit> new_handles) {
  535. if (is_legacy_message()) {
  536. // Old semantics for ChromeOS and Android
  537. if (legacy_header()->num_handles == 0) {
  538. CHECK(new_handles.empty());
  539. return;
  540. }
  541. CHECK_EQ(new_handles.size(), legacy_header()->num_handles);
  542. std::swap(handle_vector_, new_handles);
  543. return;
  544. }
  545. if (max_handles_ == 0) {
  546. CHECK(new_handles.empty());
  547. return;
  548. }
  549. CHECK_LE(new_handles.size(), max_handles_);
  550. header()->num_handles = static_cast<uint16_t>(new_handles.size());
  551. std::swap(handle_vector_, new_handles);
  552. #if BUILDFLAG(IS_WIN)
  553. memset(handles_, 0, extra_header_size());
  554. for (size_t i = 0; i < handle_vector_.size(); i++) {
  555. HANDLE handle = handle_vector_[i].remote_handle();
  556. if (handle == INVALID_HANDLE_VALUE)
  557. handle = handle_vector_[i].handle().GetHandle().Get();
  558. handles_[i].handle = base::win::HandleToUint32(handle);
  559. }
  560. #endif // BUILDFLAG(IS_WIN)
  561. #if BUILDFLAG(IS_MAC)
  562. if (mach_ports_header_) {
  563. for (size_t i = 0; i < max_handles_; ++i) {
  564. mach_ports_header_->entries[i] = {0};
  565. }
  566. for (size_t i = 0; i < handle_vector_.size(); i++) {
  567. mach_ports_header_->entries[i].type =
  568. static_cast<uint8_t>(handle_vector_[i].handle().type());
  569. }
  570. mach_ports_header_->num_ports = handle_vector_.size();
  571. }
  572. #endif
  573. }
  574. std::vector<PlatformHandleInTransit> ComplexMessage::TakeHandles() {
  575. return std::move(handle_vector_);
  576. }
  577. size_t ComplexMessage::NumHandlesForTransit() const {
  578. return handle_vector_.size();
  579. }
  580. // static
  581. Channel::MessagePtr TrivialMessage::TryConstruct(size_t payload_size,
  582. MessageType message_type) {
  583. const bool is_legacy_message = (message_type == MessageType::NORMAL_LEGACY);
  584. const size_t header_size =
  585. is_legacy_message ? sizeof(LegacyHeader) : sizeof(Header);
  586. size_t size = header_size + payload_size;
  587. if (size > kInternalCapacity) {
  588. return nullptr;
  589. }
  590. auto message = base::WrapUnique(new TrivialMessage);
  591. memset(message->mutable_data(), 0, sizeof(TrivialMessage::data_));
  592. DCHECK(base::IsValueInRangeForNumericType<uint32_t>(size));
  593. message->size_ = size;
  594. message->legacy_header()->num_bytes = static_cast<uint32_t>(size);
  595. message->legacy_header()->message_type = message_type;
  596. if (!is_legacy_message) {
  597. DCHECK(base::IsValueInRangeForNumericType<uint16_t>(header_size));
  598. message->header()->num_header_bytes = static_cast<uint16_t>(header_size);
  599. }
  600. return base::WrapUnique<Channel::Message>(message.release());
  601. }
  602. size_t TrivialMessage::capacity() const {
  603. if (is_legacy_message())
  604. return kInternalCapacity - sizeof(LegacyHeader);
  605. return kInternalCapacity - header()->num_header_bytes;
  606. }
  607. bool TrivialMessage::ExtendPayload(size_t new_payload_size) {
  608. size_t capacity_without_header = capacity();
  609. size_t header_size = kInternalCapacity - capacity_without_header;
  610. size_t required_size = new_payload_size + header_size;
  611. if (required_size > kInternalCapacity) {
  612. return false;
  613. }
  614. // We can just bump up the internal size as it's less than the capacity.
  615. size_ = required_size;
  616. DCHECK(base::IsValueInRangeForNumericType<uint32_t>(size_));
  617. legacy_header()->num_bytes = static_cast<uint32_t>(size_);
  618. return true;
  619. }
  620. void TrivialMessage::SetHandles(std::vector<PlatformHandle> new_handles) {
  621. CHECK(new_handles.empty());
  622. }
  623. void TrivialMessage::SetHandles(
  624. std::vector<PlatformHandleInTransit> new_handles) {
  625. CHECK(new_handles.empty());
  626. }
  627. std::vector<PlatformHandleInTransit> TrivialMessage::TakeHandles() {
  628. return std::vector<PlatformHandleInTransit>();
  629. }
  630. size_t TrivialMessage::NumHandlesForTransit() const {
  631. return 0;
  632. }
  633. // Helper class for managing a Channel's read buffer allocations. This maintains
  634. // a single contiguous buffer with the layout:
  635. //
  636. // [discarded bytes][occupied bytes][unoccupied bytes]
  637. //
  638. // The Reserve() method ensures that a certain capacity of unoccupied bytes are
  639. // available. It does not claim that capacity and only allocates new capacity
  640. // when strictly necessary.
  641. //
  642. // Claim() marks unoccupied bytes as occupied.
  643. //
  644. // Discard() marks occupied bytes as discarded, signifying that their contents
  645. // can be forgotten or overwritten.
  646. //
  647. // Realign() moves occupied bytes to the front of the buffer so that those
  648. // occupied bytes are properly aligned.
  649. //
  650. // The most common Channel behavior in practice should result in very few
  651. // allocations and copies, as memory is claimed and discarded shortly after
  652. // being reserved, and future reservations will immediately reuse discarded
  653. // memory.
  654. class Channel::ReadBuffer {
  655. public:
  656. ReadBuffer() {
  657. size_ = kReadBufferSize;
  658. data_ = MakeAlignedBuffer(size_);
  659. }
  660. ReadBuffer(const ReadBuffer&) = delete;
  661. ReadBuffer& operator=(const ReadBuffer&) = delete;
  662. ~ReadBuffer() { DCHECK(data_); }
  663. const char* occupied_bytes() const {
  664. return data_.get() + num_discarded_bytes_;
  665. }
  666. size_t num_occupied_bytes() const {
  667. return num_occupied_bytes_ - num_discarded_bytes_;
  668. }
  669. // Ensures the ReadBuffer has enough contiguous space allocated to hold
  670. // |num_bytes| more bytes; returns the address of the first available byte.
  671. char* Reserve(size_t num_bytes) {
  672. if (num_occupied_bytes_ + num_bytes > size_) {
  673. size_ = std::max(static_cast<size_t>(size_ * kGrowthFactor),
  674. num_occupied_bytes_ + num_bytes);
  675. AlignedBuffer new_data = MakeAlignedBuffer(size_);
  676. memcpy(new_data.get(), data_.get(), num_occupied_bytes_);
  677. data_ = std::move(new_data);
  678. }
  679. return data_.get() + num_occupied_bytes_;
  680. }
  681. // Marks the first |num_bytes| unoccupied bytes as occupied.
  682. void Claim(size_t num_bytes) {
  683. DCHECK_LE(num_occupied_bytes_ + num_bytes, size_);
  684. num_occupied_bytes_ += num_bytes;
  685. }
  686. // Marks the first |num_bytes| occupied bytes as discarded. This may result in
  687. // shrinkage of the internal buffer, and it is not safe to assume the result
  688. // of a previous Reserve() call is still valid after this.
  689. void Discard(size_t num_bytes) {
  690. DCHECK_LE(num_discarded_bytes_ + num_bytes, num_occupied_bytes_);
  691. num_discarded_bytes_ += num_bytes;
  692. if (num_discarded_bytes_ == num_occupied_bytes_) {
  693. // We can just reuse the buffer from the beginning in this common case.
  694. num_discarded_bytes_ = 0;
  695. num_occupied_bytes_ = 0;
  696. }
  697. if (num_discarded_bytes_ > kMaxUnusedReadBufferCapacity) {
  698. // In the uncommon case that we have a lot of discarded data at the
  699. // front of the buffer, simply move remaining data to a smaller buffer.
  700. size_t num_preserved_bytes = num_occupied_bytes_ - num_discarded_bytes_;
  701. size_ = std::max(num_preserved_bytes, kReadBufferSize);
  702. AlignedBuffer new_data = MakeAlignedBuffer(size_);
  703. memcpy(new_data.get(), data_.get() + num_discarded_bytes_,
  704. num_preserved_bytes);
  705. data_ = std::move(new_data);
  706. num_discarded_bytes_ = 0;
  707. num_occupied_bytes_ = num_preserved_bytes;
  708. }
  709. if (num_occupied_bytes_ == 0 && size_ > kMaxUnusedReadBufferCapacity) {
  710. // Opportunistically shrink the read buffer back down to a small size if
  711. // it's grown very large. We only do this if there are no remaining
  712. // unconsumed bytes in the buffer to avoid copies in most the common
  713. // cases.
  714. size_ = kMaxUnusedReadBufferCapacity;
  715. data_ = MakeAlignedBuffer(size_);
  716. }
  717. }
  718. void Realign() {
  719. size_t num_bytes = num_occupied_bytes();
  720. memmove(data_.get(), occupied_bytes(), num_bytes);
  721. num_discarded_bytes_ = 0;
  722. num_occupied_bytes_ = num_bytes;
  723. }
  724. private:
  725. AlignedBuffer data_;
  726. // The total size of the allocated buffer.
  727. size_t size_ = 0;
  728. // The number of discarded bytes at the beginning of the allocated buffer.
  729. size_t num_discarded_bytes_ = 0;
  730. // The total number of occupied bytes, including discarded bytes.
  731. size_t num_occupied_bytes_ = 0;
  732. };
  733. bool Channel::Delegate::IsIpczTransport() const {
  734. return false;
  735. }
  736. void Channel::Delegate::OnChannelDestroyed() {}
  737. Channel::Channel(Delegate* delegate,
  738. HandlePolicy handle_policy,
  739. DispatchBufferPolicy buffer_policy)
  740. : is_for_ipcz_(delegate ? delegate->IsIpczTransport() : false),
  741. delegate_(delegate),
  742. handle_policy_(handle_policy),
  743. read_buffer_(buffer_policy == DispatchBufferPolicy::kManaged
  744. ? new ReadBuffer
  745. : nullptr) {}
  746. Channel::~Channel() {
  747. if (is_for_ipcz()) {
  748. DCHECK(delegate_);
  749. delegate_->OnChannelDestroyed();
  750. }
  751. }
  752. // static
  753. scoped_refptr<Channel> Channel::CreateForIpczDriver(
  754. Delegate* delegate,
  755. PlatformChannelEndpoint endpoint,
  756. scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
  757. scoped_refptr<Channel> channel =
  758. Create(delegate, ConnectionParams(std::move(endpoint)),
  759. HandlePolicy::kAcceptHandles, std::move(io_task_runner));
  760. return channel;
  761. }
  762. void Channel::ShutDown() {
  763. ShutDownImpl();
  764. if (!is_for_ipcz()) {
  765. // When Channel is used for an ipcz transport, we leave `delegate_` intact
  766. // so the Channel can notify once it's finally being destroyed.
  767. delegate_ = nullptr;
  768. }
  769. }
  770. char* Channel::GetReadBuffer(size_t* buffer_capacity) {
  771. DCHECK(read_buffer_);
  772. size_t required_capacity = *buffer_capacity;
  773. if (!required_capacity)
  774. required_capacity = kReadBufferSize;
  775. *buffer_capacity = required_capacity;
  776. return read_buffer_->Reserve(required_capacity);
  777. }
  778. bool Channel::OnReadComplete(size_t bytes_read, size_t* next_read_size_hint) {
  779. DCHECK(read_buffer_);
  780. *next_read_size_hint = kReadBufferSize;
  781. read_buffer_->Claim(bytes_read);
  782. const size_t header_size = is_for_ipcz_ ? sizeof(Message::IpczHeader)
  783. : sizeof(Message::LegacyHeader);
  784. while (read_buffer_->num_occupied_bytes() >= header_size) {
  785. // Ensure the occupied data is properly aligned. If it isn't, a SIGBUS could
  786. // happen on architectures that don't allow misaligned words access (i.e.
  787. // anything other than x86). Only re-align when necessary to avoid copies.
  788. if (!IsAlignedForChannelMessage(
  789. reinterpret_cast<uintptr_t>(read_buffer_->occupied_bytes()))) {
  790. read_buffer_->Realign();
  791. }
  792. DispatchResult result =
  793. TryDispatchMessage(base::make_span(read_buffer_->occupied_bytes(),
  794. read_buffer_->num_occupied_bytes()),
  795. next_read_size_hint);
  796. if (result == DispatchResult::kOK) {
  797. read_buffer_->Discard(*next_read_size_hint);
  798. *next_read_size_hint = 0;
  799. } else if (result == DispatchResult::kNotEnoughData) {
  800. return true;
  801. } else if (result == DispatchResult::kMissingHandles) {
  802. break;
  803. } else if (result == DispatchResult::kError) {
  804. return false;
  805. }
  806. }
  807. return true;
  808. }
  809. Channel::DispatchResult Channel::TryDispatchMessage(
  810. base::span<const char> buffer,
  811. size_t* size_hint) {
  812. TRACE_EVENT(TRACE_DISABLED_BY_DEFAULT("toplevel.ipc"),
  813. "Mojo dispatch message");
  814. if (is_for_ipcz_) {
  815. // This has already been validated.
  816. DCHECK_GE(buffer.size(), sizeof(Message::IpczHeader));
  817. const auto& header =
  818. *reinterpret_cast<const Message::IpczHeader*>(buffer.data());
  819. const size_t header_size = header.size;
  820. const size_t num_bytes = header.num_bytes;
  821. const size_t num_handles = header.num_handles;
  822. if (header_size < sizeof(header) || num_bytes < header_size) {
  823. return DispatchResult::kError;
  824. }
  825. if (buffer.size() < num_bytes) {
  826. *size_hint = num_bytes - buffer.size();
  827. return DispatchResult::kNotEnoughData;
  828. }
  829. std::vector<PlatformHandle> handles;
  830. if (num_handles > 0) {
  831. if (handle_policy_ == HandlePolicy::kRejectHandles ||
  832. !GetReadPlatformHandlesForIpcz(num_handles, handles)) {
  833. return DispatchResult::kError;
  834. }
  835. if (handles.empty()) {
  836. return DispatchResult::kMissingHandles;
  837. }
  838. }
  839. auto data = buffer.first(num_bytes).subspan(header_size);
  840. delegate_->OnChannelMessage(data.data(), data.size(), std::move(handles));
  841. *size_hint = num_bytes;
  842. return DispatchResult::kOK;
  843. }
  844. // We have at least enough data available for a LegacyHeader.
  845. const Message::LegacyHeader* legacy_header =
  846. reinterpret_cast<const Message::LegacyHeader*>(buffer.data());
  847. if (legacy_header->num_bytes < sizeof(Message::LegacyHeader)) {
  848. LOG(ERROR) << "Invalid message size: " << legacy_header->num_bytes;
  849. return DispatchResult::kError;
  850. }
  851. if (buffer.size() < legacy_header->num_bytes) {
  852. // Not enough data available to read the full message. Hint to the
  853. // implementation that it should try reading the full size of the message.
  854. *size_hint = legacy_header->num_bytes - buffer.size();
  855. return DispatchResult::kNotEnoughData;
  856. }
  857. const Message::Header* header = nullptr;
  858. if (legacy_header->message_type != Message::MessageType::NORMAL_LEGACY) {
  859. header = reinterpret_cast<const Message::Header*>(legacy_header);
  860. }
  861. size_t extra_header_size = 0;
  862. const void* extra_header = nullptr;
  863. size_t payload_size = 0;
  864. void* payload = nullptr;
  865. if (header) {
  866. if (header->num_header_bytes < sizeof(Message::Header) ||
  867. header->num_header_bytes > header->num_bytes) {
  868. LOG(ERROR) << "Invalid message header size: " << header->num_header_bytes;
  869. return DispatchResult::kError;
  870. }
  871. extra_header_size = header->num_header_bytes - sizeof(Message::Header);
  872. extra_header = extra_header_size ? header + 1 : nullptr;
  873. payload_size = header->num_bytes - header->num_header_bytes;
  874. payload =
  875. payload_size
  876. ? reinterpret_cast<Message::Header*>(
  877. const_cast<char*>(buffer.data()) + header->num_header_bytes)
  878. : nullptr;
  879. } else {
  880. payload_size = legacy_header->num_bytes - sizeof(Message::LegacyHeader);
  881. payload = payload_size
  882. ? const_cast<Message::LegacyHeader*>(&legacy_header[1])
  883. : nullptr;
  884. }
  885. const uint16_t num_handles =
  886. header ? header->num_handles : legacy_header->num_handles;
  887. std::vector<PlatformHandle> handles;
  888. bool deferred = false;
  889. if (num_handles > 0) {
  890. if (handle_policy_ == HandlePolicy::kRejectHandles)
  891. return DispatchResult::kError;
  892. if (!GetReadPlatformHandles(payload, payload_size, num_handles,
  893. extra_header, extra_header_size, &handles,
  894. &deferred)) {
  895. return DispatchResult::kError;
  896. }
  897. if (handles.empty()) {
  898. // Not enough handles available for this message.
  899. return DispatchResult::kMissingHandles;
  900. }
  901. }
  902. // We've got a complete message! Dispatch it and try another.
  903. if (legacy_header->message_type != Message::MessageType::NORMAL_LEGACY &&
  904. legacy_header->message_type != Message::MessageType::NORMAL) {
  905. DCHECK(!deferred);
  906. if (!OnControlMessage(legacy_header->message_type, payload, payload_size,
  907. std::move(handles))) {
  908. return DispatchResult::kError;
  909. }
  910. } else if (!deferred && delegate_) {
  911. delegate_->OnChannelMessage(payload, payload_size, std::move(handles));
  912. }
  913. *size_hint = legacy_header->num_bytes;
  914. return DispatchResult::kOK;
  915. }
  916. void Channel::OnError(Error error) {
  917. if (delegate_)
  918. delegate_->OnChannelError(error);
  919. }
  920. bool Channel::OnControlMessage(Message::MessageType message_type,
  921. const void* payload,
  922. size_t payload_size,
  923. std::vector<PlatformHandle> handles) {
  924. return false;
  925. }
  926. // Currently only Non-nacl CrOs, Linux, and Android support upgrades.
  927. #if BUILDFLAG(IS_NACL) || (!(BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || \
  928. BUILDFLAG(IS_ANDROID)))
  929. // static
  930. MOJO_SYSTEM_IMPL_EXPORT bool Channel::SupportsChannelUpgrade() {
  931. return false;
  932. }
  933. MOJO_SYSTEM_IMPL_EXPORT void Channel::OfferChannelUpgrade() {
  934. NOTREACHED();
  935. return;
  936. }
  937. #endif
  938. } // namespace core
  939. } // namespace mojo