Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2015 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 | |
Elliott Hughes | e3c5a2a | 2018-06-26 17:17:41 -0700 | [diff] [blame] | 17 | #pragma once |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 18 | |
Josh Gao | 1f02e83 | 2018-11-01 12:32:52 -0700 | [diff] [blame] | 19 | #include <dirent.h> |
Josh Gao | 34e157b | 2019-01-25 16:22:41 -0800 | [diff] [blame] | 20 | #include <errno.h> |
Josh Gao | 4ae64ef | 2017-08-25 18:00:18 -0700 | [diff] [blame] | 21 | #include <fcntl.h> |
| 22 | |
Josh Gao | 7c0f0f0 | 2018-09-04 11:05:08 -0700 | [diff] [blame] | 23 | #include <stdio.h> |
Josh Gao | 4ae64ef | 2017-08-25 18:00:18 -0700 | [diff] [blame] | 24 | #include <sys/types.h> |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 25 | #include <unistd.h> |
| 26 | |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 27 | // DO NOT INCLUDE OTHER LIBBASE HEADERS HERE! |
Christopher Wiley | 39ea3c5 | 2016-04-19 14:09:41 -0700 | [diff] [blame] | 28 | // This file gets used in libbinder, and libbinder is used everywhere. |
| 29 | // Including other headers from libbase frequently results in inclusion of |
| 30 | // android-base/macros.h, which causes macro collisions. |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 31 | |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 32 | #if defined(__BIONIC__) |
| 33 | #include <android/fdsan.h> |
| 34 | #endif |
| 35 | #if !defined(_WIN32) |
| 36 | #include <sys/socket.h> |
| 37 | #endif |
| 38 | |
| 39 | namespace android { |
| 40 | namespace base { |
| 41 | |
Elliott Hughes | b1fa61b | 2016-03-22 20:03:48 -0700 | [diff] [blame] | 42 | // Container for a file descriptor that automatically closes the descriptor as |
| 43 | // it goes out of scope. |
| 44 | // |
| 45 | // unique_fd ufd(open("/some/path", "r")); |
| 46 | // if (ufd.get() == -1) return error; |
| 47 | // |
| 48 | // // Do something useful, possibly including 'return'. |
| 49 | // |
| 50 | // return 0; // Descriptor is closed for you. |
| 51 | // |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 52 | // See also the Pipe()/Socketpair()/Fdopen()/Fdopendir() functions in this file |
| 53 | // that provide interoperability with the libc functions with the same (but |
| 54 | // lowercase) names. |
| 55 | // |
Elliott Hughes | b1fa61b | 2016-03-22 20:03:48 -0700 | [diff] [blame] | 56 | // unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help |
| 57 | // you find this class if you're searching for one of those names. |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 58 | // |
| 59 | // unique_fd itself is a specialization of unique_fd_impl with a default closer. |
Josh Gao | d0de23d | 2016-05-13 14:52:06 -0700 | [diff] [blame] | 60 | template <typename Closer> |
Greg Kaiser | f00ff0c | 2021-04-29 05:05:17 +0000 | [diff] [blame] | 61 | class unique_fd_impl final { |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 62 | public: |
Josh Gao | 6b4ef85 | 2018-07-20 12:42:14 -0700 | [diff] [blame] | 63 | unique_fd_impl() {} |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 64 | |
Josh Gao | 6b4ef85 | 2018-07-20 12:42:14 -0700 | [diff] [blame] | 65 | explicit unique_fd_impl(int fd) { reset(fd); } |
Josh Gao | e2a9eb0 | 2016-09-14 12:47:02 -0700 | [diff] [blame] | 66 | ~unique_fd_impl() { reset(); } |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 67 | |
Tomasz Wasilczyk | 36815d4 | 2019-07-17 17:25:23 -0700 | [diff] [blame] | 68 | unique_fd_impl(const unique_fd_impl&) = delete; |
| 69 | void operator=(const unique_fd_impl&) = delete; |
Chih-Hung Hsieh | 2f515bf | 2018-09-25 11:16:22 -0700 | [diff] [blame] | 70 | unique_fd_impl(unique_fd_impl&& other) noexcept { reset(other.release()); } |
| 71 | unique_fd_impl& operator=(unique_fd_impl&& s) noexcept { |
Josh Gao | 6b4ef85 | 2018-07-20 12:42:14 -0700 | [diff] [blame] | 72 | int fd = s.fd_; |
| 73 | s.fd_ = -1; |
| 74 | reset(fd, &s); |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 75 | return *this; |
| 76 | } |
| 77 | |
Josh Gao | 89e5018 | 2020-03-09 12:05:32 -0700 | [diff] [blame] | 78 | [[clang::reinitializes]] void reset(int new_value = -1) { reset(new_value, nullptr); } |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 79 | |
Josh Gao | 6b4ef85 | 2018-07-20 12:42:14 -0700 | [diff] [blame] | 80 | int get() const { return fd_; } |
Josh Gao | e440199 | 2019-04-25 14:04:57 -0700 | [diff] [blame] | 81 | |
| 82 | #if !defined(ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION) |
| 83 | // unique_fd's operator int is dangerous, but we have way too much code that |
| 84 | // depends on it, so make this opt-in at first. |
Andreas Gampe | cbc9bc0 | 2019-01-10 08:54:45 -0800 | [diff] [blame] | 85 | operator int() const { return get(); } // NOLINT |
Josh Gao | e440199 | 2019-04-25 14:04:57 -0700 | [diff] [blame] | 86 | #endif |
| 87 | |
| 88 | bool operator>=(int rhs) const { return get() >= rhs; } |
| 89 | bool operator<(int rhs) const { return get() < rhs; } |
| 90 | bool operator==(int rhs) const { return get() == rhs; } |
| 91 | bool operator!=(int rhs) const { return get() != rhs; } |
Peter Collingbourne | 655a181 | 2020-01-13 18:39:56 -0800 | [diff] [blame] | 92 | bool operator==(const unique_fd_impl& rhs) const { return get() == rhs.get(); } |
| 93 | bool operator!=(const unique_fd_impl& rhs) const { return get() != rhs.get(); } |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 94 | |
Bernie Innocenti | cf2a948 | 2019-03-28 15:32:37 +0900 | [diff] [blame] | 95 | // Catch bogus error checks (i.e.: "!fd" instead of "fd != -1"). |
| 96 | bool operator!() const = delete; |
| 97 | |
Daniel Colascione | 700254a | 2019-09-04 13:46:50 -0700 | [diff] [blame] | 98 | bool ok() const { return get() >= 0; } |
Tomasz Wasilczyk | 36815d4 | 2019-07-17 17:25:23 -0700 | [diff] [blame] | 99 | |
Elliott Hughes | b1fa61b | 2016-03-22 20:03:48 -0700 | [diff] [blame] | 100 | int release() __attribute__((warn_unused_result)) { |
Josh Gao | 6b4ef85 | 2018-07-20 12:42:14 -0700 | [diff] [blame] | 101 | tag(fd_, this, nullptr); |
| 102 | int ret = fd_; |
| 103 | fd_ = -1; |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 104 | return ret; |
| 105 | } |
| 106 | |
| 107 | private: |
Josh Gao | 6b4ef85 | 2018-07-20 12:42:14 -0700 | [diff] [blame] | 108 | void reset(int new_value, void* previous_tag) { |
Josh Gao | 34e157b | 2019-01-25 16:22:41 -0800 | [diff] [blame] | 109 | int previous_errno = errno; |
| 110 | |
Josh Gao | 6b4ef85 | 2018-07-20 12:42:14 -0700 | [diff] [blame] | 111 | if (fd_ != -1) { |
| 112 | close(fd_, this); |
| 113 | } |
| 114 | |
| 115 | fd_ = new_value; |
| 116 | if (new_value != -1) { |
| 117 | tag(new_value, previous_tag, this); |
| 118 | } |
Josh Gao | 34e157b | 2019-01-25 16:22:41 -0800 | [diff] [blame] | 119 | |
| 120 | errno = previous_errno; |
Josh Gao | 6b4ef85 | 2018-07-20 12:42:14 -0700 | [diff] [blame] | 121 | } |
| 122 | |
| 123 | int fd_ = -1; |
| 124 | |
| 125 | // Template magic to use Closer::Tag if available, and do nothing if not. |
| 126 | // If Closer::Tag exists, this implementation is preferred, because int is a better match. |
| 127 | // If not, this implementation is SFINAEd away, and the no-op below is the only one that exists. |
| 128 | template <typename T = Closer> |
| 129 | static auto tag(int fd, void* old_tag, void* new_tag) |
| 130 | -> decltype(T::Tag(fd, old_tag, new_tag), void()) { |
| 131 | T::Tag(fd, old_tag, new_tag); |
| 132 | } |
| 133 | |
| 134 | template <typename T = Closer> |
| 135 | static void tag(long, void*, void*) { |
| 136 | // No-op. |
| 137 | } |
| 138 | |
| 139 | // Same as above, to select between Closer::Close(int) and Closer::Close(int, void*). |
| 140 | template <typename T = Closer> |
| 141 | static auto close(int fd, void* tag_value) -> decltype(T::Close(fd, tag_value), void()) { |
| 142 | T::Close(fd, tag_value); |
| 143 | } |
| 144 | |
| 145 | template <typename T = Closer> |
| 146 | static auto close(int fd, void*) -> decltype(T::Close(fd), void()) { |
| 147 | T::Close(fd); |
| 148 | } |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 149 | }; |
| 150 | |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 151 | // The actual details of closing are factored out to support unusual cases. |
| 152 | // Almost everyone will want this DefaultCloser, which handles fdsan on bionic. |
| 153 | struct DefaultCloser { |
| 154 | #if defined(__BIONIC__) |
| 155 | static void Tag(int fd, void* old_addr, void* new_addr) { |
| 156 | if (android_fdsan_exchange_owner_tag) { |
| 157 | uint64_t old_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD, |
| 158 | reinterpret_cast<uint64_t>(old_addr)); |
| 159 | uint64_t new_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD, |
| 160 | reinterpret_cast<uint64_t>(new_addr)); |
| 161 | android_fdsan_exchange_owner_tag(fd, old_tag, new_tag); |
| 162 | } |
| 163 | } |
| 164 | static void Close(int fd, void* addr) { |
| 165 | if (android_fdsan_close_with_tag) { |
| 166 | uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD, |
| 167 | reinterpret_cast<uint64_t>(addr)); |
| 168 | android_fdsan_close_with_tag(fd, tag); |
| 169 | } else { |
| 170 | close(fd); |
| 171 | } |
| 172 | } |
| 173 | #else |
| 174 | static void Close(int fd) { |
| 175 | // Even if close(2) fails with EINTR, the fd will have been closed. |
| 176 | // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone |
| 177 | // else's fd. |
| 178 | // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html |
| 179 | ::close(fd); |
| 180 | } |
| 181 | #endif |
| 182 | }; |
| 183 | |
Greg Kaiser | f00ff0c | 2021-04-29 05:05:17 +0000 | [diff] [blame] | 184 | using unique_fd = unique_fd_impl<DefaultCloser>; |
Josh Gao | d0de23d | 2016-05-13 14:52:06 -0700 | [diff] [blame] | 185 | |
Josh Gao | 4ae64ef | 2017-08-25 18:00:18 -0700 | [diff] [blame] | 186 | #if !defined(_WIN32) |
| 187 | |
| 188 | // Inline functions, so that they can be used header-only. |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 189 | |
| 190 | // See pipe(2). |
| 191 | // This helper hides the details of converting to unique_fd, and also hides the |
| 192 | // fact that macOS doesn't support O_CLOEXEC or O_NONBLOCK directly. |
Josh Gao | a0aa1c5 | 2018-06-01 15:47:20 -0700 | [diff] [blame] | 193 | template <typename Closer> |
Yabin Cui | f6aa738 | 2019-01-18 11:11:57 -0800 | [diff] [blame] | 194 | inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write, |
| 195 | int flags = O_CLOEXEC) { |
Josh Gao | 4ae64ef | 2017-08-25 18:00:18 -0700 | [diff] [blame] | 196 | int pipefd[2]; |
Josh Gao | ec6376f | 2017-08-29 21:28:06 -0700 | [diff] [blame] | 197 | |
| 198 | #if defined(__linux__) |
Yabin Cui | f6aa738 | 2019-01-18 11:11:57 -0800 | [diff] [blame] | 199 | if (pipe2(pipefd, flags) != 0) { |
Josh Gao | 4ae64ef | 2017-08-25 18:00:18 -0700 | [diff] [blame] | 200 | return false; |
| 201 | } |
Josh Gao | ec6376f | 2017-08-29 21:28:06 -0700 | [diff] [blame] | 202 | #else // defined(__APPLE__) |
Yabin Cui | f6aa738 | 2019-01-18 11:11:57 -0800 | [diff] [blame] | 203 | if (flags & ~(O_CLOEXEC | O_NONBLOCK)) { |
| 204 | return false; |
| 205 | } |
Josh Gao | ec6376f | 2017-08-29 21:28:06 -0700 | [diff] [blame] | 206 | if (pipe(pipefd) != 0) { |
| 207 | return false; |
| 208 | } |
| 209 | |
Yabin Cui | f6aa738 | 2019-01-18 11:11:57 -0800 | [diff] [blame] | 210 | if (flags & O_CLOEXEC) { |
| 211 | if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) { |
| 212 | close(pipefd[0]); |
| 213 | close(pipefd[1]); |
| 214 | return false; |
| 215 | } |
| 216 | } |
| 217 | if (flags & O_NONBLOCK) { |
| 218 | if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) != 0 || fcntl(pipefd[1], F_SETFL, O_NONBLOCK) != 0) { |
| 219 | close(pipefd[0]); |
| 220 | close(pipefd[1]); |
| 221 | return false; |
| 222 | } |
Josh Gao | ec6376f | 2017-08-29 21:28:06 -0700 | [diff] [blame] | 223 | } |
| 224 | #endif |
| 225 | |
Josh Gao | 4ae64ef | 2017-08-25 18:00:18 -0700 | [diff] [blame] | 226 | read->reset(pipefd[0]); |
| 227 | write->reset(pipefd[1]); |
| 228 | return true; |
| 229 | } |
| 230 | |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 231 | // See socketpair(2). |
| 232 | // This helper hides the details of converting to unique_fd. |
Josh Gao | a0aa1c5 | 2018-06-01 15:47:20 -0700 | [diff] [blame] | 233 | template <typename Closer> |
| 234 | inline bool Socketpair(int domain, int type, int protocol, unique_fd_impl<Closer>* left, |
| 235 | unique_fd_impl<Closer>* right) { |
Josh Gao | 4ae64ef | 2017-08-25 18:00:18 -0700 | [diff] [blame] | 236 | int sockfd[2]; |
| 237 | if (socketpair(domain, type, protocol, sockfd) != 0) { |
| 238 | return false; |
| 239 | } |
| 240 | left->reset(sockfd[0]); |
| 241 | right->reset(sockfd[1]); |
| 242 | return true; |
| 243 | } |
| 244 | |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 245 | // See socketpair(2). |
| 246 | // This helper hides the details of converting to unique_fd. |
Josh Gao | a0aa1c5 | 2018-06-01 15:47:20 -0700 | [diff] [blame] | 247 | template <typename Closer> |
| 248 | inline bool Socketpair(int type, unique_fd_impl<Closer>* left, unique_fd_impl<Closer>* right) { |
Josh Gao | 4ae64ef | 2017-08-25 18:00:18 -0700 | [diff] [blame] | 249 | return Socketpair(AF_UNIX, type, 0, left, right); |
| 250 | } |
| 251 | |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 252 | // See fdopen(3). |
Josh Gao | 7c0f0f0 | 2018-09-04 11:05:08 -0700 | [diff] [blame] | 253 | // Using fdopen with unique_fd correctly is more annoying than it should be, |
| 254 | // because fdopen doesn't close the file descriptor received upon failure. |
| 255 | inline FILE* Fdopen(unique_fd&& ufd, const char* mode) { |
| 256 | int fd = ufd.release(); |
| 257 | FILE* file = fdopen(fd, mode); |
| 258 | if (!file) { |
| 259 | close(fd); |
| 260 | } |
| 261 | return file; |
| 262 | } |
| 263 | |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 264 | // See fdopendir(3). |
Mathieu Chartier | a5d863b | 2018-11-02 08:05:31 -0700 | [diff] [blame] | 265 | // Using fdopendir with unique_fd correctly is more annoying than it should be, |
| 266 | // because fdopen doesn't close the file descriptor received upon failure. |
| 267 | inline DIR* Fdopendir(unique_fd&& ufd) { |
| 268 | int fd = ufd.release(); |
| 269 | DIR* dir = fdopendir(fd); |
| 270 | if (dir == nullptr) { |
| 271 | close(fd); |
| 272 | } |
| 273 | return dir; |
| 274 | } |
| 275 | |
Josh Gao | 4ae64ef | 2017-08-25 18:00:18 -0700 | [diff] [blame] | 276 | #endif // !defined(_WIN32) |
| 277 | |
Elliott Hughes | ebf33a2 | 2021-05-19 12:29:49 -0700 | [diff] [blame] | 278 | // A wrapper type that can be implicitly constructed from either int or |
| 279 | // unique_fd. This supports cases where you don't actually own the file |
| 280 | // descriptor, and can't take ownership, but are temporarily acting as if |
| 281 | // you're the owner. |
| 282 | // |
| 283 | // One example would be a function that needs to also allow |
| 284 | // STDERR_FILENO, not just a newly-opened fd. Another example would be JNI code |
| 285 | // that's using a file descriptor that's actually owned by a |
| 286 | // ParcelFileDescriptor or whatever on the Java side, but where the JNI code |
| 287 | // would like to enforce this weaker sense of "temporary ownership". |
| 288 | // |
| 289 | // If you think of unique_fd as being like std::string in that represents |
| 290 | // ownership, borrowed_fd is like std::string_view (and int is like const |
| 291 | // char*). |
Josh Gao | e440199 | 2019-04-25 14:04:57 -0700 | [diff] [blame] | 292 | struct borrowed_fd { |
Tom Cherry | 3d4916e | 2019-07-15 14:56:53 -0700 | [diff] [blame] | 293 | /* implicit */ borrowed_fd(int fd) : fd_(fd) {} // NOLINT |
Josh Gao | e440199 | 2019-04-25 14:04:57 -0700 | [diff] [blame] | 294 | template <typename T> |
Tom Cherry | 3d4916e | 2019-07-15 14:56:53 -0700 | [diff] [blame] | 295 | /* implicit */ borrowed_fd(const unique_fd_impl<T>& ufd) : fd_(ufd.get()) {} // NOLINT |
Josh Gao | e440199 | 2019-04-25 14:04:57 -0700 | [diff] [blame] | 296 | |
| 297 | int get() const { return fd_; } |
| 298 | |
| 299 | bool operator>=(int rhs) const { return get() >= rhs; } |
| 300 | bool operator<(int rhs) const { return get() < rhs; } |
| 301 | bool operator==(int rhs) const { return get() == rhs; } |
| 302 | bool operator!=(int rhs) const { return get() != rhs; } |
| 303 | |
| 304 | private: |
| 305 | int fd_ = -1; |
| 306 | }; |
Casey Dahlin | 1a0849a | 2015-11-12 14:52:13 -0800 | [diff] [blame] | 307 | } // namespace base |
| 308 | } // namespace android |
| 309 | |
Josh Gao | d2b2f3e | 2016-08-29 14:20:59 -0700 | [diff] [blame] | 310 | template <typename T> |
| 311 | int close(const android::base::unique_fd_impl<T>&) |
Elliott Hughes | 309e9fb | 2018-07-02 10:52:49 -0700 | [diff] [blame] | 312 | __attribute__((__unavailable__("close called on unique_fd"))); |
Josh Gao | 1f02e83 | 2018-11-01 12:32:52 -0700 | [diff] [blame] | 313 | |
| 314 | template <typename T> |
| 315 | FILE* fdopen(const android::base::unique_fd_impl<T>&, const char* mode) |
| 316 | __attribute__((__unavailable__("fdopen takes ownership of the fd passed in; either dup the " |
| 317 | "unique_fd, or use android::base::Fdopen to pass ownership"))); |
| 318 | |
| 319 | template <typename T> |
| 320 | DIR* fdopendir(const android::base::unique_fd_impl<T>&) __attribute__(( |
| 321 | __unavailable__("fdopendir takes ownership of the fd passed in; either dup the " |
| 322 | "unique_fd, or use android::base::Fdopendir to pass ownership"))); |