summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorJosh Gao2018-07-20 14:42:14 -0500
committerJosh Gao2018-07-20 15:50:15 -0500
commit22666feacc24041c8d885c21b8403ae24db25618 (patch)
tree9edfbb5f3abc05ab29d0bd635e7afd9f6ada70d7 /base
parenta570644b7df8f9a69b2a46a3a85052affcc5442c (diff)
downloadplatform-system-core-22666feacc24041c8d885c21b8403ae24db25618.tar.gz
platform-system-core-22666feacc24041c8d885c21b8403ae24db25618.tar.xz
platform-system-core-22666feacc24041c8d885c21b8403ae24db25618.zip
Revert "Revert "base: add support for tagged fd closure to unique_fd.""
Use __attribute__((weak)) to check for fdsan availability at runtime, to support being used when built with the NDK while targeting older platform versions. This reverts commit af798acaea49b8d9150b94eb9f5f11450a6b8893. Bug: http://b/110100358 Test: m libjnitest Change-Id: Ie59d041d69cc3d4b6c59412d706f702dd1d2dab2
Diffstat (limited to 'base')
-rw-r--r--base/Android.bp1
-rw-r--r--base/include/android-base/unique_fd.h88
-rw-r--r--base/unique_fd_test.cpp54
3 files changed, 129 insertions, 14 deletions
diff --git a/base/Android.bp b/base/Android.bp
index 3d80d9719..46a023342 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -135,6 +135,7 @@ cc_test {
135 "strings_test.cpp", 135 "strings_test.cpp",
136 "test_main.cpp", 136 "test_main.cpp",
137 "test_utils_test.cpp", 137 "test_utils_test.cpp",
138 "unique_fd_test.cpp",
138 ], 139 ],
139 target: { 140 target: {
140 android: { 141 android: {
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index c7330817a..c6936f137 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -42,10 +42,35 @@
42// 42//
43// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help 43// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
44// you find this class if you're searching for one of those names. 44// you find this class if you're searching for one of those names.
45
46#if defined(__BIONIC__)
47#include <android/fdsan.h>
48#endif
49
45namespace android { 50namespace android {
46namespace base { 51namespace base {
47 52
48struct DefaultCloser { 53struct DefaultCloser {
54#if defined(__BIONIC__)
55 static void Tag(int fd, void* old_addr, void* new_addr) {
56 if (android_fdsan_exchange_owner_tag) {
57 uint64_t old_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
58 reinterpret_cast<uint64_t>(old_addr));
59 uint64_t new_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
60 reinterpret_cast<uint64_t>(new_addr));
61 android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
62 }
63 }
64 static void Close(int fd, void* addr) {
65 if (android_fdsan_close_with_tag) {
66 uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
67 reinterpret_cast<uint64_t>(addr));
68 android_fdsan_close_with_tag(fd, tag);
69 } else {
70 close(fd);
71 }
72 }
73#else
49 static void Close(int fd) { 74 static void Close(int fd) {
50 // Even if close(2) fails with EINTR, the fd will have been closed. 75 // Even if close(2) fails with EINTR, the fd will have been closed.
51 // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone 76 // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
@@ -53,40 +78,75 @@ struct DefaultCloser {
53 // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html 78 // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
54 ::close(fd); 79 ::close(fd);
55 } 80 }
81#endif
56}; 82};
57 83
58template <typename Closer> 84template <typename Closer>
59class unique_fd_impl final { 85class unique_fd_impl final {
60 public: 86 public:
61 unique_fd_impl() : value_(-1) {} 87 unique_fd_impl() {}
62 88
63 explicit unique_fd_impl(int value) : value_(value) {} 89 explicit unique_fd_impl(int fd) { reset(fd); }
64 ~unique_fd_impl() { reset(); } 90 ~unique_fd_impl() { reset(); }
65 91
66 unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {} 92 unique_fd_impl(unique_fd_impl&& other) { reset(other.release()); }
67 unique_fd_impl& operator=(unique_fd_impl&& s) { 93 unique_fd_impl& operator=(unique_fd_impl&& s) {
68 reset(s.release()); 94 int fd = s.fd_;
95 s.fd_ = -1;
96 reset(fd, &s);
69 return *this; 97 return *this;
70 } 98 }
71 99
72 void reset(int new_value = -1) { 100 void reset(int new_value = -1) { reset(new_value, nullptr); }
73 if (value_ != -1) {
74 Closer::Close(value_);
75 }
76 value_ = new_value;
77 }
78 101
79 int get() const { return value_; } 102 int get() const { return fd_; }
80 operator int() const { return get(); } 103 operator int() const { return get(); }
81 104
82 int release() __attribute__((warn_unused_result)) { 105 int release() __attribute__((warn_unused_result)) {
83 int ret = value_; 106 tag(fd_, this, nullptr);
84 value_ = -1; 107 int ret = fd_;
108 fd_ = -1;
85 return ret; 109 return ret;
86 } 110 }
87 111
88 private: 112 private:
89 int value_; 113 void reset(int new_value, void* previous_tag) {
114 if (fd_ != -1) {
115 close(fd_, this);
116 }
117
118 fd_ = new_value;
119 if (new_value != -1) {
120 tag(new_value, previous_tag, this);
121 }
122 }
123
124 int fd_ = -1;
125
126 // Template magic to use Closer::Tag if available, and do nothing if not.
127 // If Closer::Tag exists, this implementation is preferred, because int is a better match.
128 // If not, this implementation is SFINAEd away, and the no-op below is the only one that exists.
129 template <typename T = Closer>
130 static auto tag(int fd, void* old_tag, void* new_tag)
131 -> decltype(T::Tag(fd, old_tag, new_tag), void()) {
132 T::Tag(fd, old_tag, new_tag);
133 }
134
135 template <typename T = Closer>
136 static void tag(long, void*, void*) {
137 // No-op.
138 }
139
140 // Same as above, to select between Closer::Close(int) and Closer::Close(int, void*).
141 template <typename T = Closer>
142 static auto close(int fd, void* tag_value) -> decltype(T::Close(fd, tag_value), void()) {
143 T::Close(fd, tag_value);
144 }
145
146 template <typename T = Closer>
147 static auto close(int fd, void*) -> decltype(T::Close(fd), void()) {
148 T::Close(fd);
149 }
90 150
91 unique_fd_impl(const unique_fd_impl&); 151 unique_fd_impl(const unique_fd_impl&);
92 void operator=(const unique_fd_impl&); 152 void operator=(const unique_fd_impl&);
diff --git a/base/unique_fd_test.cpp b/base/unique_fd_test.cpp
new file mode 100644
index 000000000..3fdf12a30
--- /dev/null
+++ b/base/unique_fd_test.cpp
@@ -0,0 +1,54 @@
1/*
2 * Copyright (C) 2018 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#include "android-base/unique_fd.h"
18
19#include <gtest/gtest.h>
20
21#include <errno.h>
22#include <fcntl.h>
23#include <unistd.h>
24
25using android::base::unique_fd;
26
27TEST(unique_fd, unowned_close) {
28#if defined(__BIONIC__)
29 unique_fd fd(open("/dev/null", O_RDONLY));
30 EXPECT_DEATH(close(fd.get()), "incorrect tag");
31#endif
32}
33
34TEST(unique_fd, untag_on_release) {
35 unique_fd fd(open("/dev/null", O_RDONLY));
36 close(fd.release());
37}
38
39TEST(unique_fd, move) {
40 unique_fd fd(open("/dev/null", O_RDONLY));
41 unique_fd fd_moved = std::move(fd);
42 ASSERT_EQ(-1, fd.get());
43 ASSERT_GT(fd_moved.get(), -1);
44}
45
46TEST(unique_fd, unowned_close_after_move) {
47#if defined(__BIONIC__)
48 unique_fd fd(open("/dev/null", O_RDONLY));
49 unique_fd fd_moved = std::move(fd);
50 ASSERT_EQ(-1, fd.get());
51 ASSERT_GT(fd_moved.get(), -1);
52 EXPECT_DEATH(close(fd_moved.get()), "incorrect tag");
53#endif
54}