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 #ifndef INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_ 18 #define INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_ 19 20 #include <stdint.h> 21 #include <sys/types.h> 22 23 #include <memory> 24 #include <string> 25 26 #include "perfetto/base/build_config.h" 27 #include "perfetto/base/export.h" 28 #include "perfetto/base/logging.h" 29 #include "perfetto/ext/base/scoped_file.h" 30 #include "perfetto/ext/base/utils.h" 31 #include "perfetto/ext/base/weak_ptr.h" 32 33 struct msghdr; 34 35 namespace perfetto { 36 namespace base { 37 38 // Define the SocketHandle and ScopedSocketHandle types. 39 // On POSIX OSes, a SocketHandle is really just an int (a file descriptor). 40 // On Windows, sockets are have their own type (SOCKET) which is neither a 41 // HANDLE nor an int. However Windows SOCKET(s) can have a event HANDLE attached 42 // to them (which in Perfetto is a PlatformHandle), and that can be used in 43 // WaitForMultipleObjects, hence in base::TaskRunner.AddFileDescriptorWatch(). 44 45 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 46 // uintptr_t really reads as SOCKET here (Windows headers typedef to that). 47 // As usual we don't just use SOCKET here to avoid leaking Windows.h includes 48 // in our headers. 49 using SocketHandle = uintptr_t; // SOCKET 50 int CloseSocket(SocketHandle); // A wrapper around ::closesocket(). 51 using ScopedSocketHandle = 52 ScopedResource<SocketHandle, CloseSocket, static_cast<SocketHandle>(-1)>; 53 #else 54 using SocketHandle = int; 55 using ScopedSocketHandle = ScopedFile; 56 #endif 57 58 class TaskRunner; 59 60 // Use arbitrarily high values to avoid that some code accidentally ends up 61 // assuming that these enum values match the sysroot's SOCK_xxx defines rather 62 // than using GetSockType() / GetSockFamily(). 63 enum class SockType { kStream = 100, kDgram, kSeqPacket }; 64 enum class SockFamily { kUnix = 200, kInet, kInet6 }; 65 66 // Controls the getsockopt(SO_PEERCRED) behavior, which allows to obtain the 67 // peer credentials. 68 enum class SockPeerCredMode { 69 // Obtain the peer credentials immediatley after connection and cache them. 70 kReadOnConnect = 0, 71 72 // Don't read peer credentials at all. Calls to peer_uid()/peer_pid() will 73 // hit a DCHECK and return kInvalidUid/Pid in release builds. 74 kIgnore = 1, 75 76 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 77 kDefault = kIgnore, 78 #else 79 kDefault = kReadOnConnect, 80 #endif 81 }; 82 83 // UnixSocketRaw is a basic wrapper around sockets. It exposes wrapper 84 // methods that take care of most common pitfalls (e.g., marking fd as 85 // O_CLOEXEC, avoiding SIGPIPE, properly handling partial writes). It is used as 86 // a building block for the more sophisticated UnixSocket class which depends 87 // on base::TaskRunner. 88 class UnixSocketRaw { 89 public: 90 // Creates a new unconnected unix socket. 91 static UnixSocketRaw CreateMayFail(SockFamily family, SockType type); 92 93 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 94 // Crates a pair of connected sockets. 95 static std::pair<UnixSocketRaw, UnixSocketRaw> CreatePairPosix(SockFamily, 96 SockType); 97 #endif 98 99 // Creates an uninitialized unix socket. 100 UnixSocketRaw(); 101 102 // Creates a unix socket adopting an existing file descriptor. This is 103 // typically used to inherit fds from init via environment variables. 104 UnixSocketRaw(ScopedSocketHandle, SockFamily, SockType); 105 106 ~UnixSocketRaw() = default; 107 UnixSocketRaw(UnixSocketRaw&&) noexcept = default; 108 UnixSocketRaw& operator=(UnixSocketRaw&&) = default; 109 110 bool Bind(const std::string& socket_name); 111 bool Listen(); 112 bool Connect(const std::string& socket_name); 113 bool SetTxTimeout(uint32_t timeout_ms); 114 bool SetRxTimeout(uint32_t timeout_ms); 115 void Shutdown(); 116 void SetBlocking(bool); 117 void DcheckIsBlocking(bool expected) const; // No-op on release and Win. 118 void RetainOnExec(); type()119 SockType type() const { return type_; } family()120 SockFamily family() const { return family_; } fd()121 SocketHandle fd() const { return *fd_; } 122 explicit operator bool() const { return !!fd_; } 123 124 // This is the handle that passed to TaskRunner.AddFileDescriptorWatch(). 125 // On UNIX this is just the socket FD. On Windows, we need to create a 126 // dedicated event object. watch_handle()127 PlatformHandle watch_handle() const { 128 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 129 return *event_handle_; 130 #else 131 return *fd_; 132 #endif 133 } 134 ReleaseFd()135 ScopedSocketHandle ReleaseFd() { return std::move(fd_); } 136 137 // |send_fds| and |num_fds| are ignored on Windows. 138 ssize_t Send(const void* msg, 139 size_t len, 140 const int* send_fds = nullptr, 141 size_t num_fds = 0); 142 SendStr(const std::string & str)143 ssize_t SendStr(const std::string& str) { 144 return Send(str.data(), str.size()); 145 } 146 147 // |fd_vec| and |max_files| are ignored on Windows. 148 ssize_t Receive(void* msg, 149 size_t len, 150 ScopedFile* fd_vec = nullptr, 151 size_t max_files = 0); 152 153 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 154 // UNIX-specific helpers to deal with SCM_RIGHTS. 155 156 // Re-enter sendmsg until all the data has been sent or an error occurs. 157 // TODO(fmayer): Figure out how to do timeouts here for heapprofd. 158 ssize_t SendMsgAllPosix(struct msghdr* msg); 159 160 // Exposed for testing only. 161 // Update msghdr so subsequent sendmsg will send data that remains after n 162 // bytes have already been sent. 163 static void ShiftMsgHdrPosix(size_t n, struct msghdr* msg); 164 #endif 165 166 private: 167 UnixSocketRaw(SockFamily, SockType); 168 169 UnixSocketRaw(const UnixSocketRaw&) = delete; 170 UnixSocketRaw& operator=(const UnixSocketRaw&) = delete; 171 172 ScopedSocketHandle fd_; 173 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 174 ScopedPlatformHandle event_handle_; 175 #endif 176 SockFamily family_ = SockFamily::kUnix; 177 SockType type_ = SockType::kStream; 178 uint32_t tx_timeout_ms_ = 0; 179 }; 180 181 // A non-blocking UNIX domain socket. Allows also to transfer file descriptors. 182 // None of the methods in this class are blocking. 183 // The main design goal is making strong guarantees on the EventListener 184 // callbacks, in order to avoid ending in some undefined state. 185 // In case of any error it will aggressively just shut down the socket and 186 // notify the failure with OnConnect(false) or OnDisconnect() depending on the 187 // state of the socket (see below). 188 // EventListener callbacks stop happening as soon as the instance is destroyed. 189 // 190 // Lifecycle of a client socket: 191 // 192 // Connect() 193 // | 194 // +------------------+------------------+ 195 // | (success) | (failure or Shutdown()) 196 // V V 197 // OnConnect(true) OnConnect(false) 198 // | 199 // V 200 // OnDataAvailable() 201 // | 202 // V 203 // OnDisconnect() (failure or shutdown) 204 // 205 // 206 // Lifecycle of a server socket: 207 // 208 // Listen() --> returns false in case of errors. 209 // | 210 // V 211 // OnNewIncomingConnection(new_socket) 212 // 213 // (|new_socket| inherits the same EventListener) 214 // | 215 // V 216 // OnDataAvailable() 217 // | (failure or Shutdown()) 218 // V 219 // OnDisconnect() 220 class PERFETTO_EXPORT UnixSocket { 221 public: 222 class EventListener { 223 public: 224 virtual ~EventListener(); 225 226 // After Listen(). 227 virtual void OnNewIncomingConnection( 228 UnixSocket* self, 229 std::unique_ptr<UnixSocket> new_connection); 230 231 // After Connect(), whether successful or not. 232 virtual void OnConnect(UnixSocket* self, bool connected); 233 234 // After a successful Connect() or OnNewIncomingConnection(). Either the 235 // other endpoint did disconnect or some other error happened. 236 virtual void OnDisconnect(UnixSocket* self); 237 238 // Whenever there is data available to Receive(). Note that spurious FD 239 // watch events are possible, so it is possible that Receive() soon after 240 // OnDataAvailable() returns 0 (just ignore those). 241 virtual void OnDataAvailable(UnixSocket* self); 242 }; 243 244 enum class State { 245 kDisconnected = 0, // Failed connection, peer disconnection or Shutdown(). 246 kConnecting, // Soon after Connect(), before it either succeeds or fails. 247 kConnected, // After a successful Connect(). 248 kListening // After Listen(), until Shutdown(). 249 }; 250 251 // Creates a socket and starts listening. If SockFamily::kUnix and 252 // |socket_name| starts with a '@', an abstract UNIX dmoain socket will be 253 // created instead of a filesystem-linked UNIX socket (Linux/Android only). 254 // If SockFamily::kInet, |socket_name| is host:port (e.g., "1.2.3.4:8000"). 255 // If SockFamily::kInet6, |socket_name| is [host]:port (e.g., "[::1]:8000"). 256 // Returns nullptr if the socket creation or bind fails. If listening fails, 257 // (e.g. if another socket with the same name is already listening) the 258 // returned socket will have is_listening() == false. 259 static std::unique_ptr<UnixSocket> Listen(const std::string& socket_name, 260 EventListener*, 261 TaskRunner*, 262 SockFamily, 263 SockType); 264 265 // Attaches to a pre-existing socket. The socket must have been created in 266 // SOCK_STREAM mode and the caller must have called bind() on it. 267 static std::unique_ptr<UnixSocket> Listen(ScopedSocketHandle, 268 EventListener*, 269 TaskRunner*, 270 SockFamily, 271 SockType); 272 273 // Creates a Unix domain socket and connects to the listening endpoint. 274 // Returns always an instance. EventListener::OnConnect(bool success) will 275 // be called always, whether the connection succeeded or not. 276 static std::unique_ptr<UnixSocket> Connect( 277 const std::string& socket_name, 278 EventListener*, 279 TaskRunner*, 280 SockFamily, 281 SockType, 282 SockPeerCredMode = SockPeerCredMode::kDefault); 283 284 // Constructs a UnixSocket using the given connected socket. 285 static std::unique_ptr<UnixSocket> AdoptConnected( 286 ScopedSocketHandle, 287 EventListener*, 288 TaskRunner*, 289 SockFamily, 290 SockType, 291 SockPeerCredMode = SockPeerCredMode::kDefault); 292 293 UnixSocket(const UnixSocket&) = delete; 294 UnixSocket& operator=(const UnixSocket&) = delete; 295 // Cannot be easily moved because of tasks from the FileDescriptorWatch. 296 UnixSocket(UnixSocket&&) = delete; 297 UnixSocket& operator=(UnixSocket&&) = delete; 298 299 // This class gives the hard guarantee that no callback is called on the 300 // passed EventListener immediately after the object has been destroyed. 301 // Any queued callback will be silently dropped. 302 ~UnixSocket(); 303 304 // Shuts down the current connection, if any. If the socket was Listen()-ing, 305 // stops listening. The socket goes back to kNotInitialized state, so it can 306 // be reused with Listen() or Connect(). 307 void Shutdown(bool notify); 308 SetTxTimeout(uint32_t timeout_ms)309 void SetTxTimeout(uint32_t timeout_ms) { 310 PERFETTO_CHECK(sock_raw_.SetTxTimeout(timeout_ms)); 311 } SetRxTimeout(uint32_t timeout_ms)312 void SetRxTimeout(uint32_t timeout_ms) { 313 PERFETTO_CHECK(sock_raw_.SetRxTimeout(timeout_ms)); 314 } 315 // Returns true is the message was queued, false if there was no space in the 316 // output buffer, in which case the client should retry or give up. 317 // If any other error happens the socket will be shutdown and 318 // EventListener::OnDisconnect() will be called. 319 // If the socket is not connected, Send() will just return false. 320 // Does not append a null string terminator to msg in any case. 321 bool Send(const void* msg, size_t len, const int* send_fds, size_t num_fds); 322 323 inline bool Send(const void* msg, size_t len, int send_fd = -1) { 324 if (send_fd != -1) 325 return Send(msg, len, &send_fd, 1); 326 return Send(msg, len, nullptr, 0); 327 } 328 SendStr(const std::string & msg)329 inline bool SendStr(const std::string& msg) { 330 return Send(msg.data(), msg.size(), -1); 331 } 332 333 // Returns the number of bytes (<= |len|) written in |msg| or 0 if there 334 // is no data in the buffer to read or an error occurs (in which case a 335 // EventListener::OnDisconnect() will follow). 336 // If the ScopedFile pointer is not null and a FD is received, it moves the 337 // received FD into that. If a FD is received but the ScopedFile pointer is 338 // null, the FD will be automatically closed. 339 size_t Receive(void* msg, size_t len, ScopedFile*, size_t max_files = 1); 340 Receive(void * msg,size_t len)341 inline size_t Receive(void* msg, size_t len) { 342 return Receive(msg, len, nullptr, 0); 343 } 344 345 // Only for tests. This is slower than Receive() as it requires a heap 346 // allocation and a copy for the std::string. Guarantees that the returned 347 // string is null terminated even if the underlying message sent by the peer 348 // is not. 349 std::string ReceiveString(size_t max_length = 1024); 350 is_connected()351 bool is_connected() const { return state_ == State::kConnected; } is_listening()352 bool is_listening() const { return state_ == State::kListening; } fd()353 SocketHandle fd() const { return sock_raw_.fd(); } 354 355 // User ID of the peer, as returned by the kernel. If the client disconnects 356 // and the socket goes into the kDisconnected state, it retains the uid of 357 // the last peer. 358 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 359 uid_t peer_uid_posix(bool skip_check_for_testing = false) const { 360 PERFETTO_DCHECK((!is_listening() && peer_uid_ != kInvalidUid) || 361 skip_check_for_testing); 362 363 return peer_uid_; 364 } 365 #endif 366 367 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 368 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 369 // Process ID of the peer, as returned by the kernel. If the client 370 // disconnects and the socket goes into the kDisconnected state, it 371 // retains the pid of the last peer. 372 // 373 // This is only available on Linux / Android. 374 pid_t peer_pid_linux(bool skip_check_for_testing = false) const { 375 PERFETTO_DCHECK((!is_listening() && peer_pid_ != kInvalidPid) || 376 skip_check_for_testing); 377 return peer_pid_; 378 } 379 #endif 380 381 // This makes the UnixSocket unusable. 382 UnixSocketRaw ReleaseSocket(); 383 384 private: 385 UnixSocket(EventListener*, 386 TaskRunner*, 387 SockFamily, 388 SockType, 389 SockPeerCredMode); 390 UnixSocket(EventListener*, 391 TaskRunner*, 392 ScopedSocketHandle, 393 State, 394 SockFamily, 395 SockType, 396 SockPeerCredMode); 397 398 // Called once by the corresponding public static factory methods. 399 void DoConnect(const std::string& socket_name); 400 401 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 402 void ReadPeerCredentialsPosix(); 403 #endif 404 405 void OnEvent(); 406 void NotifyConnectionState(bool success); 407 408 UnixSocketRaw sock_raw_; 409 State state_ = State::kDisconnected; 410 SockPeerCredMode peer_cred_mode_ = SockPeerCredMode::kDefault; 411 412 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 413 uid_t peer_uid_ = kInvalidUid; 414 #endif 415 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 416 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 417 pid_t peer_pid_ = kInvalidPid; 418 #endif 419 EventListener* const event_listener_; 420 TaskRunner* const task_runner_; 421 WeakPtrFactory<UnixSocket> weak_ptr_factory_; // Keep last. 422 }; 423 424 } // namespace base 425 } // namespace perfetto 426 427 #endif // INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_ 428