• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 
19 #include <dirent.h>
20 #include <err.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <netinet/in.h>
24 #include <stdlib.h>
25 #include <sys/epoll.h>
26 #include <sys/eventfd.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 
30 #if defined(__BIONIC__)
31 #include "platform/bionic/fdtrack.h"
32 #endif
33 
34 #include <vector>
35 
36 #include <android-base/cmsg.h>
37 #include <android-base/unique_fd.h>
38 
39 using android::base::ReceiveFileDescriptors;
40 using android::base::SendFileDescriptors;
41 using android::base::unique_fd;
42 
43 #if defined(__BIONIC__)
FdtrackRun(void (* func)())44 std::vector<android_fdtrack_event> FdtrackRun(void (*func)()) {
45   // Each bionic test is run in separate process, so we can safely use a static here.
46   static std::vector<android_fdtrack_event> events;
47   events.clear();
48 
49   android_fdtrack_hook_t previous = nullptr;
50   android_fdtrack_hook_t hook = [](android_fdtrack_event* event) {
51     events.push_back(*event);
52   };
53 
54   if (!android_fdtrack_compare_exchange_hook(&previous, hook)) {
55     errx(1, "failed to exchange hook: previous hook was %p", previous);
56   }
57 
58   if (previous) {
59     errx(1, "hook was already registered?");
60     abort();
61   }
62 
63   func();
64 
65   if (!android_fdtrack_compare_exchange_hook(&hook, nullptr)) {
66     errx(1, "failed to reset hook");
67   }
68 
69   return std::move(events);
70 }
71 
FdtrackEventTypeToName(android_fdtrack_event_type event_type)72 const char* FdtrackEventTypeToName(android_fdtrack_event_type event_type) {
73   switch (event_type) {
74     case ANDROID_FDTRACK_EVENT_TYPE_CREATE:
75       return "created";
76     case ANDROID_FDTRACK_EVENT_TYPE_CLOSE:
77       return "closed";
78   }
79 }
80 #endif
81 
TEST(fdtrack,close)82 TEST(fdtrack, close) {
83 #if defined(__BIONIC__)
84   static int fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
85   ASSERT_NE(-1, fd);
86 
87   auto events = FdtrackRun([]() { close(fd); });
88   ASSERT_EQ(1U, events.size());
89   ASSERT_EQ(fd, events[0].fd);
90   ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CLOSE, events[0].type);
91 #endif
92 }
93 
TEST(fdtrack,enable_disable)94 TEST(fdtrack, enable_disable) {
95 #if defined(__BIONIC__)
96   static int fd1 = -1;
97   static int fd2 = -1;
98   static int fd3 = -1;
99 
100   auto events = FdtrackRun([]() {
101     if (!android_fdtrack_get_enabled()) {
102       errx(1, "fdtrack is disabled");
103     }
104     fd1 = open("/dev/null", O_WRONLY | O_CLOEXEC);
105     android_fdtrack_set_enabled(false);
106     fd2 = open("/dev/null", O_WRONLY | O_CLOEXEC);
107     android_fdtrack_set_enabled(true);
108     fd3 = open("/dev/null", O_WRONLY | O_CLOEXEC);
109   });
110 
111   if (fd1 == -1 || fd2 == -1 || fd3 == -1) {
112     errx(1, "failed to open /dev/null");
113   }
114 
115   ASSERT_EQ(2U, events.size());
116 
117   ASSERT_EQ(fd1, events[0].fd);
118   ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, events[0].type);
119   ASSERT_STREQ("open", events[0].data.create.function_name);
120 
121   ASSERT_EQ(fd3, events[1].fd);
122   ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, events[1].type);
123   ASSERT_STREQ("open", events[1].data.create.function_name);
124 #endif
125 }
126 
127 struct require_semicolon;
128 
129 #if defined(__BIONIC__)
SetFdResult(std::vector<int> * output,int fd)130 void SetFdResult(std::vector<int>* output, int fd) {
131   output->push_back(fd);
132 }
133 
SetFdResult(std::vector<int> * output,std::vector<int> fds)134 void SetFdResult(std::vector<int>* output, std::vector<int> fds) {
135   *output = fds;
136 }
137 
138 #define FDTRACK_TEST_NAME(test_name, fdtrack_name, expression)                                   \
139   TEST(fdtrack, test_name) {                                                                     \
140     static std::vector<int> expected_fds;                                                        \
141     auto events = FdtrackRun([]() { SetFdResult(&expected_fds, expression); });                  \
142     for (auto& fd : expected_fds) {                                                              \
143       ASSERT_NE(-1, fd);                                                                         \
144     }                                                                                            \
145     if (events.size() != expected_fds.size()) {                                                  \
146       fprintf(stderr, "too many events received: expected %zu, got %zu:\n", expected_fds.size(), \
147               events.size());                                                                    \
148       for (size_t i = 0; i < events.size(); ++i) {                                               \
149         auto& event = events[i];                                                                 \
150         if (event.type == ANDROID_FDTRACK_EVENT_TYPE_CREATE) {                                   \
151           fprintf(stderr, "  event %zu: fd %d created by %s\n", i, event.fd,                     \
152                   event.data.create.function_name);                                              \
153         } else if (event.type == ANDROID_FDTRACK_EVENT_TYPE_CLOSE) {                             \
154           fprintf(stderr, "  event %zu: fd %d closed\n", i, event.fd);                           \
155         } else {                                                                                 \
156           errx(1, "unexpected fdtrack event type: %d", event.type);                              \
157         }                                                                                        \
158       }                                                                                          \
159       FAIL();                                                                                    \
160       return;                                                                                    \
161     }                                                                                            \
162     for (auto& event : events) {                                                                 \
163       ASSERT_NE(expected_fds.end(),                                                              \
164                 std::find(expected_fds.begin(), expected_fds.end(), events[0].fd));              \
165       ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, event.type);                                  \
166       ASSERT_STREQ(fdtrack_name, event.data.create.function_name);                               \
167     }                                                                                            \
168   }                                                                                              \
169   struct require_semicolon
170 #else
171 #define FDTRACK_TEST_NAME(name, fdtrack_name, expression) \
172   TEST(fdtrack, name) {}                                  \
173   struct require_semicolon
174 #endif
175 
176 #define FDTRACK_TEST(name, expression) FDTRACK_TEST_NAME(name, #name, expression)
177 
178 // clang-format misformats statement expressions pretty badly here:
179 // clang-format off
180 FDTRACK_TEST(open, open("/dev/null", O_WRONLY | O_CLOEXEC));
181 FDTRACK_TEST(openat, openat(AT_EMPTY_PATH, "/dev/null", O_WRONLY | O_CLOEXEC));
182 FDTRACK_TEST(socket, socket(AF_UNIX, SOCK_STREAM, 0));
183 
184 FDTRACK_TEST(dup, dup(STDOUT_FILENO));
185 FDTRACK_TEST(dup2, dup2(STDOUT_FILENO, STDERR_FILENO));
186 FDTRACK_TEST(dup3, dup3(STDOUT_FILENO, STDERR_FILENO, 0));
187 FDTRACK_TEST_NAME(fcntl_F_DUPFD, "F_DUPFD", fcntl(STDOUT_FILENO, F_DUPFD, 0));
188 FDTRACK_TEST_NAME(fcntl_F_DUPFD_CLOEXEC, "F_DUPFD_CLOEXEC", fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0));
189 
190 FDTRACK_TEST(pipe, ({
191   std::vector<int> fds = { -1, -1};
192   if (pipe(fds.data()) != 0) {
193     err(1, "pipe failed");
194   }
195   fds;
196 }));
197 
198 FDTRACK_TEST(pipe2, ({
199   std::vector<int> fds = { -1, -1};
200   if (pipe2(fds.data(), O_CLOEXEC) != 0) {
201     err(1, "pipe failed");
202   }
203   fds;
204 }));
205 
206 FDTRACK_TEST(socketpair, ({
207   std::vector<int> fds = { -1, -1};
208   if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds.data()) != 0) {
209     err(1, "socketpair failed");
210   }
211   fds;
212 }));
213 
214 FDTRACK_TEST(epoll_create, epoll_create(1));
215 FDTRACK_TEST(epoll_create1, epoll_create1(0));
216 
217 FDTRACK_TEST(eventfd, eventfd(0, 0));
218 
219 #if 0
220 // Why is this generating an extra socket/close event?
221 FDTRACK_TEST(accept, ({
222   android_fdtrack_set_enabled(false);
223   int listener = socket(AF_INET, SOCK_STREAM, 0);
224   ASSERT_NE(-1, listener);
225 
226   sockaddr_in addr = {
227       .sin_family = AF_INET,
228       .sin_port = 0,
229       .sin_addr = {htonl(INADDR_LOOPBACK)},
230   };
231   socklen_t addrlen = sizeof(addr);
232 
233   ASSERT_NE(-1, bind(listener, reinterpret_cast<sockaddr*>(&addr), addrlen)) << strerror(errno);
234   ASSERT_NE(-1, getsockname(listener, reinterpret_cast<sockaddr*>(&addr), &addrlen));
235   ASSERT_EQ(static_cast<size_t>(addrlen), sizeof(addr));
236   ASSERT_NE(-1, listen(listener, 1));
237 
238   int connector = socket(AF_INET, SOCK_STREAM, 0);
239   ASSERT_NE(-1, connector);
240   ASSERT_NE(-1, connect(connector, reinterpret_cast<sockaddr*>(&addr), addrlen));
241 
242   android_fdtrack_set_enabled(true);
243   int accepted = accept(listener, nullptr, nullptr);
244   accepted;
245 }));
246 #endif
247 
248 FDTRACK_TEST(recvmsg, ({
249   android_fdtrack_set_enabled(false);
250   int sockets[2];
251   ASSERT_NE(-1, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets));
252   ASSERT_EQ(3, SendFileDescriptors(sockets[0], "foo", 3, STDIN_FILENO));
253   android_fdtrack_set_enabled(true);
254 
255   char buf[4];
256   unique_fd received_fd;
257   ASSERT_EQ(3, ReceiveFileDescriptors(sockets[1], buf, sizeof(buf), &received_fd));
258   received_fd.release();
259 }));
260 
261 FDTRACK_TEST_NAME(vfork, "open", ({
262   int fd = open("/dev/null", O_RDONLY);
263 
264   pid_t rc = vfork();
265   ASSERT_NE(-1, rc);
266 
267   if (rc == 0) {
268     close(fd);
269     _exit(0);
270   }
271 
272   int status;
273   pid_t wait_result = waitpid(rc, &status, 0);
274   ASSERT_EQ(wait_result, rc);
275   ASSERT_TRUE(WIFEXITED(status));
276   ASSERT_EQ(0, WEXITSTATUS(status));
277 
278   fd;
279 }));
280 // clang-format on
281