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