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