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