Android-cuttlefish cvd tool
shared_fd.h
Go to the documentation of this file.
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 <string_view>
42#include <utility>
43#include <vector>
44
45#include <errno.h>
46#include <fcntl.h>
47#include <string.h>
48#include <termios.h>
49#include <unistd.h>
50
51#include <android-base/cmsg.h>
52
53#ifdef __linux__
54#include <linux/vm_sockets.h>
55#endif
56
58
78namespace cuttlefish {
79
80struct PollSharedFd;
81class Epoll;
82class FileInstance;
83struct VhostUserVsockCid;
84struct VsockCid;
85
129class SharedFD {
130 // Give WeakFD access to the underlying shared_ptr.
131 friend class WeakFD;
132 public:
133 inline SharedFD();
134 SharedFD(const std::shared_ptr<FileInstance>& in) : value_(in) {}
135 SharedFD(SharedFD const&) = default;
136 SharedFD(SharedFD&& other);
137 SharedFD& operator=(SharedFD const&) = default;
138 SharedFD& operator=(SharedFD&& other);
139 // Reference the listener as a FileInstance to make this FD type agnostic.
140 static SharedFD Accept(const FileInstance& listener, struct sockaddr* addr,
141 socklen_t* addrlen);
142 static SharedFD Accept(const FileInstance& listener);
143 static SharedFD Dup(int unmanaged_fd);
144 // All SharedFDs have the O_CLOEXEC flag after creation. To remove use the
145 // Fcntl or Dup functions.
146 static SharedFD Open(const char* pathname, int flags, mode_t mode = 0);
147 static SharedFD Open(const std::string& pathname, int flags, mode_t mode = 0);
148 static SharedFD InotifyFd();
149 static SharedFD Creat(const std::string& pathname, mode_t mode);
150 static int Fchdir(SharedFD);
151 static Result<SharedFD> Fifo(const std::string& pathname, mode_t mode);
152 static bool Pipe(SharedFD* fd0, SharedFD* fd1);
153#ifdef __linux__
154 static SharedFD Event(int initval = 0, int flags = 0);
155 static SharedFD ShmOpen(const std::string& name, int oflag, int mode);
156#endif
157 static SharedFD MemfdCreate(const std::string& name, unsigned int flags = 0);
158 static SharedFD MemfdCreateWithData(const std::string& name, const std::string& data, unsigned int flags = 0);
159 static SharedFD Mkstemp(std::string* path);
161 std::string_view path, int flags = O_CLOEXEC);
162 static int Poll(PollSharedFd* fds, size_t num_fds, int timeout);
163 static int Poll(std::vector<PollSharedFd>& fds, int timeout);
164 static bool SocketPair(int domain, int type, int protocol, SharedFD* fd0,
165 SharedFD* fd1);
167 int protocol);
168 static SharedFD Socket(int domain, int socket_type, int protocol);
169 static SharedFD SocketLocalClient(const std::string& name, bool is_abstract,
170 int in_type);
171 static SharedFD SocketLocalClient(const std::string& name, bool is_abstract,
172 int in_type, int timeout_seconds);
173 static SharedFD SocketLocalClient(int port, int type);
174 static SharedFD SocketClient(const std::string& host, int port,
175 int type, std::chrono::seconds timeout = std::chrono::seconds(0));
176 static SharedFD Socket6Client(const std::string& host, const std::string& interface, int port,
177 int type, std::chrono::seconds timeout = std::chrono::seconds(0));
178 static SharedFD SocketLocalServer(const std::string& name, bool is_abstract,
179 int in_type, mode_t mode);
180 static SharedFD SocketLocalServer(int port, int type);
181
182#ifdef __linux__
183 // For binding in vsock, svm_cid from `cid` param would be either
184 // VMADDR_CID_ANY, VMADDR_CID_LOCAL, VMADDR_CID_HOST or their own CID, and it
185 // is used for indicating connections which it accepts from.
186 // * VMADDR_CID_ANY: accept from any
187 // * VMADDR_CID_LOCAL: accept from local
188 // * VMADDR_CID_HOST: accept from child vm
189 // * their own CID: accept from parent vm
190 // With vhost-user-vsock, it is basically similar to VMADDR_CID_HOST, but for
191 // now it has limitations that it should bind to a specific socket file which
192 // is for a certain cid. So for vhost-user-vsock, we need to specify the
193 // expected client's cid. That's why vhost_user_vsock_listening_cid is
194 // necessary.
195 // TODO: combining them when vhost-user-vsock impl supports a kind of
196 // VMADDR_CID_HOST
197 static SharedFD VsockServer(unsigned int port, int type,
198 std::optional<int> vhost_user_vsock_listening_cid,
199 unsigned int cid = VMADDR_CID_ANY);
200 static SharedFD VsockServer(
201 int type, std::optional<int> vhost_user_vsock_listening_cid);
202 static SharedFD VsockClient(unsigned int cid, unsigned int port, int type,
203 bool vhost_user);
204 static std::string GetVhostUserVsockServerAddr(
205 unsigned int port, int vhost_user_vsock_listening_cid);
206 static std::string GetVhostUserVsockClientAddr(int cid);
207#endif
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 bool operator>(const SharedFD& rhs) const { return value_ > rhs.value_; }
218
219 bool operator>=(const SharedFD& rhs) const { return value_ >= rhs.value_; }
220
221 std::shared_ptr<FileInstance> operator->() const { return value_; }
222
223 const FileInstance& operator*() const { return *value_; }
224
226
227 private:
228 static SharedFD ErrorFD(int error);
229
230 std::shared_ptr<FileInstance> value_;
231};
232
238class WeakFD {
239 public:
240 WeakFD(SharedFD shared_fd) : value_(shared_fd.value_) {}
241
242 // Creates a new SharedFD object that shares ownership of the underlying fd.
243 // Callers need to check that the returned SharedFD is open before using it.
244 SharedFD lock() const;
245
246 private:
247 std::weak_ptr<FileInstance> value_;
248};
249
250// Provides RAII semantics for memory mappings, preventing memory leaks. It does
251// not however prevent use-after-free errors since the underlying pointer can be
252// extracted and could survive this object.
254 public:
255 ScopedMMap();
256 ScopedMMap(void* ptr, size_t len);
257 ScopedMMap(const ScopedMMap& other) = delete;
258 ScopedMMap& operator=(const ScopedMMap& other) = delete;
259 ScopedMMap(ScopedMMap&& other);
260
261 ~ScopedMMap();
262
263 void* get() { return ptr_; }
264 const void* get() const { return ptr_; }
265 size_t len() const { return len_; }
266
267 operator bool() const { return ptr_ != MAP_FAILED; }
268
269 // Checks whether the interval [offset, offset + length) is contained within
270 // [0, len_)
271 bool WithinBounds(size_t offset, size_t length) const {
272 // Don't add offset + len to avoid overflow
273 return offset < len_ && len_ - offset >= length;
274 }
275
276 private:
277 void* ptr_ = MAP_FAILED;
278 size_t len_;
279};
280
295 // Give SharedFD access to the aliasing constructor.
296 friend class SharedFD;
297 friend class Epoll;
298
299 public:
300 virtual ~FileInstance() { Close(); }
301
302 // This can't be a singleton because our shared_ptr's aren't thread safe.
303 static std::shared_ptr<FileInstance> ClosedInstance();
304
305 int Bind(const struct sockaddr* addr, socklen_t addrlen);
306 int Connect(const struct sockaddr* addr, socklen_t addrlen);
307 int ConnectWithTimeout(const struct sockaddr* addr, socklen_t addrlen,
308 struct timeval* timeout);
309 void Close();
310
311 bool Chmod(mode_t mode);
312
313 // Returns true if the entire input was copied.
314 // Otherwise an error will be set either on this file or the input.
315 // The non-const reference is needed to avoid binding this to a particular
316 // reference type.
317 bool CopyFrom(FileInstance& in, size_t length, FileInstance* stop = nullptr);
318 // Same as CopyFrom, but reads from input until EOF is reached.
319 bool CopyAllFrom(FileInstance& in, FileInstance* stop = nullptr);
320
321 int UNMANAGED_Dup();
322 int UNMANAGED_Dup2(int newfd);
323 int Fchdir();
324 int Fcntl(int command, int value);
325 int Fsync();
326
327 Result<void> Flock(int operation);
328
329 int GetErrno() const { return errno_; }
330 int GetSockName(struct sockaddr* addr, socklen_t* addrlen);
331
332#ifdef __linux__
333 unsigned int VsockServerPort();
334#endif
335
336 int Ioctl(int request, void* val = nullptr);
337 bool IsOpen() const { return fd_ != -1; }
338
339 // in probably isn't modified, but the API spec doesn't have const.
340 bool IsSet(fd_set* in) const;
341
342 // whether this is a regular file or not
343 bool IsRegular() const { return is_regular_file_; }
344
353 // Used with O_TMPFILE files to attach them to the filesystem.
354 int LinkAtCwd(const std::string& path);
355 int Listen(int backlog);
356 static void Log(const char* message);
357 off_t LSeek(off_t offset, int whence);
358 ssize_t Recv(void* buf, size_t len, int flags);
359 ssize_t RecvMsg(struct msghdr* msg, int flags);
360 ssize_t Read(void* buf, size_t count);
361#ifdef __linux__
362 int EventfdRead(eventfd_t* value);
363#endif
364 ssize_t Send(const void* buf, size_t len, int flags);
365 ssize_t SendMsg(const struct msghdr* msg, int flags);
366
367 template <typename... Args>
368 ssize_t SendFileDescriptors(const void* buf, size_t len, Args&&... sent_fds) {
369 std::vector<int> fds;
370 android::base::Append(fds, std::forward<int>(sent_fds->fd_)...);
371 errno = 0;
372 auto ret = android::base::SendFileDescriptorVector(fd_, buf, len, fds);
373 errno_ = errno;
374 return ret;
375 }
376
377 int Shutdown(int how);
378 void Set(fd_set* dest, int* max_index) const;
379 int SetSockOpt(int level, int optname, const void* optval, socklen_t optlen);
380 int GetSockOpt(int level, int optname, void* optval, socklen_t* optlen);
381 int SetTerminalRaw();
382 std::string StrError() const;
383 ScopedMMap MMap(void* addr, size_t length, int prot, int flags, off_t offset);
384 ssize_t Truncate(off_t length);
385 /*
386 * If the file is a regular file and the count is 0, Write() may detect
387 * error(s) by calling write(fd, buf, 0) declared in <unistd.h>. If detected,
388 * it will return -1. If not, 0 will be returned. For non-regular files such
389 * as socket or pipe, write(fd, buf, 0) is not specified. Write(), however,
390 * will do nothing and just return 0.
391 *
392 */
393 ssize_t Write(const void* buf, size_t count);
394#ifdef __linux__
395 int EventfdWrite(eventfd_t value);
396#endif
397 bool IsATTY();
398
399 int Futimens(const struct timespec times[2]);
400
401 // Returns the target of "/proc/getpid()/fd/" + std::to_string(fd_)
402 // if appropriate
404
405 // inotify related functions
406 int InotifyAddWatch(const std::string& pathname, uint32_t mask);
407 void InotifyRmWatch(int watch);
408
409 private:
410 FileInstance(int fd, int in_errno);
411 FileInstance* Accept(struct sockaddr* addr, socklen_t* addrlen) const;
412
413 int fd_;
415 std::string identity_;
417};
418
421 short events;
422 short revents;
423};
424
425/* Methods that need both a fully defined SharedFD and a fully defined
426 FileInstance. */
427
428SharedFD::SharedFD() : value_(FileInstance::ClosedInstance()) {}
429
430} // namespace cuttlefish
431
432#endif // CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_H_
Definition: expected.h:86
Definition: epoll.h:36
Definition: shared_fd.h:294
off_t LSeek(off_t offset, int whence)
Definition: shared_fd.cpp:909
Result< void > Flock(int operation)
Definition: shared_fd.cpp:866
int Bind(const struct sockaddr *addr, socklen_t addrlen)
Definition: shared_fd.cpp:830
int ConnectWithTimeout(const struct sockaddr *addr, socklen_t addrlen, struct timeval *timeout)
Definition: shared_fd.cpp:203
ssize_t SendMsg(const struct msghdr *msg, int flags)
Definition: shared_fd.cpp:947
ssize_t Truncate(off_t length)
Definition: shared_fd.cpp:1011
void Set(fd_set *dest, int *max_index) const
Definition: shared_fd.cpp:282
ssize_t SendFileDescriptors(const void *buf, size_t len, Args &&... sent_fds)
Definition: shared_fd.h:368
virtual ~FileInstance()
Definition: shared_fd.h:300
int Futimens(const struct timespec times[2])
Definition: shared_fd.cpp:1041
static std::shared_ptr< FileInstance > ClosedInstance()
Definition: shared_fd.cpp:826
int Ioctl(int request, void *val=nullptr)
Definition: shared_fd.cpp:888
int Shutdown(int how)
Definition: shared_fd.cpp:953
bool IsSet(fd_set *in) const
Definition: shared_fd.cpp:267
bool CopyAllFrom(FileInstance &in, FileInstance *stop=nullptr)
Definition: shared_fd.cpp:165
std::string StrError() const
Definition: shared_fd.cpp:998
Result< std::string > ProcFdLinkTarget() const
bool IsRegular() const
Definition: shared_fd.h:343
void InotifyRmWatch(int watch)
Definition: shared_fd.cpp:1065
void Close()
Definition: shared_fd.cpp:176
ssize_t Send(const void *buf, size_t len, int flags)
Definition: shared_fd.cpp:941
int SetTerminalRaw()
Definition: shared_fd.cpp:973
int fd_
Definition: shared_fd.h:413
int Fcntl(int command, int value)
Definition: shared_fd.cpp:854
ssize_t RecvMsg(struct msghdr *msg, int flags)
Definition: shared_fd.cpp:921
int GetErrno() const
Definition: shared_fd.h:329
FileInstance(int fd, int in_errno)
Definition: shared_fd.cpp:1069
bool Chmod(mode_t mode)
Definition: shared_fd.cpp:197
int Connect(const struct sockaddr *addr, socklen_t addrlen)
Definition: shared_fd.cpp:836
static void Log(const char *message)
Definition: shared_fd.cpp:279
int Fsync()
Definition: shared_fd.cpp:860
ssize_t Write(const void *buf, size_t count)
Definition: shared_fd.cpp:1017
bool is_regular_file_
Definition: shared_fd.h:416
FileInstance * Accept(struct sockaddr *addr, socklen_t *addrlen) const
Definition: shared_fd.cpp:1079
int LinkAtCwd(const std::string &path)
Definition: shared_fd.cpp:894
ssize_t Read(void *buf, size_t count)
Definition: shared_fd.cpp:927
int UNMANAGED_Dup2(int newfd)
Definition: shared_fd.cpp:848
bool IsOpen() const
Definition: shared_fd.h:337
int UNMANAGED_Dup()
Definition: shared_fd.cpp:842
int GetSockOpt(int level, int optname, void *optval, socklen_t *optlen)
Definition: shared_fd.cpp:966
std::string identity_
Definition: shared_fd.h:415
int SetSockOpt(int level, int optname, const void *optval, socklen_t optlen)
Definition: shared_fd.cpp:959
ScopedMMap MMap(void *addr, size_t length, int prot, int flags, off_t offset)
Definition: shared_fd.cpp:1003
int errno_
Definition: shared_fd.h:414
int InotifyAddWatch(const std::string &pathname, uint32_t mask)
Definition: shared_fd.cpp:1061
int Listen(int backlog)
Definition: shared_fd.cpp:903
ssize_t Recv(void *buf, size_t len, int flags)
Definition: shared_fd.cpp:915
bool IsATTY()
Definition: shared_fd.cpp:1035
bool CopyFrom(FileInstance &in, size_t length, FileInstance *stop=nullptr)
Definition: shared_fd.cpp:111
int GetSockName(struct sockaddr *addr, socklen_t *addrlen)
Definition: shared_fd.cpp:873
Definition: shared_fd.h:253
bool WithinBounds(size_t offset, size_t length) const
Definition: shared_fd.h:271
void * get()
Definition: shared_fd.h:263
ScopedMMap & operator=(const ScopedMMap &other)=delete
const void * get() const
Definition: shared_fd.h:264
ScopedMMap()
Definition: shared_fd.cpp:812
ScopedMMap(const ScopedMMap &other)=delete
size_t len() const
Definition: shared_fd.h:265
~ScopedMMap()
Definition: shared_fd.cpp:820
size_t len_
Definition: shared_fd.h:278
void * ptr_
Definition: shared_fd.h:277
Definition: shared_fd.h:129
SharedFD & operator=(SharedFD const &)=default
static SharedFD ErrorFD(int error)
Definition: shared_fd.cpp:538
static SharedFD Open(const char *pathname, int flags, mode_t mode=0)
Definition: shared_fd.cpp:465
bool operator>=(const SharedFD &rhs) const
Definition: shared_fd.h:219
static int Fchdir(SharedFD)
Definition: shared_fd.cpp:484
bool operator<(const SharedFD &rhs) const
Definition: shared_fd.h:213
std::shared_ptr< FileInstance > value_
Definition: shared_fd.h:230
static SharedFD Socket(int domain, int socket_type, int protocol)
Definition: shared_fd.cpp:508
SharedFD()
Definition: shared_fd.h:428
FileInstance & operator*()
Definition: shared_fd.h:225
static Result< std::pair< SharedFD, std::string > > Mkostemp(std::string_view path, int flags=O_CLOEXEC)
Definition: shared_fd.cpp:526
static SharedFD MemfdCreate(const std::string &name, unsigned int flags=0)
Definition: shared_fd.cpp:420
SharedFD(const std::shared_ptr< FileInstance > &in)
Definition: shared_fd.h:134
static SharedFD MemfdCreateWithData(const std::string &name, const std::string &data, unsigned int flags=0)
Definition: shared_fd.cpp:426
static SharedFD Mkstemp(std::string *path)
Definition: shared_fd.cpp:517
static SharedFD Dup(int unmanaged_fd)
Definition: shared_fd.cpp:385
static SharedFD Accept(const FileInstance &listener, struct sockaddr *addr, socklen_t *addrlen)
Definition: shared_fd.cpp:375
static SharedFD Creat(const std::string &pathname, mode_t mode)
Definition: shared_fd.cpp:480
static int Poll(PollSharedFd *fds, size_t num_fds, int timeout)
Definition: shared_fd.cpp:335
bool operator<=(const SharedFD &rhs) const
Definition: shared_fd.h:215
static bool Pipe(SharedFD *fd0, SharedFD *fd1)
Definition: shared_fd.cpp:391
static Result< SharedFD > Fifo(const std::string &pathname, mode_t mode)
Definition: shared_fd.cpp:493
static bool SocketPair(int domain, int type, int protocol, SharedFD *fd0, SharedFD *fd1)
Definition: shared_fd.cpp:440
const FileInstance & operator*() const
Definition: shared_fd.h:223
std::shared_ptr< FileInstance > operator->() const
Definition: shared_fd.h:221
static SharedFD SocketLocalClient(const std::string &name, bool is_abstract, int in_type)
Definition: shared_fd.cpp:542
static SharedFD SocketClient(const std::string &host, int port, int type, std::chrono::seconds timeout=std::chrono::seconds(0))
Definition: shared_fd.cpp:579
bool operator!=(const SharedFD &rhs) const
Definition: shared_fd.h:211
bool operator>(const SharedFD &rhs) const
Definition: shared_fd.h:217
static SharedFD Socket6Client(const std::string &host, const std::string &interface, int port, int type, std::chrono::seconds timeout=std::chrono::seconds(0))
Definition: shared_fd.cpp:597
bool operator==(const SharedFD &rhs) const
Definition: shared_fd.h:209
static SharedFD InotifyFd()
Definition: shared_fd.cpp:474
static SharedFD SocketLocalServer(const std::string &name, bool is_abstract, int in_type, mode_t mode)
Definition: shared_fd.cpp:662
SharedFD(SharedFD const &)=default
Definition: shared_fd.h:238
WeakFD(SharedFD shared_fd)
Definition: shared_fd.h:240
std::weak_ptr< FileInstance > value_
Definition: shared_fd.h:247
SharedFD lock() const
Definition: shared_fd.cpp:802
#define error(format, args...)
Definition: fec_private.h:201
char data[Size]
Definition: incremental_server.cpp:1
ssize_t SendFileDescriptorVector(borrowed_fd sockfd, const void *data, size_t len, const std::vector< int > &fds)
Definition: cmsg.cpp:32
void Append(CollectionType &collection, T &&arg)
Definition: collections.h:36
Event
Definition: kernel_log_server.h:31
Definition: alloc_utils.cpp:23
std::vector< std::string_view > Args
Definition: incremental.h:28
__u32 mask
Definition: nl80211.h:0
uint8_t type
Definition: pairing_connection.h:0
Definition: shared_fd.h:419
short revents
Definition: shared_fd.h:422
short events
Definition: shared_fd.h:421
SharedFD fd
Definition: shared_fd.h:420
#define VMADDR_CID_ANY
Definition: vm_sockets.h:24