Home | History | Annotate | Download | only in ipc
      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 "src/ipc/unix_socket.h"
     18 
     19 #include <errno.h>
     20 #include <fcntl.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <sys/socket.h>
     24 #include <sys/stat.h>
     25 #include <sys/types.h>
     26 #include <sys/un.h>
     27 #include <unistd.h>
     28 
     29 #include <algorithm>
     30 #include <memory>
     31 
     32 #include "perfetto/base/build_config.h"
     33 #include "perfetto/base/logging.h"
     34 #include "perfetto/base/task_runner.h"
     35 #include "perfetto/base/utils.h"
     36 
     37 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
     38 #include <sys/ucred.h>
     39 #endif
     40 
     41 namespace perfetto {
     42 namespace ipc {
     43 
     44 // TODO(primiano): Add ThreadChecker to methods of this class.
     45 
     46 namespace {
     47 
     48 // MSG_NOSIGNAL is not supported on Mac OS X, but in that case the socket is
     49 // created with SO_NOSIGPIPE (See InitializeSocket()).
     50 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
     51 constexpr int kNoSigPipe = 0;
     52 #else
     53 constexpr int kNoSigPipe = MSG_NOSIGNAL;
     54 #endif
     55 
     56 // Android takes an int instead of socklen_t for the control buffer size.
     57 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
     58 using CBufLenType = size_t;
     59 #else
     60 using CBufLenType = socklen_t;
     61 #endif
     62 
     63 bool MakeSockAddr(const std::string& socket_name,
     64                   sockaddr_un* addr,
     65                   socklen_t* addr_size) {
     66   memset(addr, 0, sizeof(*addr));
     67   const size_t name_len = socket_name.size();
     68   if (name_len >= sizeof(addr->sun_path)) {
     69     errno = ENAMETOOLONG;
     70     return false;
     71   }
     72   memcpy(addr->sun_path, socket_name.data(), name_len);
     73   if (addr->sun_path[0] == '@')
     74     addr->sun_path[0] = '\0';
     75   addr->sun_family = AF_UNIX;
     76   *addr_size = static_cast<socklen_t>(
     77       __builtin_offsetof(sockaddr_un, sun_path) + name_len + 1);
     78   return true;
     79 }
     80 
     81 base::ScopedFile CreateSocket() {
     82   return base::ScopedFile(socket(AF_UNIX, SOCK_STREAM, 0));
     83 }
     84 
     85 }  // namespace
     86 
     87 // static
     88 base::ScopedFile UnixSocket::CreateAndBind(const std::string& socket_name) {
     89   base::ScopedFile fd = CreateSocket();
     90   if (!fd)
     91     return fd;
     92 
     93   sockaddr_un addr;
     94   socklen_t addr_size;
     95   if (!MakeSockAddr(socket_name, &addr, &addr_size)) {
     96     return base::ScopedFile();
     97   }
     98 
     99   if (bind(*fd, reinterpret_cast<sockaddr*>(&addr), addr_size)) {
    100     PERFETTO_DPLOG("bind()");
    101     return base::ScopedFile();
    102   }
    103 
    104   return fd;
    105 }
    106 
    107 // static
    108 std::unique_ptr<UnixSocket> UnixSocket::Listen(const std::string& socket_name,
    109                                                EventListener* event_listener,
    110                                                base::TaskRunner* task_runner) {
    111   // Forward the call to the Listen() overload below.
    112   return Listen(CreateAndBind(socket_name), event_listener, task_runner);
    113 }
    114 
    115 // static
    116 std::unique_ptr<UnixSocket> UnixSocket::Listen(base::ScopedFile socket_fd,
    117                                                EventListener* event_listener,
    118                                                base::TaskRunner* task_runner) {
    119   std::unique_ptr<UnixSocket> sock(new UnixSocket(
    120       event_listener, task_runner, std::move(socket_fd), State::kListening));
    121   return sock;
    122 }
    123 
    124 // static
    125 std::unique_ptr<UnixSocket> UnixSocket::Connect(const std::string& socket_name,
    126                                                 EventListener* event_listener,
    127                                                 base::TaskRunner* task_runner) {
    128   std::unique_ptr<UnixSocket> sock(new UnixSocket(event_listener, task_runner));
    129   sock->DoConnect(socket_name);
    130   return sock;
    131 }
    132 
    133 UnixSocket::UnixSocket(EventListener* event_listener,
    134                        base::TaskRunner* task_runner)
    135     : UnixSocket(event_listener,
    136                  task_runner,
    137                  base::ScopedFile(),
    138                  State::kDisconnected) {}
    139 
    140 UnixSocket::UnixSocket(EventListener* event_listener,
    141                        base::TaskRunner* task_runner,
    142                        base::ScopedFile adopt_fd,
    143                        State adopt_state)
    144     : event_listener_(event_listener),
    145       task_runner_(task_runner),
    146       weak_ptr_factory_(this) {
    147   state_ = State::kDisconnected;
    148   if (adopt_state == State::kDisconnected) {
    149     // We get here from the default ctor().
    150     PERFETTO_DCHECK(!adopt_fd);
    151     fd_ = CreateSocket();
    152     if (!fd_) {
    153       last_error_ = errno;
    154       return;
    155     }
    156   } else if (adopt_state == State::kConnected) {
    157     // We get here from OnNewIncomingConnection().
    158     PERFETTO_DCHECK(adopt_fd);
    159     fd_ = std::move(adopt_fd);
    160     state_ = State::kConnected;
    161     ReadPeerCredentials();
    162   } else if (adopt_state == State::kListening) {
    163     // We get here from Listen().
    164 
    165     // |adopt_fd| might genuinely be invalid if the bind() failed.
    166     if (!adopt_fd) {
    167       last_error_ = errno;
    168       return;
    169     }
    170 
    171     fd_ = std::move(adopt_fd);
    172     if (listen(*fd_, SOMAXCONN)) {
    173       last_error_ = errno;
    174       PERFETTO_DPLOG("listen()");
    175       return;
    176     }
    177     state_ = State::kListening;
    178   } else {
    179     PERFETTO_CHECK(false);  // Unfeasible.
    180   }
    181 
    182   PERFETTO_DCHECK(fd_);
    183   last_error_ = 0;
    184 
    185 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
    186   const int no_sigpipe = 1;
    187   setsockopt(*fd_, SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, sizeof(no_sigpipe));
    188 #endif
    189   // There is no reason why a socket should outlive the process in case of
    190   // exec() by default, this is just working around a broken unix design.
    191   int fcntl_res = fcntl(*fd_, F_SETFD, FD_CLOEXEC);
    192   PERFETTO_CHECK(fcntl_res == 0);
    193 
    194   SetBlockingIO(false);
    195 
    196   base::WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
    197   task_runner_->AddFileDescriptorWatch(*fd_, [weak_ptr]() {
    198     if (weak_ptr)
    199       weak_ptr->OnEvent();
    200   });
    201 }
    202 
    203 UnixSocket::~UnixSocket() {
    204   // The implicit dtor of |weak_ptr_factory_| will no-op pending callbacks.
    205   Shutdown(true);
    206 }
    207 
    208 // Called only by the Connect() static constructor.
    209 void UnixSocket::DoConnect(const std::string& socket_name) {
    210   PERFETTO_DCHECK(state_ == State::kDisconnected);
    211 
    212   // This is the only thing that can gracefully fail in the ctor.
    213   if (!fd_)
    214     return NotifyConnectionState(false);
    215 
    216   sockaddr_un addr;
    217   socklen_t addr_size;
    218   if (!MakeSockAddr(socket_name, &addr, &addr_size)) {
    219     last_error_ = errno;
    220     return NotifyConnectionState(false);
    221   }
    222 
    223   int res = PERFETTO_EINTR(
    224       connect(*fd_, reinterpret_cast<sockaddr*>(&addr), addr_size));
    225   if (res && errno != EINPROGRESS) {
    226     last_error_ = errno;
    227     return NotifyConnectionState(false);
    228   }
    229 
    230   // At this point either |res| == 0 (the connect() succeeded) or started
    231   // asynchronously (EINPROGRESS).
    232   last_error_ = 0;
    233   state_ = State::kConnecting;
    234 
    235   // Even if the socket is non-blocking, connecting to a UNIX socket can be
    236   // acknowledged straight away rather than returning EINPROGRESS. In this case
    237   // just trigger an OnEvent without waiting for the FD watch. That will poll
    238   // the SO_ERROR and evolve the state into either kConnected or kDisconnected.
    239   if (res == 0) {
    240     base::WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
    241     task_runner_->PostTask([weak_ptr]() {
    242       if (weak_ptr)
    243         weak_ptr->OnEvent();
    244     });
    245   }
    246 }
    247 
    248 void UnixSocket::ReadPeerCredentials() {
    249 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
    250     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
    251   struct ucred user_cred;
    252   socklen_t len = sizeof(user_cred);
    253   int res = getsockopt(*fd_, SOL_SOCKET, SO_PEERCRED, &user_cred, &len);
    254   PERFETTO_CHECK(res == 0);
    255   peer_uid_ = user_cred.uid;
    256 #else
    257   struct xucred user_cred;
    258   socklen_t len = sizeof(user_cred);
    259   int res = getsockopt(*fd_, 0, LOCAL_PEERCRED, &user_cred, &len);
    260   PERFETTO_CHECK(res == 0 && user_cred.cr_version == XUCRED_VERSION);
    261   peer_uid_ = static_cast<uid_t>(user_cred.cr_uid);
    262 #endif
    263 }
    264 
    265 void UnixSocket::OnEvent() {
    266   if (state_ == State::kDisconnected)
    267     return;  // Some spurious event, typically queued just before Shutdown().
    268 
    269   if (state_ == State::kConnected)
    270     return event_listener_->OnDataAvailable(this);
    271 
    272   if (state_ == State::kConnecting) {
    273     PERFETTO_DCHECK(fd_);
    274     int sock_err = EINVAL;
    275     socklen_t err_len = sizeof(sock_err);
    276     int res = getsockopt(*fd_, SOL_SOCKET, SO_ERROR, &sock_err, &err_len);
    277     if (res == 0 && sock_err == EINPROGRESS)
    278       return;  // Not connected yet, just a spurious FD watch wakeup.
    279     if (res == 0 && sock_err == 0) {
    280       ReadPeerCredentials();
    281       state_ = State::kConnected;
    282       return event_listener_->OnConnect(this, true /* connected */);
    283     }
    284     last_error_ = sock_err;
    285     Shutdown(false);
    286     return event_listener_->OnConnect(this, false /* connected */);
    287   }
    288 
    289   // New incoming connection.
    290   if (state_ == State::kListening) {
    291     // There could be more than one incoming connection behind each FD watch
    292     // notification. Drain'em all.
    293     for (;;) {
    294       sockaddr_un cli_addr = {};
    295       socklen_t size = sizeof(cli_addr);
    296       base::ScopedFile new_fd(PERFETTO_EINTR(
    297           accept(*fd_, reinterpret_cast<sockaddr*>(&cli_addr), &size)));
    298       if (!new_fd)
    299         return;
    300       std::unique_ptr<UnixSocket> new_sock(new UnixSocket(
    301           event_listener_, task_runner_, std::move(new_fd), State::kConnected));
    302       event_listener_->OnNewIncomingConnection(this, std::move(new_sock));
    303     }
    304   }
    305 }
    306 
    307 bool UnixSocket::Send(const std::string& msg) {
    308   return Send(msg.c_str(), msg.size() + 1);
    309 }
    310 
    311 bool UnixSocket::Send(const void* msg,
    312                       size_t len,
    313                       int send_fd,
    314                       BlockingMode blocking_mode) {
    315   if (state_ != State::kConnected) {
    316     errno = last_error_ = ENOTCONN;
    317     return false;
    318   }
    319 
    320   msghdr msg_hdr = {};
    321   iovec iov = {const_cast<void*>(msg), len};
    322   msg_hdr.msg_iov = &iov;
    323   msg_hdr.msg_iovlen = 1;
    324   alignas(cmsghdr) char control_buf[256];
    325 
    326   if (send_fd > -1) {
    327     const CBufLenType control_buf_len =
    328         static_cast<CBufLenType>(CMSG_SPACE(sizeof(int)));
    329     PERFETTO_CHECK(control_buf_len <= sizeof(control_buf));
    330     memset(control_buf, 0, sizeof(control_buf));
    331     msg_hdr.msg_control = control_buf;
    332     msg_hdr.msg_controllen = control_buf_len;
    333     struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg_hdr);
    334     cmsg->cmsg_level = SOL_SOCKET;
    335     cmsg->cmsg_type = SCM_RIGHTS;
    336     cmsg->cmsg_len = CMSG_LEN(sizeof(int));
    337     memcpy(CMSG_DATA(cmsg), &send_fd, sizeof(int));
    338     msg_hdr.msg_controllen = cmsg->cmsg_len;
    339   }
    340 
    341   if (blocking_mode == BlockingMode::kBlocking)
    342     SetBlockingIO(true);
    343   const ssize_t sz = PERFETTO_EINTR(sendmsg(*fd_, &msg_hdr, kNoSigPipe));
    344   if (blocking_mode == BlockingMode::kBlocking)
    345     SetBlockingIO(false);
    346 
    347   if (sz == static_cast<ssize_t>(len)) {
    348     last_error_ = 0;
    349     return true;
    350   }
    351 
    352   // If sendmsg() succeds but the returned size is < |len| it means that the
    353   // endpoint disconnected in the middle of the read, and we managed to send
    354   // only a portion of the buffer. In this case we should just give up.
    355 
    356   if (sz < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
    357     // A genuine out-of-buffer. The client should retry or give up.
    358     // Man pages specify that EAGAIN and EWOULDBLOCK have the same semantic here
    359     // and clients should check for both.
    360     last_error_ = EAGAIN;
    361     return false;
    362   }
    363 
    364   // Either the the other endpoint disconnect (ECONNRESET) or some other error
    365   // happened.
    366   last_error_ = errno;
    367   PERFETTO_DPLOG("sendmsg() failed");
    368   Shutdown(true);
    369   return false;
    370 }
    371 
    372 void UnixSocket::Shutdown(bool notify) {
    373   base::WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
    374   if (notify) {
    375     if (state_ == State::kConnected) {
    376       task_runner_->PostTask([weak_ptr]() {
    377         if (weak_ptr)
    378           weak_ptr->event_listener_->OnDisconnect(weak_ptr.get());
    379       });
    380     } else if (state_ == State::kConnecting) {
    381       task_runner_->PostTask([weak_ptr]() {
    382         if (weak_ptr)
    383           weak_ptr->event_listener_->OnConnect(weak_ptr.get(), false);
    384       });
    385     }
    386   }
    387 
    388   if (fd_) {
    389     shutdown(*fd_, SHUT_RDWR);
    390     task_runner_->RemoveFileDescriptorWatch(*fd_);
    391     fd_.reset();
    392   }
    393   state_ = State::kDisconnected;
    394 }
    395 
    396 size_t UnixSocket::Receive(void* msg, size_t len, base::ScopedFile* recv_fd) {
    397   if (state_ != State::kConnected) {
    398     last_error_ = ENOTCONN;
    399     return 0;
    400   }
    401 
    402   msghdr msg_hdr = {};
    403   iovec iov = {msg, len};
    404   msg_hdr.msg_iov = &iov;
    405   msg_hdr.msg_iovlen = 1;
    406   alignas(cmsghdr) char control_buf[256];
    407 
    408   if (recv_fd) {
    409     msg_hdr.msg_control = control_buf;
    410     msg_hdr.msg_controllen = static_cast<CBufLenType>(CMSG_SPACE(sizeof(int)));
    411     PERFETTO_CHECK(msg_hdr.msg_controllen <= sizeof(control_buf));
    412   }
    413   const ssize_t sz = PERFETTO_EINTR(recvmsg(*fd_, &msg_hdr, kNoSigPipe));
    414   if (sz < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
    415     last_error_ = EAGAIN;
    416     return 0;
    417   }
    418   if (sz <= 0) {
    419     last_error_ = errno;
    420     Shutdown(true);
    421     return 0;
    422   }
    423   PERFETTO_CHECK(static_cast<size_t>(sz) <= len);
    424 
    425   int* fds = nullptr;
    426   uint32_t fds_len = 0;
    427 
    428   if (msg_hdr.msg_controllen > 0) {
    429     for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg_hdr); cmsg;
    430          cmsg = CMSG_NXTHDR(&msg_hdr, cmsg)) {
    431       const size_t payload_len = cmsg->cmsg_len - CMSG_LEN(0);
    432       if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
    433         PERFETTO_DCHECK(payload_len % sizeof(int) == 0u);
    434         PERFETTO_DCHECK(fds == nullptr);
    435         fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
    436         fds_len = static_cast<uint32_t>(payload_len / sizeof(int));
    437       }
    438     }
    439   }
    440 
    441   if (msg_hdr.msg_flags & MSG_TRUNC || msg_hdr.msg_flags & MSG_CTRUNC) {
    442     for (size_t i = 0; fds && i < fds_len; ++i)
    443       close(fds[i]);
    444     last_error_ = EMSGSIZE;
    445     Shutdown(true);
    446     return 0;
    447   }
    448 
    449   for (size_t i = 0; fds && i < fds_len; ++i) {
    450     if (recv_fd && i == 0) {
    451       recv_fd->reset(fds[i]);
    452     } else {
    453       close(fds[i]);
    454     }
    455   }
    456 
    457   last_error_ = 0;
    458   return static_cast<size_t>(sz);
    459 }
    460 
    461 std::string UnixSocket::ReceiveString(size_t max_length) {
    462   std::unique_ptr<char[]> buf(new char[max_length + 1]);
    463   size_t rsize = Receive(buf.get(), max_length);
    464   PERFETTO_CHECK(static_cast<size_t>(rsize) <= max_length);
    465   buf[static_cast<size_t>(rsize)] = '\0';
    466   return std::string(buf.get());
    467 }
    468 
    469 void UnixSocket::NotifyConnectionState(bool success) {
    470   if (!success)
    471     Shutdown(false);
    472 
    473   base::WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
    474   task_runner_->PostTask([weak_ptr, success]() {
    475     if (weak_ptr)
    476       weak_ptr->event_listener_->OnConnect(weak_ptr.get(), success);
    477   });
    478 }
    479 
    480 void UnixSocket::SetBlockingIO(bool is_blocking) {
    481   int flags = fcntl(*fd_, F_GETFL, 0);
    482   if (!is_blocking) {
    483     flags |= O_NONBLOCK;
    484   } else {
    485     flags &= ~static_cast<int>(O_NONBLOCK);
    486   }
    487   bool fcntl_res = fcntl(fd(), F_SETFL, flags);
    488   PERFETTO_CHECK(fcntl_res == 0);
    489 }
    490 
    491 UnixSocket::EventListener::~EventListener() {}
    492 void UnixSocket::EventListener::OnNewIncomingConnection(
    493     UnixSocket*,
    494     std::unique_ptr<UnixSocket>) {}
    495 void UnixSocket::EventListener::OnConnect(UnixSocket*, bool) {}
    496 void UnixSocket::EventListener::OnDisconnect(UnixSocket*) {}
    497 void UnixSocket::EventListener::OnDataAvailable(UnixSocket*) {}
    498 
    499 }  // namespace ipc
    500 }  // namespace perfetto
    501