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