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