• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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