summaryrefslogtreecommitdiffstats
path: root/base/include
diff options
context:
space:
mode:
authorJosh Gao <jmgao@google.com>2018-05-31 21:24:14 -0700
committerJosh Gao <jmgao@google.com>2018-07-18 18:11:46 -0700
commitfcf2c01b5599a96b968afb1528c996d9486937b0 (patch)
tree623c9e7d59c96d047258e72f304104c669817af4 /base/include
parent54f40303d5632e7f5852cd9f467454281c4f979a (diff)
downloadsystem_core-fcf2c01b5599a96b968afb1528c996d9486937b0.tar.gz
system_core-fcf2c01b5599a96b968afb1528c996d9486937b0.tar.bz2
system_core-fcf2c01b5599a96b968afb1528c996d9486937b0.zip
base: add support for tagged fd closure to unique_fd.
Test: libbase_test Change-Id: Ibba5e60d7007265a566eb8f76021d5dbeb734532
Diffstat (limited to 'base/include')
-rw-r--r--base/include/android-base/unique_fd.h82
1 files changed, 68 insertions, 14 deletions
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 6cfcd3fb0..057f462e5 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -42,10 +42,29 @@
//
// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
// you find this class if you're searching for one of those names.
+
+#if defined(__BIONIC__)
+#include <android/fdsan.h>
+#endif
+
namespace android {
namespace base {
struct DefaultCloser {
+#if defined(__BIONIC__)
+ static void Tag(int fd, void* old_addr, void* new_addr) {
+ uint64_t old_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
+ reinterpret_cast<uint64_t>(old_addr));
+ uint64_t new_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
+ reinterpret_cast<uint64_t>(new_addr));
+ android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
+ }
+ static void Close(int fd, void* addr) {
+ uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
+ reinterpret_cast<uint64_t>(addr));
+ android_fdsan_close_with_tag(fd, tag);
+ }
+#else
static void Close(int fd) {
// Even if close(2) fails with EINTR, the fd will have been closed.
// Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
@@ -53,40 +72,75 @@ struct DefaultCloser {
// http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
::close(fd);
}
+#endif
};
template <typename Closer>
class unique_fd_impl final {
public:
- unique_fd_impl() : value_(-1) {}
+ unique_fd_impl() {}
- explicit unique_fd_impl(int value) : value_(value) {}
+ explicit unique_fd_impl(int fd) { reset(fd); }
~unique_fd_impl() { reset(); }
- unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {}
+ unique_fd_impl(unique_fd_impl&& other) { reset(other.release()); }
unique_fd_impl& operator=(unique_fd_impl&& s) {
- reset(s.release());
+ int fd = s.fd_;
+ s.fd_ = -1;
+ reset(fd, &s);
return *this;
}
- void reset(int new_value = -1) {
- if (value_ != -1) {
- Closer::Close(value_);
- }
- value_ = new_value;
- }
+ void reset(int new_value = -1) { reset(new_value, nullptr); }
- int get() const { return value_; }
+ int get() const { return fd_; }
operator int() const { return get(); }
int release() __attribute__((warn_unused_result)) {
- int ret = value_;
- value_ = -1;
+ tag(fd_, this, nullptr);
+ int ret = fd_;
+ fd_ = -1;
return ret;
}
private:
- int value_;
+ void reset(int new_value, void* previous_tag) {
+ if (fd_ != -1) {
+ close(fd_, this);
+ }
+
+ fd_ = new_value;
+ if (new_value != -1) {
+ tag(new_value, previous_tag, this);
+ }
+ }
+
+ int fd_ = -1;
+
+ // Template magic to use Closer::Tag if available, and do nothing if not.
+ // If Closer::Tag exists, this implementation is preferred, because int is a better match.
+ // If not, this implementation is SFINAEd away, and the no-op below is the only one that exists.
+ template <typename T = Closer>
+ static auto tag(int fd, void* old_tag, void* new_tag)
+ -> decltype(T::Tag(fd, old_tag, new_tag), void()) {
+ T::Tag(fd, old_tag, new_tag);
+ }
+
+ template <typename T = Closer>
+ static void tag(long, void*, void*) {
+ // No-op.
+ }
+
+ // Same as above, to select between Closer::Close(int) and Closer::Close(int, void*).
+ template <typename T = Closer>
+ static auto close(int fd, void* tag_value) -> decltype(T::Close(fd, tag_value), void()) {
+ T::Close(fd, tag_value);
+ }
+
+ template <typename T = Closer>
+ static auto close(int fd, void*) -> decltype(T::Close(fd), void()) {
+ T::Close(fd);
+ }
unique_fd_impl(const unique_fd_impl&);
void operator=(const unique_fd_impl&);