1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
mojo / core / ipcz_driver / transport.h [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_CORE_IPCZ_DRIVER_TRANSPORT_H_
#define MOJO_CORE_IPCZ_DRIVER_TRANSPORT_H_
#include <cstddef>
#include <cstdint>
#include <utility>
#include "base/check.h"
#include "base/containers/span.h"
#include "base/memory/scoped_refptr.h"
#include "base/process/process.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "mojo/core/channel.h"
#include "mojo/core/ipcz_driver/object.h"
#include "mojo/core/system_impl_export.h"
#include "mojo/public/c/system/invitation.h"
#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
#include "mojo/public/cpp/platform/platform_handle.h"
#include "third_party/ipcz/include/ipcz/ipcz.h"
namespace mojo::core::ipcz_driver {
// An ipcz driver transport implementation backed by a Channel object.
class MOJO_SYSTEM_IMPL_EXPORT Transport : public Object<Transport>,
public Channel::Delegate {
public:
// Enumerates the type of node at local endpoint of a Transport object.
enum EndpointType : uint32_t {
kBroker,
kNonBroker,
};
struct EndpointTypes {
EndpointType source;
EndpointType destination;
};
Transport(EndpointTypes endpoint_types,
PlatformChannelEndpoint endpoint,
base::Process remote_process,
bool is_remote_process_untrusted = false);
// Static helper that is slightly more readable due to better type deduction
// than MakeRefCounted<T>.
static scoped_refptr<Transport> Create(
EndpointTypes endpoint_types,
PlatformChannelEndpoint endpoint,
base::Process remote_process = base::Process(),
bool is_remote_process_untrusted = false);
static std::pair<scoped_refptr<Transport>, scoped_refptr<Transport>>
CreatePair(EndpointType first_type, EndpointType second_type);
// Accessors for a global TaskRunner to use for Transport I/O.
static void SetIOTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> runner);
static const scoped_refptr<base::SingleThreadTaskRunner>& GetIOTaskRunner();
static constexpr Type object_type() { return kTransport; }
EndpointType source_type() const { return endpoint_types_.source; }
EndpointType destination_type() const { return endpoint_types_.destination; }
const base::Process& remote_process() const { return remote_process_; }
// Provides a handle to the remote process on the other end of this transport.
// If this is called, it must be before the Transport is activated.
void set_remote_process(base::Process process) {
DCHECK(!remote_process_.IsValid());
remote_process_ = std::move(process);
}
void set_leak_channel_on_shutdown(bool leak) {
leak_channel_on_shutdown_ = leak;
}
void set_is_peer_trusted(bool trusted) { is_peer_trusted_ = trusted; }
bool is_peer_trusted() const { return is_peer_trusted_; }
void set_is_trusted_by_peer(bool trusted) { is_trusted_by_peer_ = trusted; }
bool is_trusted_by_peer() const { return is_trusted_by_peer_; }
void SetErrorHandler(MojoProcessErrorHandler handler, uintptr_t context) {
error_handler_ = handler;
error_handler_context_ = context;
}
// Overrides the IO task runner used to monitor this transport for IO. Unless
// this is called, all Transports use the global IO task runner by default.
void OverrideIOTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
// Takes ownership of the Transport's underlying channel endpoint, effectively
// invalidating the transport. May only be called on a Transport which has not
// yet been activated, and only when the channel endpoint is not a server.
PlatformChannelEndpoint TakeEndpoint() {
return std::move(inactive_endpoint_);
}
// Handles reports of bad activity from ipcz, resulting from parcel rejection
// by the application.
void ReportBadActivity(const std::string& error_message);
// Activates this transport by creating and starting the underlying Channel
// instance.
bool Activate(IpczHandle transport,
IpczTransportActivityHandler activity_handler);
// Deactives this transport, release and calling ShutDown() on the underlying
// Channel. Channel shutdown is asynchronous and will conclude with an
// OnChannelDestroyed() invocation on this Transport.
bool Deactivate();
// Transmits `data` and `handles` over the underlying Channel. All handles in
// `handles` must reference TransmissibleHandle instances with an underlying
// handle the Channel can transmit out-of-band from `data`.
bool Transmit(base::span<const uint8_t> data,
base::span<const IpczDriverHandle> handles);
// Attempts to serialize `object` for eventual transmission over this
// Transport. This essentially implements the mojo-ipcz driver's Serialize()
// API and behaves according to its specification. Upon success, `object` may
// be invalidated.
IpczResult SerializeObject(ObjectBase& object,
void* data,
size_t* num_bytes,
IpczDriverHandle* handles,
size_t* num_handles);
// Deserializes a new driver object from `bytes` and `handles` received over
// this Transport.
IpczResult DeserializeObject(base::span<const uint8_t> bytes,
base::span<const IpczDriverHandle> handles,
scoped_refptr<ObjectBase>& object);
// Object:
void Close() override;
bool IsSerializable() const override;
bool GetSerializedDimensions(Transport& transmitter,
size_t& num_bytes,
size_t& num_handles) override;
bool Serialize(Transport& transmitter,
base::span<uint8_t> data,
base::span<PlatformHandle> handles) override;
static scoped_refptr<Transport> Deserialize(
Transport& from_transport,
base::span<const uint8_t> data,
base::span<PlatformHandle> handles);
// Channel::Delegate:
bool IsIpczTransport() const override;
void OnChannelMessage(const void* payload,
size_t payload_size,
std::vector<PlatformHandle> handles,
scoped_refptr<ipcz_driver::Envelope> envelope) override;
void OnChannelError(Channel::Error error) override;
void OnChannelDestroyed() override;
private:
struct PendingTransmission {
PendingTransmission();
PendingTransmission(PendingTransmission&&);
PendingTransmission& operator=(PendingTransmission&&);
~PendingTransmission();
std::vector<uint8_t> bytes;
std::vector<PlatformHandle> handles;
};
~Transport() override;
bool CanTransmitHandles() const;
// Indicates whether this transport should serialize its remote process handle
// along with its endpoint handle being serialized for transmission over
// `transmitter`. This must only be true if we have a valid remote process
// handle and `transmitter` goes to a broker. Always false on non-Windows
// platforms.
bool ShouldSerializeProcessHandle(Transport& transmitter) const;
const EndpointTypes endpoint_types_;
base::Process remote_process_;
MojoProcessErrorHandler error_handler_ = nullptr;
uintptr_t error_handler_context_ = 0;
bool leak_channel_on_shutdown_ = false;
// Indicates whether the remote transport endpoint is "trusted" by this
// endpoint. In practice this means we will accept pre-duplicated handles from
// the remote process on Windows. This bit is ignored if the remote endpoint
// is a broker, since brokers are implicitly trusted; and it's currently
// meaningless on platforms other than Windows.
bool is_peer_trusted_ = false;
// Indicates whether this endpoint is "trusted" by the remote endpoint.
// In practice this means the remote endpoint will accept pre-duplicated
// handles from us on Windows. This bit is ignored if the local endpoint is a
// broker, since brokers are implicitly trusted; and it's currently
// meaningless on platforms other than Windows.
bool is_trusted_by_peer_ = false;
#if BUILDFLAG(IS_WIN)
// Indicates whether the remote process is "untrusted" in Mojo parlance,
// meaning this Transport restricts what kinds of objects can be transferred
// from this end (Windows only.)
bool is_remote_process_untrusted_;
#endif
// The channel endpoint which will be used by this Transport to construct and
// start its underlying Channel instance once activated. Not guarded by a lock
// since it must not accessed beyond activation, where thread safety becomes a
// factor.
PlatformChannelEndpoint inactive_endpoint_;
base::Lock lock_;
scoped_refptr<Channel> channel_ GUARDED_BY(lock_);
// Transmissions prior to activation must be queued, as the Channel is not
// created until then. Queued messages are stored here. Once the Transport has
// been activated, this is no longer used.
std::vector<PendingTransmission> pending_transmissions_ GUARDED_BY(lock_);
// NOTE: Channel does not retain a reference to its Delegate (this Transport,
// in our case) and it may call back into us from any thread as long as it's
// still alive. So we retain a self-reference on behalf of the Channel and
// release it only once notified of the Channel's destruction.
//
// TODO(crbug.com/40058840): Refactor Channel so that this is
// unnecessary, once the non-ipcz Mojo implementation is phased out.
scoped_refptr<Transport> self_reference_for_channel_ GUARDED_BY(lock_);
// The IO task runner used by this Transport to watch for incoming I/O events.
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_{
GetIOTaskRunner()};
// These fields are not guarded by locks, since they're only set prior to
// activation and remain constant throughout the remainder of this object's
// lifetime.
IpczHandle ipcz_transport_ = IPCZ_INVALID_HANDLE;
IpczTransportActivityHandler activity_handler_ = nullptr;
};
} // namespace mojo::core::ipcz_driver
#endif // MOJO_CORE_IPCZ_DRIVER_TRANSPORT_H_