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
MakeSockAddr(const std::string & socket_name,sockaddr_un * addr,socklen_t * addr_size)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
CreateSocket()81 base::ScopedFile CreateSocket() {
82 return base::ScopedFile(socket(AF_UNIX, SOCK_STREAM, 0));
83 }
84
85 } // namespace
86
87 // static
CreateAndBind(const std::string & socket_name)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
Listen(const std::string & socket_name,EventListener * event_listener,base::TaskRunner * task_runner)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
Listen(base::ScopedFile socket_fd,EventListener * event_listener,base::TaskRunner * task_runner)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
Connect(const std::string & socket_name,EventListener * event_listener,base::TaskRunner * task_runner)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
UnixSocket(EventListener * event_listener,base::TaskRunner * task_runner)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
UnixSocket(EventListener * event_listener,base::TaskRunner * task_runner,base::ScopedFile adopt_fd,State adopt_state)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
~UnixSocket()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.
DoConnect(const std::string & socket_name)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
ReadPeerCredentials()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
OnEvent()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
Send(const std::string & msg)307 bool UnixSocket::Send(const std::string& msg) {
308 return Send(msg.c_str(), msg.size() + 1);
309 }
310
Send(const void * msg,size_t len,int send_fd,BlockingMode blocking_mode)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
Shutdown(bool notify)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
Receive(void * msg,size_t len,base::ScopedFile * recv_fd)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
ReceiveString(size_t max_length)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
NotifyConnectionState(bool success)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
SetBlockingIO(bool is_blocking)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
~EventListener()491 UnixSocket::EventListener::~EventListener() {}
OnNewIncomingConnection(UnixSocket *,std::unique_ptr<UnixSocket>)492 void UnixSocket::EventListener::OnNewIncomingConnection(
493 UnixSocket*,
494 std::unique_ptr<UnixSocket>) {}
OnConnect(UnixSocket *,bool)495 void UnixSocket::EventListener::OnConnect(UnixSocket*, bool) {}
OnDisconnect(UnixSocket *)496 void UnixSocket::EventListener::OnDisconnect(UnixSocket*) {}
OnDataAvailable(UnixSocket *)497 void UnixSocket::EventListener::OnDataAvailable(UnixSocket*) {}
498
499 } // namespace ipc
500 } // namespace perfetto
501