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