|
46 | 46 |
|
47 | 47 | #include <linux/sched.h> |
48 | 48 | #include <sys/epoll.h> |
| 49 | +#include <sys/mman.h> |
49 | 50 | #include <sys/prctl.h> |
50 | 51 | #include <sys/socket.h> |
51 | 52 | #include <sys/un.h> |
@@ -110,6 +111,8 @@ enum BinderLibTestTranscationCode { |
110 | 111 | BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, |
111 | 112 | BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, |
112 | 113 | BINDER_LIB_TEST_WRITE_PARCEL_FILE_DESCRIPTOR_TRANSACTION, |
| 114 | + BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, |
| 115 | + BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, |
113 | 116 | BINDER_LIB_TEST_EXIT_TRANSACTION, |
114 | 117 | BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION, |
115 | 118 | BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, |
@@ -536,6 +539,30 @@ class TestDeathRecipient : public IBinder::DeathRecipient, public BinderLibTestE |
536 | 539 | }; |
537 | 540 | }; |
538 | 541 |
|
| 542 | +ssize_t countFds() { |
| 543 | + return std::distance(std::filesystem::directory_iterator("/proc/self/fd"), |
| 544 | + std::filesystem::directory_iterator{}); |
| 545 | +} |
| 546 | + |
| 547 | +struct FdLeakDetector { |
| 548 | + int startCount; |
| 549 | + |
| 550 | + FdLeakDetector() { |
| 551 | + // This log statement is load bearing. We have to log something before |
| 552 | + // counting FDs to make sure the logging system is initialized, otherwise |
| 553 | + // the sockets it opens will look like a leak. |
| 554 | + ALOGW("FdLeakDetector counting FDs."); |
| 555 | + startCount = countFds(); |
| 556 | + } |
| 557 | + ~FdLeakDetector() { |
| 558 | + int endCount = countFds(); |
| 559 | + if (startCount != endCount) { |
| 560 | + ADD_FAILURE() << "fd count changed (" << startCount << " -> " << endCount |
| 561 | + << ") fd leak?"; |
| 562 | + } |
| 563 | + } |
| 564 | +}; |
| 565 | + |
539 | 566 | TEST_F(BinderLibTest, CannotUseBinderAfterFork) { |
540 | 567 | // EXPECT_DEATH works by forking the process |
541 | 568 | EXPECT_DEATH({ ProcessState::self(); }, "libbinder ProcessState can not be used after fork"); |
@@ -1175,6 +1202,100 @@ TEST_F(BinderLibTest, PassParcelFileDescriptor) { |
1175 | 1202 | EXPECT_EQ(0, read(read_end.get(), readbuf.data(), datasize)); |
1176 | 1203 | } |
1177 | 1204 |
|
| 1205 | +TEST_F(BinderLibTest, RecvOwnedFileDescriptors) { |
| 1206 | + FdLeakDetector fd_leak_detector; |
| 1207 | + |
| 1208 | + Parcel data; |
| 1209 | + Parcel reply; |
| 1210 | + EXPECT_EQ(NO_ERROR, |
| 1211 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, |
| 1212 | + &reply)); |
| 1213 | + unique_fd a, b; |
| 1214 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 1215 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); |
| 1216 | +} |
| 1217 | + |
| 1218 | +// Used to trigger fdsan error (b/239222407). |
| 1219 | +TEST_F(BinderLibTest, RecvOwnedFileDescriptorsAndWriteInt) { |
| 1220 | + GTEST_SKIP() << "triggers fdsan false positive: b/370824489"; |
| 1221 | + |
| 1222 | + FdLeakDetector fd_leak_detector; |
| 1223 | + |
| 1224 | + Parcel data; |
| 1225 | + Parcel reply; |
| 1226 | + EXPECT_EQ(NO_ERROR, |
| 1227 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, |
| 1228 | + &reply)); |
| 1229 | + reply.setDataPosition(reply.dataSize()); |
| 1230 | + reply.writeInt32(0); |
| 1231 | + reply.setDataPosition(0); |
| 1232 | + unique_fd a, b; |
| 1233 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 1234 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); |
| 1235 | +} |
| 1236 | + |
| 1237 | +// Used to trigger fdsan error (b/239222407). |
| 1238 | +TEST_F(BinderLibTest, RecvOwnedFileDescriptorsAndTruncate) { |
| 1239 | + GTEST_SKIP() << "triggers fdsan false positive: b/370824489"; |
| 1240 | + |
| 1241 | + FdLeakDetector fd_leak_detector; |
| 1242 | + |
| 1243 | + Parcel data; |
| 1244 | + Parcel reply; |
| 1245 | + EXPECT_EQ(NO_ERROR, |
| 1246 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, |
| 1247 | + &reply)); |
| 1248 | + reply.setDataSize(reply.dataSize() - sizeof(flat_binder_object)); |
| 1249 | + unique_fd a, b; |
| 1250 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 1251 | + EXPECT_EQ(BAD_TYPE, reply.readUniqueFileDescriptor(&b)); |
| 1252 | +} |
| 1253 | + |
| 1254 | +TEST_F(BinderLibTest, RecvUnownedFileDescriptors) { |
| 1255 | + FdLeakDetector fd_leak_detector; |
| 1256 | + |
| 1257 | + Parcel data; |
| 1258 | + Parcel reply; |
| 1259 | + EXPECT_EQ(NO_ERROR, |
| 1260 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, |
| 1261 | + &reply)); |
| 1262 | + unique_fd a, b; |
| 1263 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 1264 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); |
| 1265 | +} |
| 1266 | + |
| 1267 | +// Used to trigger fdsan error (b/239222407). |
| 1268 | +TEST_F(BinderLibTest, RecvUnownedFileDescriptorsAndWriteInt) { |
| 1269 | + FdLeakDetector fd_leak_detector; |
| 1270 | + |
| 1271 | + Parcel data; |
| 1272 | + Parcel reply; |
| 1273 | + EXPECT_EQ(NO_ERROR, |
| 1274 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, |
| 1275 | + &reply)); |
| 1276 | + reply.setDataPosition(reply.dataSize()); |
| 1277 | + reply.writeInt32(0); |
| 1278 | + reply.setDataPosition(0); |
| 1279 | + unique_fd a, b; |
| 1280 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 1281 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); |
| 1282 | +} |
| 1283 | + |
| 1284 | +// Used to trigger fdsan error (b/239222407). |
| 1285 | +TEST_F(BinderLibTest, RecvUnownedFileDescriptorsAndTruncate) { |
| 1286 | + FdLeakDetector fd_leak_detector; |
| 1287 | + |
| 1288 | + Parcel data; |
| 1289 | + Parcel reply; |
| 1290 | + EXPECT_EQ(NO_ERROR, |
| 1291 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, |
| 1292 | + &reply)); |
| 1293 | + reply.setDataSize(reply.dataSize() - sizeof(flat_binder_object)); |
| 1294 | + unique_fd a, b; |
| 1295 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 1296 | + EXPECT_EQ(BAD_TYPE, reply.readUniqueFileDescriptor(&b)); |
| 1297 | +} |
| 1298 | + |
1178 | 1299 | TEST_F(BinderLibTest, PromoteLocal) { |
1179 | 1300 | sp<IBinder> strong = new BBinder(); |
1180 | 1301 | wp<IBinder> weak = strong; |
@@ -2224,6 +2345,40 @@ class BinderLibTestService : public BBinder { |
2224 | 2345 | if (ret != size) return UNKNOWN_ERROR; |
2225 | 2346 | return NO_ERROR; |
2226 | 2347 | } |
| 2348 | + case BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION: { |
| 2349 | + unique_fd fd1(memfd_create("memfd1", MFD_CLOEXEC)); |
| 2350 | + if (!fd1.ok()) { |
| 2351 | + PLOGE("memfd_create failed"); |
| 2352 | + return UNKNOWN_ERROR; |
| 2353 | + } |
| 2354 | + unique_fd fd2(memfd_create("memfd2", MFD_CLOEXEC)); |
| 2355 | + if (!fd2.ok()) { |
| 2356 | + PLOGE("memfd_create failed"); |
| 2357 | + return UNKNOWN_ERROR; |
| 2358 | + } |
| 2359 | + status_t ret; |
| 2360 | + ret = reply->writeFileDescriptor(fd1.release(), true); |
| 2361 | + if (ret != NO_ERROR) { |
| 2362 | + return ret; |
| 2363 | + } |
| 2364 | + ret = reply->writeFileDescriptor(fd2.release(), true); |
| 2365 | + if (ret != NO_ERROR) { |
| 2366 | + return ret; |
| 2367 | + } |
| 2368 | + return NO_ERROR; |
| 2369 | + } |
| 2370 | + case BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION: { |
| 2371 | + status_t ret; |
| 2372 | + ret = reply->writeFileDescriptor(STDOUT_FILENO, false); |
| 2373 | + if (ret != NO_ERROR) { |
| 2374 | + return ret; |
| 2375 | + } |
| 2376 | + ret = reply->writeFileDescriptor(STDERR_FILENO, false); |
| 2377 | + if (ret != NO_ERROR) { |
| 2378 | + return ret; |
| 2379 | + } |
| 2380 | + return NO_ERROR; |
| 2381 | + } |
2227 | 2382 | case BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION: |
2228 | 2383 | alarm(10); |
2229 | 2384 | return NO_ERROR; |
|
0 commit comments