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 #include "perfetto/ext/base/unix_socket.h"
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include "perfetto/base/compiler.h"
26
27 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
28 // The include order matters on these three Windows header groups.
29 #include <Windows.h>
30
31 #include <WS2tcpip.h>
32 #include <WinSock2.h>
33
34 #include <afunix.h>
35 #else
36 #include <netdb.h>
37 #include <netinet/in.h>
38 #include <netinet/tcp.h>
39 #include <poll.h>
40 #include <sys/socket.h>
41 #include <sys/un.h>
42 #include <unistd.h>
43 #endif
44
45 #if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
46 #include <sys/ucred.h>
47 #endif
48
49 #include <algorithm>
50 #include <memory>
51
52 #include "perfetto/base/build_config.h"
53 #include "perfetto/base/logging.h"
54 #include "perfetto/base/task_runner.h"
55 #include "perfetto/base/time.h"
56 #include "perfetto/ext/base/string_utils.h"
57 #include "perfetto/ext/base/utils.h"
58
59 namespace perfetto {
60 namespace base {
61
62 // The CMSG_* macros use NULL instead of nullptr.
63 // Note: MSVC doesn't have #pragma GCC diagnostic, hence the if __GNUC__.
64 #if defined(__GNUC__) && !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
65 #pragma GCC diagnostic push
66 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
67 #endif
68
69 namespace {
70
71 // Android takes an int instead of socklen_t for the control buffer size.
72 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
73 using CBufLenType = size_t;
74 #else
75 using CBufLenType = socklen_t;
76 #endif
77
78 // A wrapper around variable-size sockaddr structs.
79 // This is solving the following problem: when calling connect() or bind(), the
80 // caller needs to take care to allocate the right struct (sockaddr_un for
81 // AF_UNIX, sockaddr_in for AF_INET). Those structs have different sizes and,
82 // more importantly, are bigger than the base struct sockaddr.
83 struct SockaddrAny {
SockaddrAnyperfetto::base::__anonea88cbd60111::SockaddrAny84 SockaddrAny() : size() {}
SockaddrAnyperfetto::base::__anonea88cbd60111::SockaddrAny85 SockaddrAny(const void* addr, socklen_t sz)
86 : data(new char[static_cast<size_t>(sz)]), size(sz) {
87 memcpy(data.get(), addr, static_cast<size_t>(size));
88 }
89
addrperfetto::base::__anonea88cbd60111::SockaddrAny90 const struct sockaddr* addr() const {
91 return reinterpret_cast<const struct sockaddr*>(data.get());
92 }
93
94 std::unique_ptr<char[]> data;
95 socklen_t size;
96 };
97
GetSockFamily(SockFamily family)98 inline int GetSockFamily(SockFamily family) {
99 switch (family) {
100 case SockFamily::kUnix:
101 return AF_UNIX;
102 case SockFamily::kInet:
103 return AF_INET;
104 case SockFamily::kInet6:
105 return AF_INET6;
106 }
107 PERFETTO_CHECK(false); // For GCC.
108 }
109
GetSockType(SockType type)110 inline int GetSockType(SockType type) {
111 #ifdef SOCK_CLOEXEC
112 constexpr int kSockCloExec = SOCK_CLOEXEC;
113 #else
114 constexpr int kSockCloExec = 0;
115 #endif
116 switch (type) {
117 case SockType::kStream:
118 return SOCK_STREAM | kSockCloExec;
119 case SockType::kDgram:
120 return SOCK_DGRAM | kSockCloExec;
121 case SockType::kSeqPacket:
122 return SOCK_SEQPACKET | kSockCloExec;
123 }
124 PERFETTO_CHECK(false); // For GCC.
125 }
126
MakeSockAddr(SockFamily family,const std::string & socket_name)127 SockaddrAny MakeSockAddr(SockFamily family, const std::string& socket_name) {
128 switch (family) {
129 case SockFamily::kUnix: {
130 struct sockaddr_un saddr {};
131 const size_t name_len = socket_name.size();
132 if (name_len >= sizeof(saddr.sun_path)) {
133 errno = ENAMETOOLONG;
134 return SockaddrAny();
135 }
136 memcpy(saddr.sun_path, socket_name.data(), name_len);
137 if (saddr.sun_path[0] == '@') {
138 saddr.sun_path[0] = '\0';
139 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
140 // The MSDN blog claims that abstract (non-filesystem based) AF_UNIX
141 // socket are supported, but that doesn't seem true.
142 PERFETTO_ELOG(
143 "Abstract AF_UNIX sockets are not supported on Windows, see "
144 "https://github.com/microsoft/WSL/issues/4240");
145 return SockaddrAny{};
146 #endif
147 }
148 saddr.sun_family = AF_UNIX;
149 auto size = static_cast<socklen_t>(
150 __builtin_offsetof(sockaddr_un, sun_path) + name_len + 1);
151 PERFETTO_CHECK(static_cast<size_t>(size) <= sizeof(saddr));
152 return SockaddrAny(&saddr, size);
153 }
154 case SockFamily::kInet: {
155 auto parts = SplitString(socket_name, ":");
156 PERFETTO_CHECK(parts.size() == 2);
157 struct addrinfo* addr_info = nullptr;
158 struct addrinfo hints {};
159 hints.ai_family = AF_INET;
160 PERFETTO_CHECK(getaddrinfo(parts[0].c_str(), parts[1].c_str(), &hints,
161 &addr_info) == 0);
162 PERFETTO_CHECK(addr_info->ai_family == AF_INET);
163 SockaddrAny res(addr_info->ai_addr,
164 static_cast<socklen_t>(addr_info->ai_addrlen));
165 freeaddrinfo(addr_info);
166 return res;
167 }
168 case SockFamily::kInet6: {
169 auto parts = SplitString(socket_name, "]");
170 PERFETTO_CHECK(parts.size() == 2);
171 auto address = SplitString(parts[0], "[");
172 PERFETTO_CHECK(address.size() == 1);
173 auto port = SplitString(parts[1], ":");
174 PERFETTO_CHECK(port.size() == 1);
175 struct addrinfo* addr_info = nullptr;
176 struct addrinfo hints {};
177 hints.ai_family = AF_INET6;
178 PERFETTO_CHECK(getaddrinfo(address[0].c_str(), port[0].c_str(), &hints,
179 &addr_info) == 0);
180 PERFETTO_CHECK(addr_info->ai_family == AF_INET6);
181 SockaddrAny res(addr_info->ai_addr,
182 static_cast<socklen_t>(addr_info->ai_addrlen));
183 freeaddrinfo(addr_info);
184 return res;
185 }
186 }
187 PERFETTO_CHECK(false); // For GCC.
188 }
189
CreateSocketHandle(SockFamily family,SockType type)190 ScopedSocketHandle CreateSocketHandle(SockFamily family, SockType type) {
191 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
192 static bool init_winsock_once = [] {
193 WSADATA ignored{};
194 return WSAStartup(MAKEWORD(2, 2), &ignored) == 0;
195 }();
196 PERFETTO_CHECK(init_winsock_once);
197 #endif
198 return ScopedSocketHandle(
199 socket(GetSockFamily(family), GetSockType(type), 0));
200 }
201
202 } // namespace
203
204 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
CloseSocket(SocketHandle s)205 int CloseSocket(SocketHandle s) {
206 return ::closesocket(s);
207 }
208 #endif
209
210 // +-----------------------+
211 // | UnixSocketRaw methods |
212 // +-----------------------+
213
214 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
215 // static
ShiftMsgHdrPosix(size_t n,struct msghdr * msg)216 void UnixSocketRaw::ShiftMsgHdrPosix(size_t n, struct msghdr* msg) {
217 using LenType = decltype(msg->msg_iovlen); // Mac and Linux don't agree.
218 for (LenType i = 0; i < msg->msg_iovlen; ++i) {
219 struct iovec* vec = &msg->msg_iov[i];
220 if (n < vec->iov_len) {
221 // We sent a part of this iovec.
222 vec->iov_base = reinterpret_cast<char*>(vec->iov_base) + n;
223 vec->iov_len -= n;
224 msg->msg_iov = vec;
225 msg->msg_iovlen -= i;
226 return;
227 }
228 // We sent the whole iovec.
229 n -= vec->iov_len;
230 }
231 // We sent all the iovecs.
232 PERFETTO_CHECK(n == 0);
233 msg->msg_iovlen = 0;
234 msg->msg_iov = nullptr;
235 }
236
237 // static
CreatePairPosix(SockFamily family,SockType type)238 std::pair<UnixSocketRaw, UnixSocketRaw> UnixSocketRaw::CreatePairPosix(
239 SockFamily family,
240 SockType type) {
241 int fds[2];
242 if (socketpair(GetSockFamily(family), GetSockType(type), 0, fds) != 0)
243 return std::make_pair(UnixSocketRaw(), UnixSocketRaw());
244
245 return std::make_pair(UnixSocketRaw(ScopedFile(fds[0]), family, type),
246 UnixSocketRaw(ScopedFile(fds[1]), family, type));
247 }
248 #endif
249
250 // static
CreateMayFail(SockFamily family,SockType type)251 UnixSocketRaw UnixSocketRaw::CreateMayFail(SockFamily family, SockType type) {
252 auto fd = CreateSocketHandle(family, type);
253 if (!fd)
254 return UnixSocketRaw();
255 return UnixSocketRaw(std::move(fd), family, type);
256 }
257
258 UnixSocketRaw::UnixSocketRaw() = default;
259
UnixSocketRaw(SockFamily family,SockType type)260 UnixSocketRaw::UnixSocketRaw(SockFamily family, SockType type)
261 : UnixSocketRaw(CreateSocketHandle(family, type), family, type) {}
262
UnixSocketRaw(ScopedSocketHandle fd,SockFamily family,SockType type)263 UnixSocketRaw::UnixSocketRaw(ScopedSocketHandle fd,
264 SockFamily family,
265 SockType type)
266 : fd_(std::move(fd)), family_(family), type_(type) {
267 PERFETTO_CHECK(fd_);
268 #if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
269 const int no_sigpipe = 1;
270 setsockopt(*fd_, SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, sizeof(no_sigpipe));
271 #endif
272
273 if (family == SockFamily::kInet || family == SockFamily::kInet6) {
274 int flag = 1;
275 // The reinterpret_cast<const char*> is needed for Windows, where the 4th
276 // arg is a const char* (on other POSIX system is a const void*).
277 PERFETTO_CHECK(!setsockopt(*fd_, SOL_SOCKET, SO_REUSEADDR,
278 reinterpret_cast<const char*>(&flag),
279 sizeof(flag)));
280 flag = 1;
281 // Disable Nagle's algorithm, optimize for low-latency.
282 // See https://github.com/google/perfetto/issues/70.
283 setsockopt(*fd_, IPPROTO_TCP, TCP_NODELAY,
284 reinterpret_cast<const char*>(&flag), sizeof(flag));
285 }
286
287 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
288 // We use one event handle for all socket events, to stay consistent to what
289 // we do on UNIX with the base::TaskRunner's poll().
290 event_handle_.reset(WSACreateEvent());
291 PERFETTO_CHECK(event_handle_);
292 #else
293 // There is no reason why a socket should outlive the process in case of
294 // exec() by default, this is just working around a broken unix design.
295 int fcntl_res = fcntl(*fd_, F_SETFD, FD_CLOEXEC);
296 PERFETTO_CHECK(fcntl_res == 0);
297 #endif
298 }
299
SetBlocking(bool is_blocking)300 void UnixSocketRaw::SetBlocking(bool is_blocking) {
301 PERFETTO_DCHECK(fd_);
302 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
303 unsigned long flag = is_blocking ? 0 : 1; // FIONBIO has reverse logic.
304 if (is_blocking) {
305 // When switching between non-blocking -> blocking mode, we need to reset
306 // the event handle registration, otherwise the call will fail.
307 PERFETTO_CHECK(WSAEventSelect(*fd_, *event_handle_, 0) == 0);
308 }
309 PERFETTO_CHECK(ioctlsocket(*fd_, static_cast<long>(FIONBIO), &flag) == 0);
310 if (!is_blocking) {
311 PERFETTO_CHECK(
312 WSAEventSelect(*fd_, *event_handle_,
313 FD_ACCEPT | FD_CONNECT | FD_READ | FD_CLOSE) == 0);
314 }
315 #else
316 int flags = fcntl(*fd_, F_GETFL, 0);
317 if (!is_blocking) {
318 flags |= O_NONBLOCK;
319 } else {
320 flags &= ~static_cast<int>(O_NONBLOCK);
321 }
322 int fcntl_res = fcntl(*fd_, F_SETFL, flags);
323 PERFETTO_CHECK(fcntl_res == 0);
324 #endif
325 }
326
RetainOnExec()327 void UnixSocketRaw::RetainOnExec() {
328 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
329 PERFETTO_DCHECK(fd_);
330 int flags = fcntl(*fd_, F_GETFD, 0);
331 flags &= ~static_cast<int>(FD_CLOEXEC);
332 int fcntl_res = fcntl(*fd_, F_SETFD, flags);
333 PERFETTO_CHECK(fcntl_res == 0);
334 #endif
335 }
336
DcheckIsBlocking(bool expected) const337 void UnixSocketRaw::DcheckIsBlocking(bool expected) const {
338 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
339 ignore_result(expected);
340 #else
341 PERFETTO_DCHECK(fd_);
342 bool is_blocking = (fcntl(*fd_, F_GETFL, 0) & O_NONBLOCK) == 0;
343 PERFETTO_DCHECK(is_blocking == expected);
344 #endif
345 }
346
Bind(const std::string & socket_name)347 bool UnixSocketRaw::Bind(const std::string& socket_name) {
348 PERFETTO_DCHECK(fd_);
349 SockaddrAny addr = MakeSockAddr(family_, socket_name);
350 if (addr.size == 0)
351 return false;
352
353 if (bind(*fd_, addr.addr(), addr.size)) {
354 PERFETTO_DPLOG("bind(%s)", socket_name.c_str());
355 return false;
356 }
357
358 return true;
359 }
360
Listen()361 bool UnixSocketRaw::Listen() {
362 PERFETTO_DCHECK(fd_);
363 PERFETTO_DCHECK(type_ == SockType::kStream || type_ == SockType::kSeqPacket);
364 return listen(*fd_, SOMAXCONN) == 0;
365 }
366
Connect(const std::string & socket_name)367 bool UnixSocketRaw::Connect(const std::string& socket_name) {
368 PERFETTO_DCHECK(fd_);
369 SockaddrAny addr = MakeSockAddr(family_, socket_name);
370 if (addr.size == 0)
371 return false;
372
373 int res = PERFETTO_EINTR(connect(*fd_, addr.addr(), addr.size));
374 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
375 bool continue_async = WSAGetLastError() == WSAEWOULDBLOCK;
376 #else
377 bool continue_async = errno == EINPROGRESS;
378 #endif
379 if (res && !continue_async)
380 return false;
381
382 return true;
383 }
384
Shutdown()385 void UnixSocketRaw::Shutdown() {
386 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
387 // Somebody felt very strongly about the naming of this constant.
388 shutdown(*fd_, SD_BOTH);
389 #else
390 shutdown(*fd_, SHUT_RDWR);
391 #endif
392 fd_.reset();
393 }
394
395 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
396
Send(const void * msg,size_t len,const int *,size_t num_fds)397 ssize_t UnixSocketRaw::Send(const void* msg,
398 size_t len,
399 const int* /*send_fds*/,
400 size_t num_fds) {
401 PERFETTO_DCHECK(num_fds == 0);
402 return sendto(*fd_, static_cast<const char*>(msg), static_cast<int>(len), 0,
403 nullptr, 0);
404 }
405
Receive(void * msg,size_t len,ScopedFile *,size_t)406 ssize_t UnixSocketRaw::Receive(void* msg,
407 size_t len,
408 ScopedFile* /*fd_vec*/,
409 size_t /*max_files*/) {
410 return recv(*fd_, static_cast<char*>(msg), static_cast<int>(len), 0);
411 }
412
413 #else
414 // For the interested reader, Linux kernel dive to verify this is not only a
415 // theoretical possibility: sock_stream_sendmsg, if sock_alloc_send_pskb returns
416 // NULL [1] (which it does when it gets interrupted [2]), returns early with the
417 // amount of bytes already sent.
418 //
419 // [1]:
420 // https://elixir.bootlin.com/linux/v4.18.10/source/net/unix/af_unix.c#L1872
421 // [2]: https://elixir.bootlin.com/linux/v4.18.10/source/net/core/sock.c#L2101
SendMsgAllPosix(struct msghdr * msg)422 ssize_t UnixSocketRaw::SendMsgAllPosix(struct msghdr* msg) {
423 // This does not make sense on non-blocking sockets.
424 PERFETTO_DCHECK(fd_);
425
426 const bool is_blocking_with_timeout =
427 tx_timeout_ms_ > 0 && ((fcntl(*fd_, F_GETFL, 0) & O_NONBLOCK) == 0);
428 const int64_t start_ms = GetWallTimeMs().count();
429
430 // Waits until some space is available in the tx buffer.
431 // Returns true if some buffer space is available, false if times out.
432 auto poll_or_timeout = [&] {
433 PERFETTO_DCHECK(is_blocking_with_timeout);
434 const int64_t deadline = start_ms + tx_timeout_ms_;
435 const int64_t now_ms = GetWallTimeMs().count();
436 if (now_ms >= deadline)
437 return false; // Timed out
438 const int timeout_ms = static_cast<int>(deadline - now_ms);
439 pollfd pfd{*fd_, POLLOUT, 0};
440 return PERFETTO_EINTR(poll(&pfd, 1, timeout_ms)) > 0;
441 };
442
443 // We implement blocking sends that require a timeout as non-blocking + poll.
444 // This is because SO_SNDTIMEO doesn't work as expected (b/193234818). On linux
445 // we can just pass MSG_DONTWAIT to force the send to be non-blocking. On Mac,
446 // instead we need to flip the O_NONBLOCK flag back and forth.
447 #if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
448 // MSG_NOSIGNAL is not supported on Mac OS X, but in that case the socket is
449 // created with SO_NOSIGPIPE (See InitializeSocket()).
450 int send_flags = 0;
451
452 if (is_blocking_with_timeout)
453 SetBlocking(false);
454
455 auto reset_nonblock_on_exit = OnScopeExit([&] {
456 if (is_blocking_with_timeout)
457 SetBlocking(true);
458 });
459 #else
460 int send_flags = MSG_NOSIGNAL | (is_blocking_with_timeout ? MSG_DONTWAIT : 0);
461 #endif
462
463 ssize_t total_sent = 0;
464 while (msg->msg_iov) {
465 ssize_t send_res = PERFETTO_EINTR(sendmsg(*fd_, msg, send_flags));
466 if (send_res == -1 && IsAgain(errno)) {
467 if (is_blocking_with_timeout && poll_or_timeout()) {
468 continue; // Tx buffer unblocked, repeat the loop.
469 }
470 return total_sent;
471 } else if (send_res <= 0) {
472 return send_res; // An error occurred.
473 } else {
474 total_sent += send_res;
475 ShiftMsgHdrPosix(static_cast<size_t>(send_res), msg);
476 // Only send the ancillary data with the first sendmsg call.
477 msg->msg_control = nullptr;
478 msg->msg_controllen = 0;
479 }
480 }
481 return total_sent;
482 }
483
Send(const void * msg,size_t len,const int * send_fds,size_t num_fds)484 ssize_t UnixSocketRaw::Send(const void* msg,
485 size_t len,
486 const int* send_fds,
487 size_t num_fds) {
488 PERFETTO_DCHECK(fd_);
489 msghdr msg_hdr = {};
490 iovec iov = {const_cast<void*>(msg), len};
491 msg_hdr.msg_iov = &iov;
492 msg_hdr.msg_iovlen = 1;
493 alignas(cmsghdr) char control_buf[256];
494
495 if (num_fds > 0) {
496 const auto raw_ctl_data_sz = num_fds * sizeof(int);
497 const CBufLenType control_buf_len =
498 static_cast<CBufLenType>(CMSG_SPACE(raw_ctl_data_sz));
499 PERFETTO_CHECK(control_buf_len <= sizeof(control_buf));
500 memset(control_buf, 0, sizeof(control_buf));
501 msg_hdr.msg_control = control_buf;
502 msg_hdr.msg_controllen = control_buf_len; // used by CMSG_FIRSTHDR
503 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg_hdr);
504 cmsg->cmsg_level = SOL_SOCKET;
505 cmsg->cmsg_type = SCM_RIGHTS;
506 cmsg->cmsg_len = static_cast<CBufLenType>(CMSG_LEN(raw_ctl_data_sz));
507 memcpy(CMSG_DATA(cmsg), send_fds, num_fds * sizeof(int));
508 // note: if we were to send multiple cmsghdr structures, then
509 // msg_hdr.msg_controllen would need to be adjusted, see "man 3 cmsg".
510 }
511
512 return SendMsgAllPosix(&msg_hdr);
513 }
514
Receive(void * msg,size_t len,ScopedFile * fd_vec,size_t max_files)515 ssize_t UnixSocketRaw::Receive(void* msg,
516 size_t len,
517 ScopedFile* fd_vec,
518 size_t max_files) {
519 PERFETTO_DCHECK(fd_);
520 msghdr msg_hdr = {};
521 iovec iov = {msg, len};
522 msg_hdr.msg_iov = &iov;
523 msg_hdr.msg_iovlen = 1;
524 alignas(cmsghdr) char control_buf[256];
525
526 if (max_files > 0) {
527 msg_hdr.msg_control = control_buf;
528 msg_hdr.msg_controllen =
529 static_cast<CBufLenType>(CMSG_SPACE(max_files * sizeof(int)));
530 PERFETTO_CHECK(msg_hdr.msg_controllen <= sizeof(control_buf));
531 }
532 const ssize_t sz = PERFETTO_EINTR(recvmsg(*fd_, &msg_hdr, 0));
533 if (sz <= 0) {
534 return sz;
535 }
536 PERFETTO_CHECK(static_cast<size_t>(sz) <= len);
537
538 int* fds = nullptr;
539 uint32_t fds_len = 0;
540
541 if (max_files > 0) {
542 for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg_hdr); cmsg;
543 cmsg = CMSG_NXTHDR(&msg_hdr, cmsg)) {
544 const size_t payload_len = cmsg->cmsg_len - CMSG_LEN(0);
545 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
546 PERFETTO_DCHECK(payload_len % sizeof(int) == 0u);
547 PERFETTO_CHECK(fds == nullptr);
548 fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
549 fds_len = static_cast<uint32_t>(payload_len / sizeof(int));
550 }
551 }
552 }
553
554 if (msg_hdr.msg_flags & MSG_TRUNC || msg_hdr.msg_flags & MSG_CTRUNC) {
555 for (size_t i = 0; fds && i < fds_len; ++i)
556 close(fds[i]);
557 PERFETTO_ELOG(
558 "Socket message truncated. This might be due to a SELinux denial on "
559 "fd:use.");
560 errno = EMSGSIZE;
561 return -1;
562 }
563
564 for (size_t i = 0; fds && i < fds_len; ++i) {
565 if (i < max_files)
566 fd_vec[i].reset(fds[i]);
567 else
568 close(fds[i]);
569 }
570
571 return sz;
572 }
573 #endif // OS_WIN
574
SetTxTimeout(uint32_t timeout_ms)575 bool UnixSocketRaw::SetTxTimeout(uint32_t timeout_ms) {
576 PERFETTO_DCHECK(fd_);
577 // On Unix-based systems, SO_SNDTIMEO isn't used for Send() because it's
578 // unreliable (b/193234818). Instead we use non-blocking sendmsg() + poll().
579 // See SendMsgAllPosix(). We still make the setsockopt call because
580 // SO_SNDTIMEO also affects connect().
581 tx_timeout_ms_ = timeout_ms;
582 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
583 DWORD timeout = timeout_ms;
584 ignore_result(tx_timeout_ms_);
585 #else
586 struct timeval timeout {};
587 uint32_t timeout_sec = timeout_ms / 1000;
588 timeout.tv_sec = static_cast<decltype(timeout.tv_sec)>(timeout_sec);
589 timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(
590 (timeout_ms - (timeout_sec * 1000)) * 1000);
591 #endif
592 return setsockopt(*fd_, SOL_SOCKET, SO_SNDTIMEO,
593 reinterpret_cast<const char*>(&timeout),
594 sizeof(timeout)) == 0;
595 }
596
SetRxTimeout(uint32_t timeout_ms)597 bool UnixSocketRaw::SetRxTimeout(uint32_t timeout_ms) {
598 PERFETTO_DCHECK(fd_);
599 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
600 DWORD timeout = timeout_ms;
601 #else
602 struct timeval timeout {};
603 uint32_t timeout_sec = timeout_ms / 1000;
604 timeout.tv_sec = static_cast<decltype(timeout.tv_sec)>(timeout_sec);
605 timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(
606 (timeout_ms - (timeout_sec * 1000)) * 1000);
607 #endif
608 return setsockopt(*fd_, SOL_SOCKET, SO_RCVTIMEO,
609 reinterpret_cast<const char*>(&timeout),
610 sizeof(timeout)) == 0;
611 }
612
613 #if defined(__GNUC__) && !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
614 #pragma GCC diagnostic pop
615 #endif
616
617 // +--------------------+
618 // | UnixSocket methods |
619 // +--------------------+
620
621 // TODO(primiano): Add ThreadChecker to methods of this class.
622
623 // static
Listen(const std::string & socket_name,EventListener * event_listener,TaskRunner * task_runner,SockFamily sock_family,SockType sock_type)624 std::unique_ptr<UnixSocket> UnixSocket::Listen(const std::string& socket_name,
625 EventListener* event_listener,
626 TaskRunner* task_runner,
627 SockFamily sock_family,
628 SockType sock_type) {
629 auto sock_raw = UnixSocketRaw::CreateMayFail(sock_family, sock_type);
630 if (!sock_raw || !sock_raw.Bind(socket_name))
631 return nullptr;
632
633 // Forward the call to the Listen() overload below.
634 return Listen(sock_raw.ReleaseFd(), event_listener, task_runner, sock_family,
635 sock_type);
636 }
637
638 // static
Listen(ScopedSocketHandle fd,EventListener * event_listener,TaskRunner * task_runner,SockFamily sock_family,SockType sock_type)639 std::unique_ptr<UnixSocket> UnixSocket::Listen(ScopedSocketHandle fd,
640 EventListener* event_listener,
641 TaskRunner* task_runner,
642 SockFamily sock_family,
643 SockType sock_type) {
644 return std::unique_ptr<UnixSocket>(new UnixSocket(
645 event_listener, task_runner, std::move(fd), State::kListening,
646 sock_family, sock_type, SockPeerCredMode::kDefault));
647 }
648
649 // static
Connect(const std::string & socket_name,EventListener * event_listener,TaskRunner * task_runner,SockFamily sock_family,SockType sock_type,SockPeerCredMode peer_cred_mode)650 std::unique_ptr<UnixSocket> UnixSocket::Connect(
651 const std::string& socket_name,
652 EventListener* event_listener,
653 TaskRunner* task_runner,
654 SockFamily sock_family,
655 SockType sock_type,
656 SockPeerCredMode peer_cred_mode) {
657 std::unique_ptr<UnixSocket> sock(new UnixSocket(
658 event_listener, task_runner, sock_family, sock_type, peer_cred_mode));
659 sock->DoConnect(socket_name);
660 return sock;
661 }
662
663 // static
AdoptConnected(ScopedSocketHandle fd,EventListener * event_listener,TaskRunner * task_runner,SockFamily sock_family,SockType sock_type,SockPeerCredMode peer_cred_mode)664 std::unique_ptr<UnixSocket> UnixSocket::AdoptConnected(
665 ScopedSocketHandle fd,
666 EventListener* event_listener,
667 TaskRunner* task_runner,
668 SockFamily sock_family,
669 SockType sock_type,
670 SockPeerCredMode peer_cred_mode) {
671 return std::unique_ptr<UnixSocket>(new UnixSocket(
672 event_listener, task_runner, std::move(fd), State::kConnected,
673 sock_family, sock_type, peer_cred_mode));
674 }
675
UnixSocket(EventListener * event_listener,TaskRunner * task_runner,SockFamily sock_family,SockType sock_type,SockPeerCredMode peer_cred_mode)676 UnixSocket::UnixSocket(EventListener* event_listener,
677 TaskRunner* task_runner,
678 SockFamily sock_family,
679 SockType sock_type,
680 SockPeerCredMode peer_cred_mode)
681 : UnixSocket(event_listener,
682 task_runner,
683 ScopedSocketHandle(),
684 State::kDisconnected,
685 sock_family,
686 sock_type,
687 peer_cred_mode) {}
688
UnixSocket(EventListener * event_listener,TaskRunner * task_runner,ScopedSocketHandle adopt_fd,State adopt_state,SockFamily sock_family,SockType sock_type,SockPeerCredMode peer_cred_mode)689 UnixSocket::UnixSocket(EventListener* event_listener,
690 TaskRunner* task_runner,
691 ScopedSocketHandle adopt_fd,
692 State adopt_state,
693 SockFamily sock_family,
694 SockType sock_type,
695 SockPeerCredMode peer_cred_mode)
696 : peer_cred_mode_(peer_cred_mode),
697 event_listener_(event_listener),
698 task_runner_(task_runner),
699 weak_ptr_factory_(this) {
700 state_ = State::kDisconnected;
701 if (adopt_state == State::kDisconnected) {
702 PERFETTO_DCHECK(!adopt_fd);
703 sock_raw_ = UnixSocketRaw::CreateMayFail(sock_family, sock_type);
704 if (!sock_raw_)
705 return;
706 } else if (adopt_state == State::kConnected) {
707 PERFETTO_DCHECK(adopt_fd);
708 sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_family, sock_type);
709 state_ = State::kConnected;
710 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
711 if (peer_cred_mode_ == SockPeerCredMode::kReadOnConnect)
712 ReadPeerCredentialsPosix();
713 #endif
714 } else if (adopt_state == State::kListening) {
715 // We get here from Listen().
716
717 // |adopt_fd| might genuinely be invalid if the bind() failed.
718 if (!adopt_fd)
719 return;
720
721 sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_family, sock_type);
722 if (!sock_raw_.Listen()) {
723 PERFETTO_DPLOG("listen() failed");
724 return;
725 }
726 state_ = State::kListening;
727 } else {
728 PERFETTO_FATAL("Unexpected adopt_state"); // Unfeasible.
729 }
730
731 PERFETTO_CHECK(sock_raw_);
732
733 sock_raw_.SetBlocking(false);
734
735 WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
736
737 task_runner_->AddFileDescriptorWatch(sock_raw_.watch_handle(), [weak_ptr] {
738 if (weak_ptr)
739 weak_ptr->OnEvent();
740 });
741 }
742
~UnixSocket()743 UnixSocket::~UnixSocket() {
744 // The implicit dtor of |weak_ptr_factory_| will no-op pending callbacks.
745 Shutdown(true);
746 }
747
ReleaseSocket()748 UnixSocketRaw UnixSocket::ReleaseSocket() {
749 // This will invalidate any pending calls to OnEvent.
750 state_ = State::kDisconnected;
751 if (sock_raw_)
752 task_runner_->RemoveFileDescriptorWatch(sock_raw_.watch_handle());
753
754 return std::move(sock_raw_);
755 }
756
757 // Called only by the Connect() static constructor.
DoConnect(const std::string & socket_name)758 void UnixSocket::DoConnect(const std::string& socket_name) {
759 PERFETTO_DCHECK(state_ == State::kDisconnected);
760
761 // This is the only thing that can gracefully fail in the ctor.
762 if (!sock_raw_)
763 return NotifyConnectionState(false);
764
765 if (!sock_raw_.Connect(socket_name))
766 return NotifyConnectionState(false);
767
768 // At this point either connect() succeeded or started asynchronously
769 // (errno = EINPROGRESS).
770 state_ = State::kConnecting;
771
772 // Even if the socket is non-blocking, connecting to a UNIX socket can be
773 // acknowledged straight away rather than returning EINPROGRESS.
774 // The decision here is to deal with the two cases uniformly, at the cost of
775 // delaying the straight-away-connect() case by one task, to avoid depending
776 // on implementation details of UNIX socket on the various OSes.
777 // Posting the OnEvent() below emulates a wakeup of the FD watch. OnEvent(),
778 // which knows how to deal with spurious wakeups, will poll the SO_ERROR and
779 // evolve, if necessary, the state into either kConnected or kDisconnected.
780 WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
781 task_runner_->PostTask([weak_ptr] {
782 if (weak_ptr)
783 weak_ptr->OnEvent();
784 });
785 }
786
787 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
ReadPeerCredentialsPosix()788 void UnixSocket::ReadPeerCredentialsPosix() {
789 // Peer credentials are supported only on AF_UNIX sockets.
790 if (sock_raw_.family() != SockFamily::kUnix)
791 return;
792 PERFETTO_CHECK(peer_cred_mode_ != SockPeerCredMode::kIgnore);
793
794 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
795 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
796 struct ucred user_cred;
797 socklen_t len = sizeof(user_cred);
798 int fd = sock_raw_.fd();
799 int res = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &user_cred, &len);
800 PERFETTO_CHECK(res == 0);
801 peer_uid_ = user_cred.uid;
802 peer_pid_ = user_cred.pid;
803 #elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
804 struct xucred user_cred;
805 socklen_t len = sizeof(user_cred);
806 int res = getsockopt(sock_raw_.fd(), 0, LOCAL_PEERCRED, &user_cred, &len);
807 PERFETTO_CHECK(res == 0 && user_cred.cr_version == XUCRED_VERSION);
808 peer_uid_ = static_cast<uid_t>(user_cred.cr_uid);
809 // There is no pid in the LOCAL_PEERCREDS for MacOS / FreeBSD.
810 #endif
811 }
812 #endif // !OS_WIN
813
814 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
OnEvent()815 void UnixSocket::OnEvent() {
816 WSANETWORKEVENTS evts{};
817 PERFETTO_CHECK(WSAEnumNetworkEvents(sock_raw_.fd(), sock_raw_.watch_handle(),
818 &evts) == 0);
819 if (state_ == State::kDisconnected)
820 return; // Some spurious event, typically queued just before Shutdown().
821
822 if (state_ == State::kConnecting && (evts.lNetworkEvents & FD_CONNECT)) {
823 PERFETTO_DCHECK(sock_raw_);
824 int err = evts.iErrorCode[FD_CONNECT_BIT];
825 if (err) {
826 PERFETTO_DPLOG("Connection error: %d", err);
827 Shutdown(false);
828 event_listener_->OnConnect(this, false /* connected */);
829 return;
830 }
831
832 // kReadOnConnect is not supported on Windows.
833 PERFETTO_DCHECK(peer_cred_mode_ != SockPeerCredMode::kReadOnConnect);
834 state_ = State::kConnected;
835 event_listener_->OnConnect(this, true /* connected */);
836 }
837
838 // This is deliberately NOT an else-if. When a client socket connects and
839 // there is already data queued, the following will happen within the same
840 // OnEvent() call:
841 // 1. The block above will transition kConnecting -> kConnected.
842 // 2. This block will cause an OnDataAvailable() call.
843 // Unlike UNIX, where poll() keeps signalling the event until the client
844 // does a recv(), Windows is more picky and stops signalling the event until
845 // the next call to recv() is made. In other words, in Windows we cannot
846 // miss an OnDataAvailable() call or the event pump will stop.
847 if (state_ == State::kConnected) {
848 if (evts.lNetworkEvents & FD_READ) {
849 event_listener_->OnDataAvailable(this);
850 // TODO(primiano): I am very conflicted here. Because of the behavior
851 // described above, if the event listener doesn't do a Recv() call in
852 // the OnDataAvailable() callback, WinSock won't notify the event ever
853 // again. On one side, I don't see any reason why a client should decide
854 // to not do a Recv() in OnDataAvailable. On the other side, the
855 // behavior here diverges from UNIX, where OnDataAvailable() would be
856 // re-posted immediately. In both cases, not doing a Recv() in
857 // OnDataAvailable, leads to something bad (getting stuck on Windows,
858 // getting in a hot loop on Linux), so doesn't feel we should worry too
859 // much about this. If we wanted to keep the behavrior consistent, here
860 // we should do something like: `if (sock_raw_)
861 // sock_raw_.SetBlocking(false)` (Note that the socket might be closed
862 // by the time we come back here, hence the if part).
863 return;
864 }
865 // Could read EOF and disconnect here.
866 if (evts.lNetworkEvents & FD_CLOSE) {
867 Shutdown(true);
868 return;
869 }
870 }
871
872 // New incoming connection.
873 if (state_ == State::kListening && (evts.lNetworkEvents & FD_ACCEPT)) {
874 // There could be more than one incoming connection behind each FD watch
875 // notification. Drain'em all.
876 for (;;) {
877 // Note: right now we don't need the remote endpoint, hence we pass
878 // nullptr to |addr| and |addrlen|. If we ever need to do so, be
879 // extremely careful. Windows' WinSock API will happily write more than
880 // |addrlen| (hence corrupt the stack) if the |addr| argument passed is
881 // not big enough (e.g. passing a struct sockaddr_in to a AF_UNIX
882 // socket, where sizeof(sockaddr_un) is >> sizef(sockaddr_in)). It seems
883 // a Windows / CRT bug in the AF_UNIX implementation.
884 ScopedSocketHandle new_fd(accept(sock_raw_.fd(), nullptr, nullptr));
885 if (!new_fd)
886 return;
887 std::unique_ptr<UnixSocket> new_sock(new UnixSocket(
888 event_listener_, task_runner_, std::move(new_fd), State::kConnected,
889 sock_raw_.family(), sock_raw_.type(), peer_cred_mode_));
890 event_listener_->OnNewIncomingConnection(this, std::move(new_sock));
891 }
892 }
893 }
894 #else
OnEvent()895 void UnixSocket::OnEvent() {
896 if (state_ == State::kDisconnected)
897 return; // Some spurious event, typically queued just before Shutdown().
898
899 if (state_ == State::kConnected)
900 return event_listener_->OnDataAvailable(this);
901
902 if (state_ == State::kConnecting) {
903 PERFETTO_DCHECK(sock_raw_);
904 int sock_err = EINVAL;
905 socklen_t err_len = sizeof(sock_err);
906 int res =
907 getsockopt(sock_raw_.fd(), SOL_SOCKET, SO_ERROR, &sock_err, &err_len);
908
909 if (res == 0 && sock_err == EINPROGRESS)
910 return; // Not connected yet, just a spurious FD watch wakeup.
911 if (res == 0 && sock_err == 0) {
912 if (peer_cred_mode_ == SockPeerCredMode::kReadOnConnect)
913 ReadPeerCredentialsPosix();
914 state_ = State::kConnected;
915 return event_listener_->OnConnect(this, true /* connected */);
916 }
917 PERFETTO_DLOG("Connection error: %s", strerror(sock_err));
918 Shutdown(false);
919 return event_listener_->OnConnect(this, false /* connected */);
920 }
921
922 // New incoming connection.
923 if (state_ == State::kListening) {
924 // There could be more than one incoming connection behind each FD watch
925 // notification. Drain'em all.
926 for (;;) {
927 ScopedFile new_fd(
928 PERFETTO_EINTR(accept(sock_raw_.fd(), nullptr, nullptr)));
929 if (!new_fd)
930 return;
931 std::unique_ptr<UnixSocket> new_sock(new UnixSocket(
932 event_listener_, task_runner_, std::move(new_fd), State::kConnected,
933 sock_raw_.family(), sock_raw_.type(), peer_cred_mode_));
934 event_listener_->OnNewIncomingConnection(this, std::move(new_sock));
935 }
936 }
937 }
938 #endif
939
Send(const void * msg,size_t len,const int * send_fds,size_t num_fds)940 bool UnixSocket::Send(const void* msg,
941 size_t len,
942 const int* send_fds,
943 size_t num_fds) {
944 if (state_ != State::kConnected) {
945 errno = ENOTCONN;
946 return false;
947 }
948
949 sock_raw_.SetBlocking(true);
950 const ssize_t sz = sock_raw_.Send(msg, len, send_fds, num_fds);
951 sock_raw_.SetBlocking(false);
952
953 if (sz == static_cast<ssize_t>(len)) {
954 return true;
955 }
956
957 // If we ever decide to support non-blocking sends again, here we should
958 // watch for both EAGAIN and EWOULDBLOCK (see base::IsAgain()).
959
960 // If sendmsg() succeeds but the returned size is >= 0 and < |len| it means
961 // that the endpoint disconnected in the middle of the read, and we managed
962 // to send only a portion of the buffer.
963 // If sz < 0, either the other endpoint disconnected (ECONNRESET) or some
964 // other error happened. In both cases we should just give up.
965 PERFETTO_DPLOG("sendmsg() failed");
966 Shutdown(true);
967 return false;
968 }
969
Shutdown(bool notify)970 void UnixSocket::Shutdown(bool notify) {
971 WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
972 if (notify) {
973 if (state_ == State::kConnected) {
974 task_runner_->PostTask([weak_ptr] {
975 if (weak_ptr)
976 weak_ptr->event_listener_->OnDisconnect(weak_ptr.get());
977 });
978 } else if (state_ == State::kConnecting) {
979 task_runner_->PostTask([weak_ptr] {
980 if (weak_ptr)
981 weak_ptr->event_listener_->OnConnect(weak_ptr.get(), false);
982 });
983 }
984 }
985
986 if (sock_raw_) {
987 task_runner_->RemoveFileDescriptorWatch(sock_raw_.watch_handle());
988 sock_raw_.Shutdown();
989 }
990 state_ = State::kDisconnected;
991 }
992
Receive(void * msg,size_t len,ScopedFile * fd_vec,size_t max_files)993 size_t UnixSocket::Receive(void* msg,
994 size_t len,
995 ScopedFile* fd_vec,
996 size_t max_files) {
997 if (state_ != State::kConnected)
998 return 0;
999
1000 const ssize_t sz = sock_raw_.Receive(msg, len, fd_vec, max_files);
1001 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
1002 bool async_would_block = WSAGetLastError() == WSAEWOULDBLOCK;
1003 #else
1004 bool async_would_block = IsAgain(errno);
1005 #endif
1006 if (sz < 0 && async_would_block)
1007 return 0;
1008
1009 if (sz <= 0) {
1010 Shutdown(true);
1011 return 0;
1012 }
1013 PERFETTO_CHECK(static_cast<size_t>(sz) <= len);
1014 return static_cast<size_t>(sz);
1015 }
1016
ReceiveString(size_t max_length)1017 std::string UnixSocket::ReceiveString(size_t max_length) {
1018 std::unique_ptr<char[]> buf(new char[max_length + 1]);
1019 size_t rsize = Receive(buf.get(), max_length);
1020 PERFETTO_CHECK(rsize <= max_length);
1021 buf[rsize] = '\0';
1022 return std::string(buf.get());
1023 }
1024
NotifyConnectionState(bool success)1025 void UnixSocket::NotifyConnectionState(bool success) {
1026 if (!success)
1027 Shutdown(false);
1028
1029 WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
1030 task_runner_->PostTask([weak_ptr, success] {
1031 if (weak_ptr)
1032 weak_ptr->event_listener_->OnConnect(weak_ptr.get(), success);
1033 });
1034 }
1035
~EventListener()1036 UnixSocket::EventListener::~EventListener() {}
OnNewIncomingConnection(UnixSocket *,std::unique_ptr<UnixSocket>)1037 void UnixSocket::EventListener::OnNewIncomingConnection(
1038 UnixSocket*,
1039 std::unique_ptr<UnixSocket>) {}
OnConnect(UnixSocket *,bool)1040 void UnixSocket::EventListener::OnConnect(UnixSocket*, bool) {}
OnDisconnect(UnixSocket *)1041 void UnixSocket::EventListener::OnDisconnect(UnixSocket*) {}
OnDataAvailable(UnixSocket *)1042 void UnixSocket::EventListener::OnDataAvailable(UnixSocket*) {}
1043
1044 } // namespace base
1045 } // namespace perfetto
1046