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