1 /*
2 * Copyright (C) 2016 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 // TODO: We can't use std::shared_ptr on the older guests due to HALs.
18
19 #ifndef CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_H_
20 #define CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_H_
21
22 #ifdef __linux__
23 #include <sys/epoll.h>
24 #include <sys/eventfd.h>
25 #endif
26 #include <sys/inotify.h>
27 #include <sys/ioctl.h>
28 #include <sys/mman.h>
29 #include <sys/select.h>
30 #include <sys/socket.h>
31 #include <sys/stat.h>
32 #include <sys/time.h>
33 #include <sys/types.h>
34 #include <sys/uio.h>
35 #include <sys/un.h>
36
37 #include <chrono>
38 #include <memory>
39 #include <sstream>
40 #include <string>
41 #include <utility>
42 #include <vector>
43
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <string.h>
47 #include <termios.h>
48 #include <unistd.h>
49
50 #include <android-base/cmsg.h>
51
52 #ifdef __linux__
53 #include <linux/vm_sockets.h>
54 #endif
55
56 #include "common/libs/utils/result.h"
57
58 /**
59 * Classes to to enable safe access to files.
60 * POSIX kernels have an unfortunate habit of recycling file descriptors.
61 * That can cause problems like http://b/26121457 in code that doesn't manage
62 * file lifetimes properly. These classes implement an alternate interface
63 * that has some advantages:
64 *
65 * o References to files are tightly controlled
66 * o Files are auto-closed if they go out of scope
67 * o Files are life-time aware. It is impossible to close the instance twice.
68 * o File descriptors are always initialized. By default the descriptor is
69 * set to a closed instance.
70 *
71 * These classes are designed to mimic to POSIX interface as closely as
72 * possible. Specifically, they don't attempt to track the type of file
73 * descriptors and expose only the valid operations. This is by design, since
74 * it makes it easier to convert existing code to SharedFDs and avoids the
75 * possibility that new POSIX functionality will lead to large refactorings.
76 */
77 namespace cuttlefish {
78
79 struct PollSharedFd;
80 class Epoll;
81 class FileInstance;
82 struct VhostUserVsockCid;
83 struct VsockCid;
84
85 /**
86 * Counted reference to a FileInstance.
87 *
88 * This is also the place where most new FileInstances are created. The creation
89 * methods correspond to the underlying POSIX calls.
90 *
91 * SharedFDs can be compared and stored in STL containers. The semantics are
92 * slightly different from POSIX file descriptors:
93 *
94 * o The value of the SharedFD is the identity of its underlying FileInstance.
95 *
96 * o Each newly created SharedFD has a unique, closed FileInstance:
97 * SharedFD a, b;
98 * assert (a != b);
99 * a = b;
100 * assert(a == b);
101 *
102 * o The identity of the FileInstance is not affected by closing the file:
103 * SharedFD a, b;
104 * set<SharedFD> s;
105 * s.insert(a);
106 * assert(s.count(a) == 1);
107 * assert(s.count(b) == 0);
108 * a->Close();
109 * assert(s.count(a) == 1);
110 * assert(s.count(b) == 0);
111 *
112 * o FileInstances are never visibly recycled.
113 *
114 * o If all of the SharedFDs referring to a FileInstance go out of scope the
115 * file is closed and the FileInstance is recycled.
116 *
117 * Creation methods must ensure that no references to the new file descriptor
118 * escape. The underlying FileInstance should have the only reference to the
119 * file descriptor. Any method that needs to know the fd must be in either
120 * SharedFD or FileInstance.
121 *
122 * SharedFDs always have an underlying FileInstance, so all of the method
123 * calls are safe in accordance with the null object pattern.
124 *
125 * Errors on system calls that create new FileInstances, such as Open, are
126 * reported with a new, closed FileInstance with the errno set.
127 */
128 class SharedFD {
129 // Give WeakFD access to the underlying shared_ptr.
130 friend class WeakFD;
131 public:
132 inline SharedFD();
SharedFD(const std::shared_ptr<FileInstance> & in)133 SharedFD(const std::shared_ptr<FileInstance>& in) : value_(in) {}
134 SharedFD(SharedFD const&) = default;
135 SharedFD(SharedFD&& other);
136 SharedFD& operator=(SharedFD const&) = default;
137 SharedFD& operator=(SharedFD&& other);
138 // Reference the listener as a FileInstance to make this FD type agnostic.
139 static SharedFD Accept(const FileInstance& listener, struct sockaddr* addr,
140 socklen_t* addrlen);
141 static SharedFD Accept(const FileInstance& listener);
142 static SharedFD Dup(int unmanaged_fd);
143 // All SharedFDs have the O_CLOEXEC flag after creation. To remove use the
144 // Fcntl or Dup functions.
145 static SharedFD Open(const char* pathname, int flags, mode_t mode = 0);
146 static SharedFD Open(const std::string& pathname, int flags, mode_t mode = 0);
147 static SharedFD InotifyFd();
148 static SharedFD Creat(const std::string& pathname, mode_t mode);
149 static int Fchdir(SharedFD);
150 static Result<SharedFD> Fifo(const std::string& pathname, mode_t mode);
151 static bool Pipe(SharedFD* fd0, SharedFD* fd1);
152 #ifdef __linux__
153 static SharedFD Event(int initval = 0, int flags = 0);
154 #endif
155 static SharedFD MemfdCreate(const std::string& name, unsigned int flags = 0);
156 static SharedFD MemfdCreateWithData(const std::string& name, const std::string& data, unsigned int flags = 0);
157 static SharedFD Mkstemp(std::string* path);
158 static int Poll(PollSharedFd* fds, size_t num_fds, int timeout);
159 static int Poll(std::vector<PollSharedFd>& fds, int timeout);
160 static bool SocketPair(int domain, int type, int protocol, SharedFD* fd0,
161 SharedFD* fd1);
162 static Result<std::pair<SharedFD, SharedFD>> SocketPair(int domain, int type,
163 int protocol);
164 static SharedFD Socket(int domain, int socket_type, int protocol);
165 static SharedFD SocketLocalClient(const std::string& name, bool is_abstract,
166 int in_type);
167 static SharedFD SocketLocalClient(const std::string& name, bool is_abstract,
168 int in_type, int timeout_seconds);
169 static SharedFD SocketLocalClient(int port, int type);
170 static SharedFD SocketClient(const std::string& host, int port,
171 int type, std::chrono::seconds timeout = std::chrono::seconds(0));
172 static SharedFD Socket6Client(const std::string& host, const std::string& interface, int port,
173 int type, std::chrono::seconds timeout = std::chrono::seconds(0));
174 static SharedFD SocketLocalServer(const std::string& name, bool is_abstract,
175 int in_type, mode_t mode);
176 static SharedFD SocketLocalServer(int port, int type);
177
178 #ifdef __linux__
179 // For binding in vsock, svm_cid from `cid` param would be either
180 // VMADDR_CID_ANY, VMADDR_CID_LOCAL, VMADDR_CID_HOST or their own CID, and it
181 // is used for indicating connections which it accepts from.
182 // * VMADDR_CID_ANY: accept from any
183 // * VMADDR_CID_LOCAL: accept from local
184 // * VMADDR_CID_HOST: accept from child vm
185 // * their own CID: accept from parent vm
186 // With vhost-user-vsock, it is basically similar to VMADDR_CID_HOST, but for
187 // now it has limitations that it should bind to a specific socket file which
188 // is for a certain cid. So for vhost-user-vsock, we need to specify the
189 // expected client's cid. That's why vhost_user_vsock_listening_cid is
190 // necessary.
191 // TODO: combining them when vhost-user-vsock impl supports a kind of
192 // VMADDR_CID_HOST
193 static SharedFD VsockServer(unsigned int port, int type,
194 std::optional<int> vhost_user_vsock_listening_cid,
195 unsigned int cid = VMADDR_CID_ANY);
196 static SharedFD VsockServer(
197 int type, std::optional<int> vhost_user_vsock_listening_cid);
198 static SharedFD VsockClient(unsigned int cid, unsigned int port, int type,
199 bool vhost_user);
200 static std::string GetVhostUserVsockServerAddr(
201 unsigned int port, int vhost_user_vsock_listening_cid);
202 static std::string GetVhostUserVsockClientAddr(int cid);
203 #endif
204
205 bool operator==(const SharedFD& rhs) const { return value_ == rhs.value_; }
206
207 bool operator!=(const SharedFD& rhs) const { return value_ != rhs.value_; }
208
209 bool operator<(const SharedFD& rhs) const { return value_ < rhs.value_; }
210
211 bool operator<=(const SharedFD& rhs) const { return value_ <= rhs.value_; }
212
213 bool operator>(const SharedFD& rhs) const { return value_ > rhs.value_; }
214
215 bool operator>=(const SharedFD& rhs) const { return value_ >= rhs.value_; }
216
217 std::shared_ptr<FileInstance> operator->() const { return value_; }
218
219 const FileInstance& operator*() const { return *value_; }
220
221 FileInstance& operator*() { return *value_; }
222
223 private:
224 static SharedFD ErrorFD(int error);
225
226 std::shared_ptr<FileInstance> value_;
227 };
228
229 /**
230 * A non-owning reference to a FileInstance. The referenced FileInstance needs
231 * to be managed by a SharedFD. A WeakFD needs to be converted to a SharedFD to
232 * access the underlying FileInstance.
233 */
234 class WeakFD {
235 public:
WeakFD(SharedFD shared_fd)236 WeakFD(SharedFD shared_fd) : value_(shared_fd.value_) {}
237
238 // Creates a new SharedFD object that shares ownership of the underlying fd.
239 // Callers need to check that the returned SharedFD is open before using it.
240 SharedFD lock() const;
241
242 private:
243 std::weak_ptr<FileInstance> value_;
244 };
245
246 // Provides RAII semantics for memory mappings, preventing memory leaks. It does
247 // not however prevent use-after-free errors since the underlying pointer can be
248 // extracted and could survive this object.
249 class ScopedMMap {
250 public:
251 ScopedMMap();
252 ScopedMMap(void* ptr, size_t size);
253 ScopedMMap(const ScopedMMap& other) = delete;
254 ScopedMMap& operator=(const ScopedMMap& other) = delete;
255 ScopedMMap(ScopedMMap&& other);
256
257 ~ScopedMMap();
258
get()259 void* get() { return ptr_; }
get()260 const void* get() const { return ptr_; }
len()261 size_t len() const { return len_; }
262
263 operator bool() const { return ptr_ != MAP_FAILED; }
264
265 // Checks whether the interval [offset, offset + length) is contained within
266 // [0, len_)
WithinBounds(size_t offset,size_t length)267 bool WithinBounds(size_t offset, size_t length) const {
268 // Don't add offset + len to avoid overflow
269 return offset < len_ && len_ - offset >= length;
270 }
271
272 private:
273 void* ptr_ = MAP_FAILED;
274 size_t len_;
275 };
276
277 /**
278 * Tracks the lifetime of a file descriptor and provides methods to allow
279 * callers to use the file without knowledge of the underlying descriptor
280 * number.
281 *
282 * FileInstances have two states: Open and Closed. They may start in either
283 * state. However, once a FileIntance enters the Closed state it cannot be
284 * reopened.
285 *
286 * Construction of FileInstances is limited to select classes to avoid
287 * escaping file descriptors. At this point SharedFD is the only class
288 * that has access. We may eventually have ScopedFD and WeakFD.
289 */
290 class FileInstance {
291 // Give SharedFD access to the aliasing constructor.
292 friend class SharedFD;
293 friend class Epoll;
294
295 public:
~FileInstance()296 virtual ~FileInstance() { Close(); }
297
298 // This can't be a singleton because our shared_ptr's aren't thread safe.
299 static std::shared_ptr<FileInstance> ClosedInstance();
300
301 int Bind(const struct sockaddr* addr, socklen_t addrlen);
302 int Connect(const struct sockaddr* addr, socklen_t addrlen);
303 int ConnectWithTimeout(const struct sockaddr* addr, socklen_t addrlen,
304 struct timeval* timeout);
305 void Close();
306
307 bool Chmod(mode_t mode);
308
309 // Returns true if the entire input was copied.
310 // Otherwise an error will be set either on this file or the input.
311 // The non-const reference is needed to avoid binding this to a particular
312 // reference type.
313 bool CopyFrom(FileInstance& in, size_t length, FileInstance* stop = nullptr);
314 // Same as CopyFrom, but reads from input until EOF is reached.
315 bool CopyAllFrom(FileInstance& in, FileInstance* stop = nullptr);
316
317 int UNMANAGED_Dup();
318 int UNMANAGED_Dup2(int newfd);
319 int Fchdir();
320 int Fcntl(int command, int value);
321 int Fsync();
322
323 Result<void> Flock(int operation);
324
GetErrno()325 int GetErrno() const { return errno_; }
326 int GetSockName(struct sockaddr* addr, socklen_t* addrlen);
327
328 #ifdef __linux__
329 unsigned int VsockServerPort();
330 #endif
331
332 int Ioctl(int request, void* val = nullptr);
IsOpen()333 bool IsOpen() const { return fd_ != -1; }
334
335 // in probably isn't modified, but the API spec doesn't have const.
336 bool IsSet(fd_set* in) const;
337
338 // whether this is a regular file or not
IsRegular()339 bool IsRegular() const { return is_regular_file_; }
340
341 /**
342 * Adds a hard link to a file descriptor, based on the current working
343 * directory of the process or to some absolute path.
344 *
345 * https://www.man7.org/linux/man-pages/man2/linkat.2.html
346 *
347 * Using this on a file opened with O_TMPFILE can link it into the filesystem.
348 */
349 // Used with O_TMPFILE files to attach them to the filesystem.
350 int LinkAtCwd(const std::string& path);
351 int Listen(int backlog);
352 static void Log(const char* message);
353 off_t LSeek(off_t offset, int whence);
354 ssize_t Recv(void* buf, size_t len, int flags);
355 ssize_t RecvMsg(struct msghdr* msg, int flags);
356 ssize_t Read(void* buf, size_t count);
357 #ifdef __linux__
358 int EventfdRead(eventfd_t* value);
359 #endif
360 ssize_t Send(const void* buf, size_t len, int flags);
361 ssize_t SendMsg(const struct msghdr* msg, int flags);
362
363 template <typename... Args>
SendFileDescriptors(const void * buf,size_t len,Args &&...sent_fds)364 ssize_t SendFileDescriptors(const void* buf, size_t len, Args&&... sent_fds) {
365 std::vector<int> fds;
366 android::base::Append(fds, std::forward<int>(sent_fds->fd_)...);
367 errno = 0;
368 auto ret = android::base::SendFileDescriptorVector(fd_, buf, len, fds);
369 errno_ = errno;
370 return ret;
371 }
372
373 int Shutdown(int how);
374 void Set(fd_set* dest, int* max_index) const;
375 int SetSockOpt(int level, int optname, const void* optval, socklen_t optlen);
376 int GetSockOpt(int level, int optname, void* optval, socklen_t* optlen);
377 int SetTerminalRaw();
378 std::string StrError() const;
379 ScopedMMap MMap(void* addr, size_t length, int prot, int flags, off_t offset);
380 ssize_t Truncate(off_t length);
381 /*
382 * If the file is a regular file and the count is 0, Write() may detect
383 * error(s) by calling write(fd, buf, 0) declared in <unistd.h>. If detected,
384 * it will return -1. If not, 0 will be returned. For non-regular files such
385 * as socket or pipe, write(fd, buf, 0) is not specified. Write(), however,
386 * will do nothing and just return 0.
387 *
388 */
389 ssize_t Write(const void* buf, size_t count);
390 #ifdef __linux__
391 int EventfdWrite(eventfd_t value);
392 #endif
393 bool IsATTY();
394
395 int Futimens(const struct timespec times[2]);
396
397 // Returns the target of "/proc/getpid()/fd/" + std::to_string(fd_)
398 // if appropriate
399 Result<std::string> ProcFdLinkTarget() const;
400
401 // inotify related functions
402 int InotifyAddWatch(const std::string& pathname, uint32_t mask);
403 void InotifyRmWatch(int watch);
404
405 private:
406 FileInstance(int fd, int in_errno);
407 FileInstance* Accept(struct sockaddr* addr, socklen_t* addrlen) const;
408
409 int fd_;
410 int errno_;
411 std::string identity_;
412 bool is_regular_file_;
413 };
414
415 struct PollSharedFd {
416 SharedFD fd;
417 short events;
418 short revents;
419 };
420
421 /* Methods that need both a fully defined SharedFD and a fully defined
422 FileInstance. */
423
SharedFD()424 SharedFD::SharedFD() : value_(FileInstance::ClosedInstance()) {}
425
426 } // namespace cuttlefish
427
428 #endif // CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_H_
429