1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_
18 #define INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_
19
20 #include <stdint.h>
21 #include <sys/types.h>
22
23 #include <memory>
24 #include <string>
25 #include <utility>
26
27 #include "perfetto/base/build_config.h"
28 #include "perfetto/base/compiler.h"
29 #include "perfetto/base/export.h"
30 #include "perfetto/base/logging.h"
31 #include "perfetto/base/platform_handle.h"
32 #include "perfetto/ext/base/scoped_file.h"
33 #include "perfetto/ext/base/utils.h"
34 #include "perfetto/ext/base/weak_ptr.h"
35
36 struct msghdr;
37
38 namespace perfetto {
39 namespace base {
40
41 // Define the ScopedSocketHandle type.
42
43 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
44 int CloseSocket(SocketHandle); // A wrapper around ::closesocket().
45 using ScopedSocketHandle =
46 ScopedResource<SocketHandle, CloseSocket, static_cast<SocketHandle>(-1)>;
47 #else
48 using ScopedSocketHandle = ScopedFile;
49 #endif
50
51 class TaskRunner;
52
53 // Use arbitrarily high values to avoid that some code accidentally ends up
54 // assuming that these enum values match the sysroot's SOCK_xxx defines rather
55 // than using MkSockType() / MkSockFamily().
56 enum class SockType { kStream = 100, kDgram, kSeqPacket };
57 enum class SockFamily { kUnspec = 0, kUnix = 200, kInet, kInet6, kVsock };
58
59 // Controls the getsockopt(SO_PEERCRED) behavior, which allows to obtain the
60 // peer credentials.
61 enum class SockPeerCredMode {
62 // Obtain the peer credentials immediately after connection and cache them.
63 kReadOnConnect = 0,
64
65 // Don't read peer credentials at all. Calls to peer_uid()/peer_pid() will
66 // hit a DCHECK and return kInvalidUid/Pid in release builds.
67 kIgnore = 1,
68
69 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || \
70 PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
71 kDefault = kIgnore,
72 #else
73 kDefault = kReadOnConnect,
74 #endif
75 };
76
77 // Returns the socket family from the full addres that perfetto uses.
78 // Addr can be:
79 // - /path/to/socket : for linked AF_UNIX sockets.
80 // - @abstract_name : for abstract AF_UNIX sockets.
81 // - 1.2.3.4:8080 : for Inet sockets.
82 // - [::1]:8080 : for Inet6 sockets.
83 // - vsock://-1:3000 : for VM sockets.
84 SockFamily GetSockFamily(const char* addr);
85
86 // Returns whether inter-process shared memory is supported for the socket.
SockShmemSupported(SockFamily sock_family)87 inline bool SockShmemSupported(SockFamily sock_family) {
88 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
89 return sock_family == SockFamily::kUnix;
90 #else
91 base::ignore_result(sock_family);
92 // On Windows shm is negotiated by sharing an unguessable token
93 // over TCP sockets. In theory works on any socket type, in practice
94 // we need to tell the difference between a local and a remote
95 // connection. For now we assume everything is local.
96 // See comments on r.android.com/2951909 .
97 return true;
98 #endif
99 }
SockShmemSupported(const char * addr)100 inline bool SockShmemSupported(const char* addr) {
101 return SockShmemSupported(GetSockFamily(addr));
102 }
103
104 // UnixSocketRaw is a basic wrapper around sockets. It exposes wrapper
105 // methods that take care of most common pitfalls (e.g., marking fd as
106 // O_CLOEXEC, avoiding SIGPIPE, properly handling partial writes). It is used as
107 // a building block for the more sophisticated UnixSocket class which depends
108 // on base::TaskRunner.
109 class UnixSocketRaw {
110 public:
111 // Creates a new unconnected unix socket.
112 static UnixSocketRaw CreateMayFail(SockFamily family, SockType type);
113
114 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
115 // Crates a pair of connected sockets.
116 static std::pair<UnixSocketRaw, UnixSocketRaw> CreatePairPosix(SockFamily,
117 SockType);
118 #endif
119
120 // Creates an uninitialized unix socket.
121 UnixSocketRaw();
122
123 // Creates a unix socket adopting an existing file descriptor. This is
124 // typically used to inherit fds from init via environment variables.
125 UnixSocketRaw(ScopedSocketHandle, SockFamily, SockType);
126
127 ~UnixSocketRaw() = default;
128 UnixSocketRaw(UnixSocketRaw&&) noexcept = default;
129 UnixSocketRaw& operator=(UnixSocketRaw&&) = default;
130
131 bool Bind(const std::string& socket_name);
132 bool Listen();
133 bool Connect(const std::string& socket_name);
134 bool SetTxTimeout(uint32_t timeout_ms);
135 bool SetRxTimeout(uint32_t timeout_ms);
136 void Shutdown();
137 void SetBlocking(bool);
138 void DcheckIsBlocking(bool expected) const; // No-op on release and Win.
139 void SetRetainOnExec(bool retain);
140 std::string GetSockAddr() const;
type()141 SockType type() const { return type_; }
family()142 SockFamily family() const { return family_; }
fd()143 SocketHandle fd() const { return *fd_; }
144 explicit operator bool() const { return !!fd_; }
145
146 // This is the handle that passed to TaskRunner.AddFileDescriptorWatch().
147 // On UNIX this is just the socket FD. On Windows, we need to create a
148 // dedicated event object.
watch_handle()149 PlatformHandle watch_handle() const {
150 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
151 return *event_handle_;
152 #else
153 return *fd_;
154 #endif
155 }
156
ReleaseFd()157 ScopedSocketHandle ReleaseFd() { return std::move(fd_); }
158
159 // |send_fds| and |num_fds| are ignored on Windows.
160 ssize_t Send(const void* msg,
161 size_t len,
162 const int* send_fds = nullptr,
163 size_t num_fds = 0);
164
SendStr(const std::string & str)165 ssize_t SendStr(const std::string& str) {
166 return Send(str.data(), str.size());
167 }
168
169 // |fd_vec| and |max_files| are ignored on Windows.
170 ssize_t Receive(void* msg,
171 size_t len,
172 ScopedFile* fd_vec = nullptr,
173 size_t max_files = 0);
174
175 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
176 // UNIX-specific helpers to deal with SCM_RIGHTS.
177
178 // Re-enter sendmsg until all the data has been sent or an error occurs.
179 // TODO(fmayer): Figure out how to do timeouts here for heapprofd.
180 ssize_t SendMsgAllPosix(struct msghdr* msg);
181
182 // Exposed for testing only.
183 // Update msghdr so subsequent sendmsg will send data that remains after n
184 // bytes have already been sent.
185 static void ShiftMsgHdrPosix(size_t n, struct msghdr* msg);
186 #endif
187
188 private:
189 UnixSocketRaw(SockFamily, SockType);
190
191 UnixSocketRaw(const UnixSocketRaw&) = delete;
192 UnixSocketRaw& operator=(const UnixSocketRaw&) = delete;
193
194 ScopedSocketHandle fd_;
195 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
196 ScopedPlatformHandle event_handle_;
197 #endif
198 SockFamily family_ = SockFamily::kUnix;
199 SockType type_ = SockType::kStream;
200 uint32_t tx_timeout_ms_ = 0;
201 };
202
203 // A non-blocking UNIX domain socket. Allows also to transfer file descriptors.
204 // None of the methods in this class are blocking.
205 // The main design goal is making strong guarantees on the EventListener
206 // callbacks, in order to avoid ending in some undefined state.
207 // In case of any error it will aggressively just shut down the socket and
208 // notify the failure with OnConnect(false) or OnDisconnect() depending on the
209 // state of the socket (see below).
210 // EventListener callbacks stop happening as soon as the instance is destroyed.
211 //
212 // Lifecycle of a client socket:
213 //
214 // Connect()
215 // |
216 // +------------------+------------------+
217 // | (success) | (failure or Shutdown())
218 // V V
219 // OnConnect(true) OnConnect(false)
220 // |
221 // V
222 // OnDataAvailable()
223 // |
224 // V
225 // OnDisconnect() (failure or shutdown)
226 //
227 //
228 // Lifecycle of a server socket:
229 //
230 // Listen() --> returns false in case of errors.
231 // |
232 // V
233 // OnNewIncomingConnection(new_socket)
234 //
235 // (|new_socket| inherits the same EventListener)
236 // |
237 // V
238 // OnDataAvailable()
239 // | (failure or Shutdown())
240 // V
241 // OnDisconnect()
242 class PERFETTO_EXPORT_COMPONENT UnixSocket {
243 public:
244 class EventListener {
245 public:
246 EventListener() = default;
247 virtual ~EventListener();
248
249 EventListener(const EventListener&) = delete;
250 EventListener& operator=(const EventListener&) = delete;
251
252 EventListener(EventListener&&) noexcept = default;
253 EventListener& operator=(EventListener&&) noexcept = default;
254
255 // After Listen().
256 // |self| may be null if the connection was not accepted via a listen
257 // socket.
258 virtual void OnNewIncomingConnection(
259 UnixSocket* self,
260 std::unique_ptr<UnixSocket> new_connection);
261
262 // After Connect(), whether successful or not.
263 virtual void OnConnect(UnixSocket* self, bool connected);
264
265 // After a successful Connect() or OnNewIncomingConnection(). Either the
266 // other endpoint did disconnect or some other error happened.
267 virtual void OnDisconnect(UnixSocket* self);
268
269 // Whenever there is data available to Receive(). Note that spurious FD
270 // watch events are possible, so it is possible that Receive() soon after
271 // OnDataAvailable() returns 0 (just ignore those).
272 virtual void OnDataAvailable(UnixSocket* self);
273 };
274
275 enum class State {
276 kDisconnected = 0, // Failed connection, peer disconnection or Shutdown().
277 kConnecting, // Soon after Connect(), before it either succeeds or fails.
278 kConnected, // After a successful Connect().
279 kListening // After Listen(), until Shutdown().
280 };
281
282 // Creates a socket and starts listening. If SockFamily::kUnix and
283 // |socket_name| starts with a '@', an abstract UNIX dmoain socket will be
284 // created instead of a filesystem-linked UNIX socket (Linux/Android only).
285 // If SockFamily::kInet, |socket_name| is host:port (e.g., "1.2.3.4:8000").
286 // If SockFamily::kInet6, |socket_name| is [host]:port (e.g., "[::1]:8000").
287 // Returns nullptr if the socket creation or bind fails. If listening fails,
288 // (e.g. if another socket with the same name is already listening) the
289 // returned socket will have is_listening() == false.
290 static std::unique_ptr<UnixSocket> Listen(const std::string& socket_name,
291 EventListener*,
292 TaskRunner*,
293 SockFamily,
294 SockType);
295
296 // Attaches to a pre-existing socket. The socket must have been created in
297 // SOCK_STREAM mode and the caller must have called bind() on it.
298 static std::unique_ptr<UnixSocket> Listen(ScopedSocketHandle,
299 EventListener*,
300 TaskRunner*,
301 SockFamily,
302 SockType);
303
304 // Creates a Unix domain socket and connects to the listening endpoint.
305 // Returns always an instance. EventListener::OnConnect(bool success) will
306 // be called always, whether the connection succeeded or not.
307 static std::unique_ptr<UnixSocket> Connect(
308 const std::string& socket_name,
309 EventListener*,
310 TaskRunner*,
311 SockFamily,
312 SockType,
313 SockPeerCredMode = SockPeerCredMode::kDefault);
314
315 // Constructs a UnixSocket using the given connected socket.
316 static std::unique_ptr<UnixSocket> AdoptConnected(
317 ScopedSocketHandle,
318 EventListener*,
319 TaskRunner*,
320 SockFamily,
321 SockType,
322 SockPeerCredMode = SockPeerCredMode::kDefault);
323
324 UnixSocket(const UnixSocket&) = delete;
325 UnixSocket& operator=(const UnixSocket&) = delete;
326 // Cannot be easily moved because of tasks from the FileDescriptorWatch.
327 UnixSocket(UnixSocket&&) = delete;
328 UnixSocket& operator=(UnixSocket&&) = delete;
329
330 // This class gives the hard guarantee that no callback is called on the
331 // passed EventListener immediately after the object has been destroyed.
332 // Any queued callback will be silently dropped.
333 ~UnixSocket();
334
335 // Shuts down the current connection, if any. If the socket was Listen()-ing,
336 // stops listening. The socket goes back to kNotInitialized state, so it can
337 // be reused with Listen() or Connect().
338 void Shutdown(bool notify);
339
SetTxTimeout(uint32_t timeout_ms)340 void SetTxTimeout(uint32_t timeout_ms) {
341 PERFETTO_CHECK(sock_raw_.SetTxTimeout(timeout_ms));
342 }
SetRxTimeout(uint32_t timeout_ms)343 void SetRxTimeout(uint32_t timeout_ms) {
344 PERFETTO_CHECK(sock_raw_.SetRxTimeout(timeout_ms));
345 }
346
GetSockAddr()347 std::string GetSockAddr() const { return sock_raw_.GetSockAddr(); }
348
349 // Returns true is the message was queued, false if there was no space in the
350 // output buffer, in which case the client should retry or give up.
351 // If any other error happens the socket will be shutdown and
352 // EventListener::OnDisconnect() will be called.
353 // If the socket is not connected, Send() will just return false.
354 // Does not append a null string terminator to msg in any case.
355 bool Send(const void* msg, size_t len, const int* send_fds, size_t num_fds);
356
357 inline bool Send(const void* msg, size_t len, int send_fd = -1) {
358 if (send_fd != -1)
359 return Send(msg, len, &send_fd, 1);
360 return Send(msg, len, nullptr, 0);
361 }
362
SendStr(const std::string & msg)363 inline bool SendStr(const std::string& msg) {
364 return Send(msg.data(), msg.size(), -1);
365 }
366
367 // Returns the number of bytes (<= |len|) written in |msg| or 0 if there
368 // is no data in the buffer to read or an error occurs (in which case a
369 // EventListener::OnDisconnect() will follow).
370 // If the ScopedFile pointer is not null and a FD is received, it moves the
371 // received FD into that. If a FD is received but the ScopedFile pointer is
372 // null, the FD will be automatically closed.
373 size_t Receive(void* msg, size_t len, ScopedFile*, size_t max_files = 1);
374
Receive(void * msg,size_t len)375 inline size_t Receive(void* msg, size_t len) {
376 return Receive(msg, len, nullptr, 0);
377 }
378
379 // Only for tests. This is slower than Receive() as it requires a heap
380 // allocation and a copy for the std::string. Guarantees that the returned
381 // string is null terminated even if the underlying message sent by the peer
382 // is not.
383 std::string ReceiveString(size_t max_length = 1024);
384
is_connected()385 bool is_connected() const { return state_ == State::kConnected; }
is_listening()386 bool is_listening() const { return state_ == State::kListening; }
fd()387 SocketHandle fd() const { return sock_raw_.fd(); }
family()388 SockFamily family() const { return sock_raw_.family(); }
389
390 // User ID of the peer, as returned by the kernel. If the client disconnects
391 // and the socket goes into the kDisconnected state, it retains the uid of
392 // the last peer.
393 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
394 !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
395 uid_t peer_uid_posix(bool skip_check_for_testing = false) const {
396 PERFETTO_DCHECK((!is_listening() && peer_uid_ != kInvalidUid) ||
397 skip_check_for_testing);
398
399 return peer_uid_;
400 }
401 #endif
402
403 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX_BUT_NOT_QNX) || \
404 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
405 // Process ID of the peer, as returned by the kernel. If the client
406 // disconnects and the socket goes into the kDisconnected state, it
407 // retains the pid of the last peer.
408 //
409 // This is only available on Linux / Android.
410 pid_t peer_pid_linux(bool skip_check_for_testing = false) const {
411 PERFETTO_DCHECK((!is_listening() && peer_pid_ != kInvalidPid) ||
412 skip_check_for_testing);
413 return peer_pid_;
414 }
415 #endif
416
417 // This makes the UnixSocket unusable.
418 UnixSocketRaw ReleaseSocket();
419
420 private:
421 UnixSocket(EventListener*,
422 TaskRunner*,
423 SockFamily,
424 SockType,
425 SockPeerCredMode);
426 UnixSocket(EventListener*,
427 TaskRunner*,
428 ScopedSocketHandle,
429 State,
430 SockFamily,
431 SockType,
432 SockPeerCredMode);
433
434 // Called once by the corresponding public static factory methods.
435 void DoConnect(const std::string& socket_name);
436
437 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
438 void ReadPeerCredentialsPosix();
439 #endif
440
441 void OnEvent();
442 void NotifyConnectionState(bool success);
443
444 UnixSocketRaw sock_raw_;
445 State state_ = State::kDisconnected;
446 SockPeerCredMode peer_cred_mode_ = SockPeerCredMode::kDefault;
447
448 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
449 !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
450 uid_t peer_uid_ = kInvalidUid;
451 #endif
452 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
453 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
454 pid_t peer_pid_ = kInvalidPid;
455 #endif
456 EventListener* const event_listener_;
457 TaskRunner* const task_runner_;
458 WeakPtrFactory<UnixSocket> weak_ptr_factory_; // Keep last.
459 };
460
461 } // namespace base
462 } // namespace perfetto
463
464 #endif // INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_
465