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