diff options
author | Josh Gao | 2018-07-20 14:42:14 -0500 |
---|---|---|
committer | Josh Gao | 2018-07-20 15:50:15 -0500 |
commit | 22666feacc24041c8d885c21b8403ae24db25618 (patch) | |
tree | 9edfbb5f3abc05ab29d0bd635e7afd9f6ada70d7 | |
parent | a570644b7df8f9a69b2a46a3a85052affcc5442c (diff) | |
download | platform-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
-rw-r--r-- | base/Android.bp | 1 | ||||
-rw-r--r-- | base/include/android-base/unique_fd.h | 88 | ||||
-rw-r--r-- | base/unique_fd_test.cpp | 54 |
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 | |||
45 | namespace android { | 50 | namespace android { |
46 | namespace base { | 51 | namespace base { |
47 | 52 | ||
48 | struct DefaultCloser { | 53 | struct 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 | ||
58 | template <typename Closer> | 84 | template <typename Closer> |
59 | class unique_fd_impl final { | 85 | class 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 | |||
25 | using android::base::unique_fd; | ||
26 | |||
27 | TEST(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 | |||
34 | TEST(unique_fd, untag_on_release) { | ||
35 | unique_fd fd(open("/dev/null", O_RDONLY)); | ||
36 | close(fd.release()); | ||
37 | } | ||
38 | |||
39 | TEST(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 | |||
46 | TEST(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 | } | ||