Home | History | Annotate | Download | only in fs
      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 
     37 #include <errno.h>
     38 #include <fcntl.h>
     39 #include <string.h>
     40 #include <unistd.h>
     41 
     42 #include "common/libs/auto_resources/auto_resources.h"
     43 #include "vm_sockets.h"
     44 
     45 /**
     46  * Classes to to enable safe access to files.
     47  * POSIX kernels have an unfortunate habit of recycling file descriptors.
     48  * That can cause problems like http://b/26121457 in code that doesn't manage
     49  * file lifetimes properly. These classes implement an alternate interface
     50  * that has some advantages:
     51  *
     52  * o References to files are tightly controlled
     53  * o Files are auto-closed if they go out of scope
     54  * o Files are life-time aware. It is impossible to close the instance twice.
     55  * o File descriptors are always initialized. By default the descriptor is
     56  *   set to a closed instance.
     57  *
     58  * These classes are designed to mimic to POSIX interface as closely as
     59  * possible. Specifically, they don't attempt to track the type of file
     60  * descriptors and expose only the valid operations. This is by design, since
     61  * it makes it easier to convert existing code to SharedFDs and avoids the
     62  * possibility that new POSIX functionality will lead to large refactorings.
     63  */
     64 namespace cvd {
     65 
     66 class FileInstance;
     67 
     68 /**
     69  * Describes the fields in msghdr that are honored by the *MsgAndFDs
     70  * calls.
     71  */
     72 struct InbandMessageHeader {
     73   void* msg_name;
     74   socklen_t msg_namelen;
     75   struct iovec* msg_iov;
     76   size_t msg_iovlen;
     77   int msg_flags;
     78 
     79   void Convert(struct msghdr* dest) const {
     80     dest->msg_name = msg_name;
     81     dest->msg_namelen = msg_namelen;
     82     dest->msg_iov = msg_iov;
     83     dest->msg_iovlen = msg_iovlen;
     84     dest->msg_flags = msg_flags;
     85   }
     86 };
     87 
     88 /**
     89  * Counted reference to a FileInstance.
     90  *
     91  * This is also the place where most new FileInstances are created. The creation
     92  * mehtods correspond to the underlying POSIX calls.
     93  *
     94  * SharedFDs can be compared and stored in STL containers. The semantics are
     95  * slightly different from POSIX file descriptors:
     96  *
     97  * o The value of the SharedFD is the identity of its underlying FileInstance.
     98  *
     99  * o Each newly created SharedFD has a unique, closed FileInstance:
    100  *    SharedFD a, b;
    101  *    assert (a != b);
    102  *    a = b;
    103  *    asssert(a == b);
    104  *
    105  * o The identity of the FileInstance is not affected by closing the file:
    106  *   SharedFD a, b;
    107  *   set<SharedFD> s;
    108  *   s.insert(a);
    109  *   assert(s.count(a) == 1);
    110  *   assert(s.count(b) == 0);
    111  *   a->Close();
    112  *   assert(s.count(a) == 1);
    113  *   assert(s.count(b) == 0);
    114  *
    115  * o FileInstances are never visibly recycled.
    116  *
    117  * o If all of the SharedFDs referring to a FileInstance go out of scope the
    118  *   file is closed and the FileInstance is recycled.
    119  *
    120  * Creation methods must ensure that no references to the new file descriptor
    121  * escape. The underlying FileInstance should have the only reference to the
    122  * file descriptor. Any method that needs to know the fd must be in either
    123  * SharedFD or FileInstance.
    124  *
    125  * SharedFDs always have an underlying FileInstance, so all of the method
    126  * calls are safe in accordance with the null object pattern.
    127  *
    128  * Errors on system calls that create new FileInstances, such as Open, are
    129  * reported with a new, closed FileInstance with the errno set.
    130  */
    131 class SharedFD {
    132  public:
    133   inline SharedFD();
    134   SharedFD(const std::shared_ptr<FileInstance>& in) : value_(in) {}
    135   // Reference the listener as a FileInstance to make this FD type agnostic.
    136   static SharedFD Accept(const FileInstance& listener, struct sockaddr* addr,
    137                          socklen_t* addrlen);
    138   static SharedFD Accept(const FileInstance& listener);
    139   static SharedFD Dup(int unmanaged_fd);
    140   static SharedFD GetControlSocket(const char* name);
    141   // All SharedFDs have the O_CLOEXEC flag after creation. To remove use the
    142   // Fcntl or Dup functions.
    143   static SharedFD Open(const char* pathname, int flags, mode_t mode = 0);
    144   static SharedFD Creat(const char* pathname, mode_t mode);
    145   static bool Pipe(SharedFD* fd0, SharedFD* fd1);
    146   static SharedFD Event(int initval = 0, int flags = 0);
    147   static SharedFD Epoll(int flags = 0);
    148   static bool SocketPair(int domain, int type, int protocol, SharedFD* fd0,
    149                          SharedFD* fd1);
    150   static SharedFD Socket(int domain, int socket_type, int protocol);
    151   static SharedFD SocketLocalClient(const char* name, bool is_abstract,
    152                                     int in_type);
    153   static SharedFD SocketLocalClient(int port, int type);
    154   static SharedFD SocketLocalServer(const char* name, bool is_abstract,
    155                                     int in_type, mode_t mode);
    156   static SharedFD SocketLocalServer(int port, int type);
    157   static SharedFD SocketSeqPacketServer(const char* name, mode_t mode);
    158   static SharedFD SocketSeqPacketClient(const char* name);
    159   static SharedFD VsockServer(unsigned int port, int type);
    160   static SharedFD VsockClient(unsigned int cid, unsigned int port, int type);
    161   static SharedFD TimerFD(int clock, int flags);
    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   bool operator<=(const SharedFD& rhs) const { return value_ <= rhs.value_; }
    170 
    171   bool operator>(const SharedFD& rhs) const { return value_ > rhs.value_; }
    172 
    173   bool operator>=(const SharedFD& rhs) const { return value_ >= rhs.value_; }
    174 
    175   std::shared_ptr<FileInstance> operator->() const { return value_; }
    176 
    177   const cvd::FileInstance& operator*() const { return *value_; }
    178 
    179   cvd::FileInstance& operator*() { return *value_; }
    180 
    181  private:
    182   static SharedFD ErrorFD(int error);
    183 
    184   std::shared_ptr<FileInstance> value_;
    185 };
    186 
    187 /**
    188  * Tracks the lifetime of a file descriptor and provides methods to allow
    189  * callers to use the file without knowledge of the underlying descriptor
    190  * number.
    191  *
    192  * FileInstances have two states: Open and Closed. They may start in either
    193  * state. However, once a FileIntance enters the Closed state it cannot be
    194  * reopened.
    195  *
    196  * Construction of FileInstances is limited to select classes to avoid
    197  * escaping file descriptors. At this point SharedFD is the only class
    198  * that has access. We may eventually have ScopedFD and WeakFD.
    199  */
    200 class FileInstance {
    201   // Give SharedFD access to the aliasing constructor.
    202   friend class SharedFD;
    203 
    204  public:
    205   virtual ~FileInstance() { Close(); }
    206 
    207   // This can't be a singleton because our shared_ptr's aren't thread safe.
    208   static std::shared_ptr<FileInstance> ClosedInstance() {
    209     return std::shared_ptr<FileInstance>(new FileInstance(-1, EBADF));
    210   }
    211 
    212   int Bind(const struct sockaddr* addr, socklen_t addrlen) {
    213     errno = 0;
    214     int rval = bind(fd_, addr, addrlen);
    215     errno_ = errno;
    216     return rval;
    217   }
    218 
    219   int Connect(const struct sockaddr* addr, socklen_t addrlen) {
    220     errno = 0;
    221     int rval = connect(fd_, addr, addrlen);
    222     errno_ = errno;
    223     return rval;
    224   }
    225 
    226   void Close();
    227 
    228   // Returns true if the entire input was copied.
    229   // Otherwise an error will be set either on this file or the input.
    230   // The non-const reference is needed to avoid binding this to a particular
    231   // reference type.
    232   bool CopyFrom(FileInstance& in);
    233   bool CopyFrom(FileInstance& in, size_t length);
    234 
    235   int UNMANAGED_Dup() {
    236     errno = 0;
    237     int rval = TEMP_FAILURE_RETRY(dup(fd_));
    238     errno_ = errno;
    239     return rval;
    240   }
    241 
    242   int UNMANAGED_Dup2(int newfd) {
    243     errno = 0;
    244     int rval = TEMP_FAILURE_RETRY(dup2(fd_, newfd));
    245     errno_ = errno;
    246     return rval;
    247   }
    248 
    249   int EpollCtl(int op, cvd::SharedFD new_fd, struct epoll_event* event) {
    250     errno = 0;
    251     int rval = TEMP_FAILURE_RETRY(epoll_ctl(fd_, op, new_fd->fd_, event));
    252     errno_ = errno;
    253     return rval;
    254   }
    255 
    256   int EpollWait(struct epoll_event* events, int maxevents, int timeout) {
    257     errno = 0;
    258     int rval = TEMP_FAILURE_RETRY(epoll_wait(fd_, events, maxevents, timeout));
    259     errno_ = errno;
    260     return rval;
    261   }
    262 
    263   int Fchown(uid_t owner, gid_t group) {
    264     errno = 0;
    265     int rval = TEMP_FAILURE_RETRY(fchown(fd_, owner, group));
    266     errno_ = errno;
    267     return rval;
    268   }
    269 
    270   int Fcntl(int command, int value) {
    271     errno = 0;
    272     int rval = TEMP_FAILURE_RETRY(fcntl(fd_, command, value));
    273     errno_ = errno;
    274     return rval;
    275   }
    276 
    277   int Fstat(struct stat* buf) {
    278     errno = 0;
    279     int rval = TEMP_FAILURE_RETRY(fstat(fd_, buf));
    280     errno_ = errno;
    281     return rval;
    282   }
    283 
    284   int GetErrno() const { return errno_; }
    285 
    286   int GetSockOpt(int level, int optname, void* optval, socklen_t* optlen) {
    287     errno = 0;
    288     int rval = getsockopt(fd_, level, optname, optval, optlen);
    289     if (rval == -1) {
    290       errno_ = errno;
    291     }
    292     return rval;
    293   }
    294 
    295   void Identify(const char* identity);
    296 
    297   int Ioctl(int request, void* val = nullptr) {
    298     errno = 0;
    299     int rval = TEMP_FAILURE_RETRY(ioctl(fd_, request, val));
    300     errno_ = errno;
    301     return rval;
    302   }
    303 
    304   bool IsOpen() const { return fd_ != -1; }
    305 
    306   // in probably isn't modified, but the API spec doesn't have const.
    307   bool IsSet(fd_set* in) const;
    308 
    309   int Listen(int backlog) {
    310     errno = 0;
    311     int rval = listen(fd_, backlog);
    312     errno_ = errno;
    313     return rval;
    314   }
    315 
    316   static void Log(const char* message);
    317 
    318   off_t LSeek(off_t offset, int whence) {
    319     errno = 0;
    320     off_t rval = TEMP_FAILURE_RETRY(lseek(fd_, offset, whence));
    321     errno_ = errno;
    322     return rval;
    323   }
    324 
    325   void* Mmap(void* addr, size_t length, int prot, int flags, off_t offset) {
    326     errno = 0;
    327     void* rval = mmap(addr, length, prot, flags, fd_, offset);
    328     errno_ = errno;
    329     return rval;
    330   }
    331 
    332   ssize_t Pread(void* buf, size_t count, off_t offset) {
    333     errno = 0;
    334     ssize_t rval = TEMP_FAILURE_RETRY(pread(fd_, buf, count, offset));
    335     errno_ = errno;
    336     return rval;
    337   }
    338 
    339   ssize_t Recv(void* buf, size_t len, int flags) {
    340     errno = 0;
    341     ssize_t rval = TEMP_FAILURE_RETRY(recv(fd_, buf, len, flags));
    342     errno_ = errno;
    343     return rval;
    344   }
    345 
    346   ssize_t RecvFrom(void* buf, size_t len, int flags, struct sockaddr* src_addr,
    347                    socklen_t* addr_len) {
    348     errno = 0;
    349     ssize_t rval =
    350         TEMP_FAILURE_RETRY(recvfrom(fd_, buf, len, flags, src_addr, addr_len));
    351     errno_ = errno;
    352     return rval;
    353   }
    354 
    355   ssize_t RecvMsg(struct msghdr* msg, int flags) {
    356     errno = 0;
    357     ssize_t rval = TEMP_FAILURE_RETRY(recvmsg(fd_, msg, flags));
    358     errno_ = errno;
    359     return rval;
    360   }
    361 
    362   template <size_t SZ>
    363   ssize_t RecvMsgAndFDs(const struct InbandMessageHeader& msg_in, int flags,
    364                         SharedFD (*new_fds)[SZ]) {
    365     // We need to make some modifications to land the fds. Make it clear
    366     // that there are no updates to the msg being passed in during this call.
    367     struct msghdr msg;
    368     msg_in.Convert(&msg);
    369     union {
    370       char buffer[CMSG_SPACE(SZ * sizeof(int))];
    371       struct cmsghdr this_aligns_buffer;
    372     } u;
    373     msg.msg_control = u.buffer;
    374     msg.msg_controllen = sizeof(u.buffer);
    375 
    376     cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
    377     cmsg->cmsg_len = CMSG_LEN(SZ * sizeof(int));
    378     cmsg->cmsg_level = SOL_SOCKET;
    379     cmsg->cmsg_type = SCM_RIGHTS;
    380     int* fd_array = reinterpret_cast<int*>(CMSG_DATA(cmsg));
    381     for (size_t i = 0; i < SZ; ++i) {
    382       fd_array[i] = -1;
    383     }
    384     ssize_t rval = RecvMsg(&msg, flags);
    385     for (size_t i = 0; i < SZ; ++i) {
    386       (*new_fds)[i] =
    387           std::shared_ptr<FileInstance>(new FileInstance(fd_array[i], errno));
    388     }
    389     return rval;
    390   }
    391 
    392   ssize_t Read(void* buf, size_t count) {
    393     errno = 0;
    394     ssize_t rval = TEMP_FAILURE_RETRY(read(fd_, buf, count));
    395     errno_ = errno;
    396     return rval;
    397   }
    398 
    399   ssize_t Send(const void* buf, size_t len, int flags) {
    400     errno = 0;
    401     ssize_t rval = TEMP_FAILURE_RETRY(send(fd_, buf, len, flags));
    402     errno_ = errno;
    403     return rval;
    404   }
    405 
    406   ssize_t SendMsg(const struct msghdr* msg, int flags) {
    407     errno = 0;
    408     ssize_t rval = TEMP_FAILURE_RETRY(sendmsg(fd_, msg, flags));
    409     errno_ = errno;
    410     return rval;
    411   }
    412 
    413   template <size_t SZ>
    414   ssize_t SendMsgAndFDs(const struct InbandMessageHeader& msg_in, int flags,
    415                         const SharedFD (&fds)[SZ]) {
    416     struct msghdr msg;
    417     msg_in.Convert(&msg);
    418     union {
    419       char buffer[CMSG_SPACE(SZ * sizeof(int))];
    420       struct cmsghdr this_aligns_buffer;
    421     } u;
    422     msg.msg_control = u.buffer;
    423     msg.msg_controllen = sizeof(u.buffer);
    424 
    425     cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
    426     cmsg->cmsg_len = CMSG_LEN(SZ * sizeof(int));
    427     cmsg->cmsg_level = SOL_SOCKET;
    428     cmsg->cmsg_type = SCM_RIGHTS;
    429     int* fd_array = reinterpret_cast<int*>(CMSG_DATA(cmsg));
    430     for (size_t i = 0; i < SZ; ++i) {
    431       fd_array[i] = fds[i]->fd_;
    432     }
    433     return SendMsg(&msg, flags);
    434   }
    435 
    436   int Shutdown(int how) {
    437     errno = 0;
    438     int rval = shutdown(fd_, how);
    439     errno_ = errno;
    440     return rval;
    441   }
    442 
    443   ssize_t SendTo(const void* buf, size_t len, int flags,
    444                  const struct sockaddr* dest_addr, socklen_t addrlen) {
    445     errno = 0;
    446     ssize_t rval =
    447         TEMP_FAILURE_RETRY(sendto(fd_, buf, len, flags, dest_addr, addrlen));
    448     errno_ = errno;
    449     return rval;
    450   }
    451 
    452   void Set(fd_set* dest, int* max_index) const;
    453 
    454   int SetSockOpt(int level, int optname, const void* optval, socklen_t optlen) {
    455     errno = 0;
    456     int rval = setsockopt(fd_, level, optname, optval, optlen);
    457     errno_ = errno;
    458     return rval;
    459   }
    460 
    461   const char* StrError() const {
    462     errno = 0;
    463     FileInstance* s = const_cast<FileInstance*>(this);
    464     char* out = strerror_r(errno_, s->strerror_buf_, sizeof(strerror_buf_));
    465 
    466     // From man page:
    467     //  strerror_r() returns a pointer to a string containing the error message.
    468     //  This may be either a pointer to a string that the function stores in
    469     //  buf, or a pointer to some (immutable) static string (in which case buf
    470     //  is unused).
    471     if (out != s->strerror_buf_) {
    472       strncpy(s->strerror_buf_, out, sizeof(strerror_buf_));
    473     }
    474     return strerror_buf_;
    475   }
    476 
    477   int TimerGet(struct itimerspec* curr_value) {
    478     errno = 0;
    479     int rval = timerfd_gettime(fd_, curr_value);
    480     errno_ = errno;
    481     return rval;
    482   }
    483 
    484   int TimerSet(int flags, const struct itimerspec* new_value,
    485                struct itimerspec* old_value) {
    486     errno = 0;
    487     int rval = timerfd_settime(fd_, flags, new_value, old_value);
    488     errno_ = errno;
    489     return rval;
    490   }
    491 
    492   ssize_t Truncate(off_t length) {
    493     errno = 0;
    494     ssize_t rval = TEMP_FAILURE_RETRY(ftruncate(fd_, length));
    495     errno_ = errno;
    496     return rval;
    497   }
    498 
    499   ssize_t Write(const void* buf, size_t count) {
    500     errno = 0;
    501     ssize_t rval = TEMP_FAILURE_RETRY(write(fd_, buf, count));
    502     errno_ = errno;
    503     return rval;
    504   }
    505 
    506   ssize_t WriteV(struct iovec* iov, int iovcount) {
    507     errno = 0;
    508     ssize_t rval = TEMP_FAILURE_RETRY(writev(fd_, iov, iovcount));
    509     errno_ = errno;
    510     return rval;
    511   }
    512 
    513  private:
    514   FileInstance(int fd, int in_errno) : fd_(fd), errno_(in_errno) {
    515     // Ensure every file descriptor managed by a FileInstance has the CLOEXEC
    516     // flag
    517     TEMP_FAILURE_RETRY(fcntl(fd, F_SETFD, FD_CLOEXEC));
    518     identity_.PrintF("fd=%d @%p", fd, this);
    519   }
    520 
    521   FileInstance* Accept(struct sockaddr* addr, socklen_t* addrlen) const {
    522     int fd = TEMP_FAILURE_RETRY(accept(fd_, addr, addrlen));
    523     if (fd == -1) {
    524       return new FileInstance(fd, errno);
    525     } else {
    526       return new FileInstance(fd, 0);
    527     }
    528   }
    529 
    530   int fd_;
    531   int errno_;
    532   AutoFreeBuffer identity_;
    533   char strerror_buf_[160];
    534 };
    535 
    536 /* Methods that need both a fully defined SharedFD and a fully defined
    537    FileInstance. */
    538 
    539 inline SharedFD::SharedFD() : value_(FileInstance::ClosedInstance()) {}
    540 
    541 }  // namespace cvd
    542 
    543 #endif  // CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_H_
    544