blob: c1e926b14bbc4e9f2481acd217208abd32c8543c [file] [log] [blame]
Josh Gaof6e5b582018-06-01 15:30:54 -07001/*
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 <gtest/gtest.h>
18
Josh Gaof6e5b582018-06-01 15:30:54 -070019#include <dirent.h>
20#include <errno.h>
21#include <fcntl.h>
22#include <stdlib.h>
23#include <sys/types.h>
Josh Gao65fb2a72020-05-07 19:40:14 -070024#include <unistd.h>
Josh Gaof6e5b582018-06-01 15:30:54 -070025
Josh Gaof6e5b582018-06-01 15:30:54 -070026#if defined(__BIONIC__)
27#include <android/fdsan.h>
Elliott Hughesd76dd142021-02-18 17:27:16 -080028#include <bionic/reserved_signals.h>
Josh Gaof6e5b582018-06-01 15:30:54 -070029#endif
30
Josh Gao7266e912018-08-08 17:31:19 -070031#include <unordered_map>
32
Elliott Hughes141b9172021-04-09 17:13:09 -070033#include <android-base/silent_death_test.h>
Josh Gao7266e912018-08-08 17:31:19 -070034#include <android-base/unique_fd.h>
35
Josh Gaof6e5b582018-06-01 15:30:54 -070036#define EXPECT_FDSAN_DEATH(expression, regex) \
37 EXPECT_DEATH((android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_FATAL), expression), \
38 (regex))
39
Elliott Hughesd76dd142021-02-18 17:27:16 -080040struct fdsan : public ::testing::Test {
Josh Gaof6e5b582018-06-01 15:30:54 -070041 void SetUp() override {
42#if defined(__BIONIC__)
43 // The bionic unit test running forks for each test by default, which turns
44 // fdsan off as a side-effect, so we need to turn it back on.
45 android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_FATAL);
46#endif
47 }
48};
49
Elliott Hughes141b9172021-04-09 17:13:09 -070050struct fdsan_DeathTest : public SilentDeathTest {
Elliott Hughesd76dd142021-02-18 17:27:16 -080051#if defined(__BIONIC__)
52 void SetUp() override {
53 android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_FATAL);
54 signal(BIONIC_SIGNAL_DEBUGGER, SIG_DFL); // Disable debuggerd.
Elliott Hughes141b9172021-04-09 17:13:09 -070055 SilentDeathTest::SetUp();
Elliott Hughesd76dd142021-02-18 17:27:16 -080056 }
57#endif
58};
59
60TEST_F(fdsan, unowned_untagged_close) {
Josh Gaof6e5b582018-06-01 15:30:54 -070061#if defined(__BIONIC__)
62 int fd = open("/dev/null", O_RDONLY);
63 ASSERT_EQ(0, close(fd));
64#endif
65}
66
Elliott Hughesd76dd142021-02-18 17:27:16 -080067TEST_F(fdsan, unowned_tagged_close) {
Josh Gaof6e5b582018-06-01 15:30:54 -070068#if defined(__BIONIC__)
69 int fd = open("/dev/null", O_RDONLY);
70 ASSERT_EQ(0, android_fdsan_close_with_tag(fd, 0));
71#endif
72}
73
Elliott Hughesd76dd142021-02-18 17:27:16 -080074TEST_F(fdsan_DeathTest, unowned_improperly_tagged_close) {
Josh Gaof6e5b582018-06-01 15:30:54 -070075#if defined(__BIONIC__)
76 int fd = open("/dev/null", O_RDONLY);
77 EXPECT_FDSAN_DEATH(android_fdsan_close_with_tag(fd, 0xdeadbeef), "actually unowned");
78#endif
79}
80
Elliott Hughesd76dd142021-02-18 17:27:16 -080081TEST_F(fdsan_DeathTest, unowned_incorrect_exchange) {
Josh Gaof6e5b582018-06-01 15:30:54 -070082#if defined(__BIONIC__)
83 int fd = open("/dev/null", O_RDONLY);
84 EXPECT_FDSAN_DEATH(android_fdsan_exchange_owner_tag(fd, 0xbadc0de, 0xdeadbeef),
Josh Gao08b7a402018-08-03 14:31:37 -070085 "failed to exchange ownership");
Josh Gaof6e5b582018-06-01 15:30:54 -070086#endif
87}
88
Elliott Hughesd76dd142021-02-18 17:27:16 -080089TEST_F(fdsan_DeathTest, owned_untagged_close) {
Josh Gaof6e5b582018-06-01 15:30:54 -070090#if defined(__BIONIC__)
91 int fd = open("/dev/null", O_RDONLY);
92 android_fdsan_exchange_owner_tag(fd, 0, 0xdeadbeef);
93 EXPECT_FDSAN_DEATH(close(fd), "expected to be unowned, actually owned");
94#endif
95}
96
Elliott Hughesd76dd142021-02-18 17:27:16 -080097TEST_F(fdsan, owned_tagged_close) {
Josh Gaof6e5b582018-06-01 15:30:54 -070098#if defined(__BIONIC__)
99 int fd = open("/dev/null", O_RDONLY);
100 android_fdsan_exchange_owner_tag(fd, 0, 0xdeadbeef);
101 ASSERT_EQ(0, android_fdsan_close_with_tag(fd, 0xdeadbeef));
102#endif
103}
104
Elliott Hughesd76dd142021-02-18 17:27:16 -0800105TEST_F(fdsan_DeathTest, owned_improperly_tagged_close) {
Josh Gaof6e5b582018-06-01 15:30:54 -0700106#if defined(__BIONIC__)
107 int fd = open("/dev/null", O_RDONLY);
108 android_fdsan_exchange_owner_tag(fd, 0, 0xdeadbeef);
109 EXPECT_FDSAN_DEATH(android_fdsan_close_with_tag(fd, 0xdeadc0de), "expected to be owned");
110#endif
111}
112
Elliott Hughesd76dd142021-02-18 17:27:16 -0800113TEST_F(fdsan_DeathTest, owned_incorrect_exchange) {
Josh Gaof6e5b582018-06-01 15:30:54 -0700114#if defined(__BIONIC__)
115 int fd = open("/dev/null", O_RDONLY);
116 android_fdsan_exchange_owner_tag(fd, 0, 0xdeadbeef);
117 EXPECT_FDSAN_DEATH(android_fdsan_exchange_owner_tag(fd, 0xbadc0de, 0xdeadbeef),
118 "failed to exchange");
119#endif
120}
121
Elliott Hughesd76dd142021-02-18 17:27:16 -0800122TEST_F(fdsan_DeathTest, fopen) {
Josh Gaof6e5b582018-06-01 15:30:54 -0700123#if defined(__BIONIC__)
124 FILE* f = fopen("/dev/null", "r");
125 ASSERT_TRUE(f);
126 EXPECT_FDSAN_DEATH(close(fileno(f)), "actually owned by FILE");
127#endif
128}
129
Elliott Hughesd76dd142021-02-18 17:27:16 -0800130TEST_F(fdsan_DeathTest, closedir) {
Josh Gaof6e5b582018-06-01 15:30:54 -0700131#if defined(__BIONIC__)
132 DIR* dir = opendir("/dev/");
133 ASSERT_TRUE(dir);
134 EXPECT_FDSAN_DEATH(close(dirfd(dir)), "actually owned by DIR");
135#endif
136}
137
Elliott Hughesd76dd142021-02-18 17:27:16 -0800138TEST_F(fdsan, overflow) {
Josh Gaof6e5b582018-06-01 15:30:54 -0700139#if defined(__BIONIC__)
140 std::unordered_map<int, uint64_t> fds;
141 for (int i = 0; i < 4096; ++i) {
142 int fd = open("/dev/null", O_RDONLY);
143 auto tag = 0xdead00000000ULL | i;
144 android_fdsan_exchange_owner_tag(fd, 0, tag);
145 fds[fd] = tag;
146 }
147
148 for (auto [fd, tag] : fds) {
149 android_fdsan_close_with_tag(fd, tag);
150 }
151#endif
152}
Josh Gao08b7a402018-08-03 14:31:37 -0700153
Elliott Hughesd76dd142021-02-18 17:27:16 -0800154TEST_F(fdsan_DeathTest, owner_value_high) {
Josh Gao08b7a402018-08-03 14:31:37 -0700155#if defined(__BIONIC__)
156 int fd = open("/dev/null", O_RDONLY);
157 uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD, ~0ULL);
158 android_fdsan_exchange_owner_tag(fd, 0, tag);
159 EXPECT_FDSAN_DEATH(android_fdsan_exchange_owner_tag(fd, 0xbadc0de, 0xdeadbeef),
160 "0xffffffffffffffff");
161#endif
162}
163
Elliott Hughesd76dd142021-02-18 17:27:16 -0800164TEST_F(fdsan_DeathTest, owner_value_low) {
Josh Gao08b7a402018-08-03 14:31:37 -0700165#if defined(__BIONIC__)
166 int fd = open("/dev/null", O_RDONLY);
167 uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD, 1);
168 android_fdsan_exchange_owner_tag(fd, 0, tag);
169 EXPECT_FDSAN_DEATH(android_fdsan_exchange_owner_tag(fd, 0xbadc0de, 0xdeadbeef),
170 "0x1");
171#endif
172}
Josh Gao7266e912018-08-08 17:31:19 -0700173
Elliott Hughesd76dd142021-02-18 17:27:16 -0800174TEST_F(fdsan_DeathTest, unique_fd_unowned_close) {
Josh Gao7266e912018-08-08 17:31:19 -0700175#if defined(__BIONIC__)
176 android::base::unique_fd fd(open("/dev/null", O_RDONLY));
177 android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_FATAL);
178 EXPECT_FDSAN_DEATH(close(fd.get()), "expected to be unowned, actually owned by unique_fd");
179#endif
180}
181
Elliott Hughesd76dd142021-02-18 17:27:16 -0800182TEST_F(fdsan, unique_fd_untag_on_release) {
Josh Gao7266e912018-08-08 17:31:19 -0700183 android::base::unique_fd fd(open("/dev/null", O_RDONLY));
184 close(fd.release());
185}
186
Elliott Hughesd76dd142021-02-18 17:27:16 -0800187TEST_F(fdsan, unique_fd_move) {
Josh Gao7266e912018-08-08 17:31:19 -0700188 android::base::unique_fd fd(open("/dev/null", O_RDONLY));
189 android::base::unique_fd fd_moved = std::move(fd);
190 ASSERT_EQ(-1, fd.get());
191 ASSERT_GT(fd_moved.get(), -1);
192}
193
Elliott Hughesd76dd142021-02-18 17:27:16 -0800194TEST_F(fdsan_DeathTest, unique_fd_unowned_close_after_move) {
Josh Gao7266e912018-08-08 17:31:19 -0700195#if defined(__BIONIC__)
196 android::base::unique_fd fd(open("/dev/null", O_RDONLY));
197 android::base::unique_fd fd_moved = std::move(fd);
198 ASSERT_EQ(-1, fd.get());
199 ASSERT_GT(fd_moved.get(), -1);
200
201 android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_FATAL);
202 EXPECT_FDSAN_DEATH(close(fd_moved.get()), "expected to be unowned, actually owned by unique_fd");
203#endif
204}
Josh Gao65fb2a72020-05-07 19:40:14 -0700205
Elliott Hughesd76dd142021-02-18 17:27:16 -0800206TEST_F(fdsan, vfork) {
Josh Gao65fb2a72020-05-07 19:40:14 -0700207 android::base::unique_fd fd(open("/dev/null", O_RDONLY));
208
209 pid_t rc = vfork();
210 ASSERT_NE(-1, rc);
211
212 if (rc == 0) {
213 close(fd.get());
214 _exit(0);
215 }
216
217 int status;
218 pid_t wait_result = waitpid(rc, &status, 0);
219 ASSERT_EQ(wait_result, rc);
220 ASSERT_TRUE(WIFEXITED(status));
221 ASSERT_EQ(0, WEXITSTATUS(status));
222}