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