From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- ipc/chromium/src/mojo/core/ports/event.cc | 565 ++++++++++++++++++++++++++++++ 1 file changed, 565 insertions(+) create mode 100644 ipc/chromium/src/mojo/core/ports/event.cc (limited to 'ipc/chromium/src/mojo/core/ports/event.cc') diff --git a/ipc/chromium/src/mojo/core/ports/event.cc b/ipc/chromium/src/mojo/core/ports/event.cc new file mode 100644 index 0000000000..5caec8ae55 --- /dev/null +++ b/ipc/chromium/src/mojo/core/ports/event.cc @@ -0,0 +1,565 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/core/ports/event.h" + +#include +#include + +#include "base/logging.h" +#include "mojo/core/ports/name.h" +#include "mojo/core/ports/user_message.h" +#include "mozilla/Assertions.h" +#include "mozilla/CheckedInt.h" + +namespace mojo { +namespace core { +namespace ports { + +namespace { + +const size_t kPortsMessageAlignment = 8; + +#pragma pack(push, 1) + +struct SerializedHeader { + Event::Type type; + uint32_t padding; + PortName port_name; + PortName from_port; + uint64_t control_sequence_num; +}; + +struct UserMessageEventData { + uint64_t sequence_num; + uint32_t num_ports; + uint32_t padding; +}; + +struct ObserveProxyEventData { + NodeName proxy_node_name; + PortName proxy_port_name; + NodeName proxy_target_node_name; + PortName proxy_target_port_name; +}; + +struct ObserveProxyAckEventData { + uint64_t last_sequence_num; +}; + +struct ObserveClosureEventData { + uint64_t last_sequence_num; +}; + +struct MergePortEventData { + PortName new_port_name; + Event::PortDescriptor new_port_descriptor; +}; + +struct UserMessageReadAckRequestEventData { + uint64_t sequence_num_to_acknowledge; +}; + +struct UserMessageReadAckEventData { + uint64_t sequence_num_acknowledged; +}; + +struct UpdatePreviousPeerEventData { + NodeName new_node_name; + PortName new_port_name; +}; + +#pragma pack(pop) + +static_assert(sizeof(Event::PortDescriptor) % kPortsMessageAlignment == 0, + "Invalid PortDescriptor size."); + +static_assert(sizeof(SerializedHeader) % kPortsMessageAlignment == 0, + "Invalid SerializedHeader size."); + +static_assert(sizeof(UserMessageEventData) % kPortsMessageAlignment == 0, + "Invalid UserEventData size."); + +static_assert(sizeof(ObserveProxyEventData) % kPortsMessageAlignment == 0, + "Invalid ObserveProxyEventData size."); + +static_assert(sizeof(ObserveProxyAckEventData) % kPortsMessageAlignment == 0, + "Invalid ObserveProxyAckEventData size."); + +static_assert(sizeof(ObserveClosureEventData) % kPortsMessageAlignment == 0, + "Invalid ObserveClosureEventData size."); + +static_assert(sizeof(MergePortEventData) % kPortsMessageAlignment == 0, + "Invalid MergePortEventData size."); + +static_assert(sizeof(UserMessageReadAckRequestEventData) % + kPortsMessageAlignment == + 0, + "Invalid UserMessageReadAckRequestEventData size."); + +static_assert(sizeof(UserMessageReadAckEventData) % kPortsMessageAlignment == 0, + "Invalid UserMessageReadAckEventData size."); + +static_assert(sizeof(UpdatePreviousPeerEventData) % kPortsMessageAlignment == 0, + "Invalid UpdatePreviousPeerEventData size."); + +} // namespace + +Event::PortDescriptor::PortDescriptor() { memset(padding, 0, sizeof(padding)); } + +Event::~Event() = default; + +// static +ScopedEvent Event::Deserialize(const void* buffer, size_t num_bytes) { + if (num_bytes < sizeof(SerializedHeader)) { + return nullptr; + } + + const auto* header = static_cast(buffer); + const PortName& port_name = header->port_name; + const PortName& from_port = header->from_port; + const uint64_t control_sequence_num = header->control_sequence_num; + const size_t data_size = num_bytes - sizeof(*header); + switch (header->type) { + case Type::kUserMessage: + return UserMessageEvent::Deserialize( + port_name, from_port, control_sequence_num, header + 1, data_size); + case Type::kPortAccepted: + return PortAcceptedEvent::Deserialize( + port_name, from_port, control_sequence_num, header + 1, data_size); + case Type::kObserveProxy: + return ObserveProxyEvent::Deserialize( + port_name, from_port, control_sequence_num, header + 1, data_size); + case Type::kObserveProxyAck: + return ObserveProxyAckEvent::Deserialize( + port_name, from_port, control_sequence_num, header + 1, data_size); + case Type::kObserveClosure: + return ObserveClosureEvent::Deserialize( + port_name, from_port, control_sequence_num, header + 1, data_size); + case Type::kMergePort: + return MergePortEvent::Deserialize( + port_name, from_port, control_sequence_num, header + 1, data_size); + case Type::kUserMessageReadAckRequest: + return UserMessageReadAckRequestEvent::Deserialize( + port_name, from_port, control_sequence_num, header + 1, data_size); + case Type::kUserMessageReadAck: + return UserMessageReadAckEvent::Deserialize( + port_name, from_port, control_sequence_num, header + 1, data_size); + case Type::kUpdatePreviousPeer: + return UpdatePreviousPeerEvent::Deserialize( + port_name, from_port, control_sequence_num, header + 1, data_size); + default: + DVLOG(2) << "Ingoring unknown port event type: " + << static_cast(header->type); + return nullptr; + } +} + +Event::Event(Type type, const PortName& port_name, const PortName& from_port, + uint64_t control_sequence_num) + : type_(type), + port_name_(port_name), + from_port_(from_port), + control_sequence_num_(control_sequence_num) {} + +size_t Event::GetSerializedSize() const { + return sizeof(SerializedHeader) + GetSerializedDataSize(); +} + +void Event::Serialize(void* buffer) const { + auto* header = static_cast(buffer); + header->type = type_; + header->padding = 0; + header->port_name = port_name_; + header->from_port = from_port_; + header->control_sequence_num = control_sequence_num_; + SerializeData(header + 1); +} + +ScopedEvent Event::CloneForBroadcast() const { return nullptr; } + +UserMessageEvent::~UserMessageEvent() = default; + +UserMessageEvent::UserMessageEvent(size_t num_ports) + : Event(Type::kUserMessage, kInvalidPortName, kInvalidPortName, -1) { + ReservePorts(num_ports); +} + +void UserMessageEvent::AttachMessage(mozilla::UniquePtr message) { + DCHECK(!message_); + message_ = std::move(message); +} + +void UserMessageEvent::ReservePorts(size_t num_ports) { + port_descriptors_.resize(num_ports); + ports_.resize(num_ports); +} + +bool UserMessageEvent::NotifyWillBeRoutedExternally() { + DCHECK(message_); + return message_->WillBeRoutedExternally(*this); +} + +// static +ScopedEvent UserMessageEvent::Deserialize(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(UserMessageEventData)) { + return nullptr; + } + + const auto* data = static_cast(buffer); + mozilla::CheckedInt port_data_size = data->num_ports; + port_data_size *= sizeof(PortDescriptor) + sizeof(PortName); + if (!port_data_size.isValid()) { + return nullptr; + } + + mozilla::CheckedInt total_size = port_data_size.value(); + total_size += sizeof(UserMessageEventData); + if (!total_size.isValid() || num_bytes < total_size.value()) { + return nullptr; + } + + auto event = mozilla::WrapUnique(new UserMessageEvent( + port_name, from_port, control_sequence_num, data->sequence_num)); + event->ReservePorts(data->num_ports); + const auto* in_descriptors = + reinterpret_cast(data + 1); + std::copy(in_descriptors, in_descriptors + data->num_ports, + event->port_descriptors()); + + const auto* in_names = + reinterpret_cast(in_descriptors + data->num_ports); + std::copy(in_names, in_names + data->num_ports, event->ports()); + return event; +} + +UserMessageEvent::UserMessageEvent(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + uint64_t sequence_num) + : Event(Type::kUserMessage, port_name, from_port, control_sequence_num), + sequence_num_(sequence_num) {} + +size_t UserMessageEvent::GetSizeIfSerialized() const { + if (!message_) { + return 0; + } + return message_->GetSizeIfSerialized(); +} + +size_t UserMessageEvent::GetSerializedDataSize() const { + DCHECK_EQ(ports_.size(), port_descriptors_.size()); + mozilla::CheckedInt size = sizeof(UserMessageEventData); + mozilla::CheckedInt ports_size = + sizeof(PortDescriptor) + sizeof(PortName); + ports_size *= ports_.size(); + mozilla::CheckedInt combined = size + ports_size; + MOZ_RELEASE_ASSERT(combined.isValid()); + return combined.value(); +} + +void UserMessageEvent::SerializeData(void* buffer) const { + DCHECK_EQ(ports_.size(), port_descriptors_.size()); + auto* data = static_cast(buffer); + data->sequence_num = sequence_num_; + mozilla::CheckedInt num_ports{ports_.size()}; + DCHECK(num_ports.isValid()); + data->num_ports = num_ports.value(); + data->padding = 0; + + auto* ports_data = reinterpret_cast(data + 1); + std::copy(port_descriptors_.begin(), port_descriptors_.end(), ports_data); + + auto* port_names_data = + reinterpret_cast(ports_data + ports_.size()); + std::copy(ports_.begin(), ports_.end(), port_names_data); +} + +PortAcceptedEvent::PortAcceptedEvent(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num) + : Event(Type::kPortAccepted, port_name, from_port, control_sequence_num) {} + +PortAcceptedEvent::~PortAcceptedEvent() = default; + +// static +ScopedEvent PortAcceptedEvent::Deserialize(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const void* buffer, + size_t num_bytes) { + return mozilla::MakeUnique(port_name, from_port, + control_sequence_num); +} + +size_t PortAcceptedEvent::GetSerializedDataSize() const { return 0; } + +void PortAcceptedEvent::SerializeData(void* buffer) const {} + +ObserveProxyEvent::ObserveProxyEvent(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const NodeName& proxy_node_name, + const PortName& proxy_port_name, + const NodeName& proxy_target_node_name, + const PortName& proxy_target_port_name) + : Event(Type::kObserveProxy, port_name, from_port, control_sequence_num), + proxy_node_name_(proxy_node_name), + proxy_port_name_(proxy_port_name), + proxy_target_node_name_(proxy_target_node_name), + proxy_target_port_name_(proxy_target_port_name) {} + +ObserveProxyEvent::~ObserveProxyEvent() = default; + +// static +ScopedEvent ObserveProxyEvent::Deserialize(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(ObserveProxyEventData)) { + return nullptr; + } + + const auto* data = static_cast(buffer); + return mozilla::MakeUnique( + port_name, from_port, control_sequence_num, data->proxy_node_name, + data->proxy_port_name, data->proxy_target_node_name, + data->proxy_target_port_name); +} + +size_t ObserveProxyEvent::GetSerializedDataSize() const { + return sizeof(ObserveProxyEventData); +} + +void ObserveProxyEvent::SerializeData(void* buffer) const { + auto* data = static_cast(buffer); + data->proxy_node_name = proxy_node_name_; + data->proxy_port_name = proxy_port_name_; + data->proxy_target_node_name = proxy_target_node_name_; + data->proxy_target_port_name = proxy_target_port_name_; +} + +ScopedEvent ObserveProxyEvent::CloneForBroadcast() const { + // Don't broadcast events targeted at specific ports. Otherwise a malicious + // node can use this to bypass sender verification. + if (port_name() != kInvalidPortName) { + return nullptr; + } + return mozilla::MakeUnique( + port_name(), from_port(), control_sequence_num(), proxy_node_name_, + proxy_port_name_, proxy_target_node_name_, proxy_target_port_name_); +} + +ObserveProxyAckEvent::ObserveProxyAckEvent(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + uint64_t last_sequence_num) + : Event(Type::kObserveProxyAck, port_name, from_port, control_sequence_num), + last_sequence_num_(last_sequence_num) {} + +ObserveProxyAckEvent::~ObserveProxyAckEvent() = default; + +// static +ScopedEvent ObserveProxyAckEvent::Deserialize(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(ObserveProxyAckEventData)) { + return nullptr; + } + + const auto* data = static_cast(buffer); + return mozilla::MakeUnique( + port_name, from_port, control_sequence_num, data->last_sequence_num); +} + +size_t ObserveProxyAckEvent::GetSerializedDataSize() const { + return sizeof(ObserveProxyAckEventData); +} + +void ObserveProxyAckEvent::SerializeData(void* buffer) const { + auto* data = static_cast(buffer); + data->last_sequence_num = last_sequence_num_; +} + +ObserveClosureEvent::ObserveClosureEvent(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + uint64_t last_sequence_num) + : Event(Type::kObserveClosure, port_name, from_port, control_sequence_num), + last_sequence_num_(last_sequence_num) {} + +ObserveClosureEvent::~ObserveClosureEvent() = default; + +// static +ScopedEvent ObserveClosureEvent::Deserialize(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(ObserveClosureEventData)) { + return nullptr; + } + + const auto* data = static_cast(buffer); + return mozilla::MakeUnique( + port_name, from_port, control_sequence_num, data->last_sequence_num); +} + +size_t ObserveClosureEvent::GetSerializedDataSize() const { + return sizeof(ObserveClosureEventData); +} + +void ObserveClosureEvent::SerializeData(void* buffer) const { + auto* data = static_cast(buffer); + data->last_sequence_num = last_sequence_num_; +} + +MergePortEvent::MergePortEvent(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const PortName& new_port_name, + const PortDescriptor& new_port_descriptor) + : Event(Type::kMergePort, port_name, from_port, control_sequence_num), + new_port_name_(new_port_name), + new_port_descriptor_(new_port_descriptor) {} + +MergePortEvent::~MergePortEvent() = default; + +// static +ScopedEvent MergePortEvent::Deserialize(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const void* buffer, size_t num_bytes) { + if (num_bytes < sizeof(MergePortEventData)) { + return nullptr; + } + + const auto* data = static_cast(buffer); + return mozilla::MakeUnique( + port_name, from_port, control_sequence_num, data->new_port_name, + data->new_port_descriptor); +} + +size_t MergePortEvent::GetSerializedDataSize() const { + return sizeof(MergePortEventData); +} + +void MergePortEvent::SerializeData(void* buffer) const { + auto* data = static_cast(buffer); + data->new_port_name = new_port_name_; + data->new_port_descriptor = new_port_descriptor_; +} + +UserMessageReadAckRequestEvent::UserMessageReadAckRequestEvent( + const PortName& port_name, const PortName& from_port, + uint64_t control_sequence_num, uint64_t sequence_num_to_acknowledge) + : Event(Type::kUserMessageReadAckRequest, port_name, from_port, + control_sequence_num), + sequence_num_to_acknowledge_(sequence_num_to_acknowledge) {} + +UserMessageReadAckRequestEvent::~UserMessageReadAckRequestEvent() = default; + +// static +ScopedEvent UserMessageReadAckRequestEvent::Deserialize( + const PortName& port_name, const PortName& from_port, + uint64_t control_sequence_num, const void* buffer, size_t num_bytes) { + if (num_bytes < sizeof(UserMessageReadAckRequestEventData)) { + return nullptr; + } + + const auto* data = + static_cast(buffer); + return mozilla::MakeUnique( + port_name, from_port, control_sequence_num, + data->sequence_num_to_acknowledge); +} + +size_t UserMessageReadAckRequestEvent::GetSerializedDataSize() const { + return sizeof(UserMessageReadAckRequestEventData); +} + +void UserMessageReadAckRequestEvent::SerializeData(void* buffer) const { + auto* data = static_cast(buffer); + data->sequence_num_to_acknowledge = sequence_num_to_acknowledge_; +} + +UserMessageReadAckEvent::UserMessageReadAckEvent( + const PortName& port_name, const PortName& from_port, + uint64_t control_sequence_num, uint64_t sequence_num_acknowledged) + : Event(Type::kUserMessageReadAck, port_name, from_port, + control_sequence_num), + sequence_num_acknowledged_(sequence_num_acknowledged) {} + +UserMessageReadAckEvent::~UserMessageReadAckEvent() = default; + +// static +ScopedEvent UserMessageReadAckEvent::Deserialize(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(UserMessageReadAckEventData)) { + return nullptr; + } + + const auto* data = static_cast(buffer); + return mozilla::MakeUnique( + port_name, from_port, control_sequence_num, + data->sequence_num_acknowledged); +} + +size_t UserMessageReadAckEvent::GetSerializedDataSize() const { + return sizeof(UserMessageReadAckEventData); +} + +void UserMessageReadAckEvent::SerializeData(void* buffer) const { + auto* data = static_cast(buffer); + data->sequence_num_acknowledged = sequence_num_acknowledged_; +} + +UpdatePreviousPeerEvent::UpdatePreviousPeerEvent(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const NodeName& new_node_name, + const PortName& new_port_name) + : Event(Type::kUpdatePreviousPeer, port_name, from_port, + control_sequence_num), + new_node_name_(new_node_name), + new_port_name_(new_port_name) {} + +UpdatePreviousPeerEvent::~UpdatePreviousPeerEvent() = default; + +// static +ScopedEvent UpdatePreviousPeerEvent::Deserialize(const PortName& port_name, + const PortName& from_port, + uint64_t control_sequence_num, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(UpdatePreviousPeerEventData)) return nullptr; + const auto* data = static_cast(buffer); + return mozilla::MakeUnique( + port_name, from_port, control_sequence_num, data->new_node_name, + data->new_port_name); +} + +size_t UpdatePreviousPeerEvent::GetSerializedDataSize() const { + return sizeof(UpdatePreviousPeerEventData); +} + +void UpdatePreviousPeerEvent::SerializeData(void* buffer) const { + auto* data = static_cast(buffer); + data->new_node_name = new_node_name_; + data->new_port_name = new_port_name_; +} + +} // namespace ports +} // namespace core +} // namespace mojo -- cgit v1.2.3