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
41namespace perfetto {
42namespace ipc {
43
44// TODO(primiano): Add ThreadChecker to methods of this class.
45
46namespace {
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)
51constexpr int kNoSigPipe = 0;
52#else
53constexpr 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)
58using CBufLenType = size_t;
59#else
60using CBufLenType = socklen_t;
61#endif
62
63bool 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
81base::ScopedFile CreateSocket() {
82  return base::ScopedFile(socket(AF_UNIX, SOCK_STREAM, 0));
83}
84
85}  // namespace
86
87// static
88base::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
108std::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
116std::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
125std::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
133UnixSocket::UnixSocket(EventListener* event_listener,
134                       base::TaskRunner* task_runner)
135    : UnixSocket(event_listener,
136                 task_runner,
137                 base::ScopedFile(),
138                 State::kDisconnected) {}
139
140UnixSocket::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
203UnixSocket::~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.
209void 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
248void 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
265void 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
307bool UnixSocket::Send(const std::string& msg) {
308  return Send(msg.c_str(), msg.size() + 1);
309}
310
311bool 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
372void 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
396size_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
461std::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
469void 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
480void 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
491UnixSocket::EventListener::~EventListener() {}
492void UnixSocket::EventListener::OnNewIncomingConnection(
493    UnixSocket*,
494    std::unique_ptr<UnixSocket>) {}
495void UnixSocket::EventListener::OnConnect(UnixSocket*, bool) {}
496void UnixSocket::EventListener::OnDisconnect(UnixSocket*) {}
497void UnixSocket::EventListener::OnDataAvailable(UnixSocket*) {}
498
499}  // namespace ipc
500}  // namespace perfetto
501