|
26 | 26 | #include <gmock/gmock.h> |
27 | 27 | #include <gtest/gtest.h> |
28 | 28 |
|
| 29 | +#include <android-base/logging.h> |
| 30 | +#include <android-base/unique_fd.h> |
29 | 31 | #include <binder/Binder.h> |
30 | 32 | #include <binder/IBinder.h> |
31 | 33 | #include <binder/IPCThreadState.h> |
32 | 34 | #include <binder/IServiceManager.h> |
33 | 35 |
|
34 | 36 | #include <linux/sched.h> |
35 | 37 | #include <sys/epoll.h> |
| 38 | +#include <sys/mman.h> |
36 | 39 | #include <sys/prctl.h> |
37 | 40 |
|
38 | 41 | #include "../binder_module.h" |
|
41 | 44 | #define ARRAY_SIZE(array) (sizeof array / sizeof array[0]) |
42 | 45 |
|
43 | 46 | using namespace android; |
| 47 | +using android::base::unique_fd; |
44 | 48 | using testing::Not; |
45 | 49 |
|
46 | 50 | // e.g. EXPECT_THAT(expr, StatusEq(OK)) << "additional message"; |
@@ -85,6 +89,8 @@ enum BinderLibTestTranscationCode { |
85 | 89 | BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, |
86 | 90 | BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, |
87 | 91 | BINDER_LIB_TEST_WRITE_PARCEL_FILE_DESCRIPTOR_TRANSACTION, |
| 92 | + BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, |
| 93 | + BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, |
88 | 94 | BINDER_LIB_TEST_EXIT_TRANSACTION, |
89 | 95 | BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION, |
90 | 96 | BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, |
@@ -404,6 +410,35 @@ class TestDeathRecipient : public IBinder::DeathRecipient, public BinderLibTestE |
404 | 410 | }; |
405 | 411 | }; |
406 | 412 |
|
| 413 | +ssize_t countFds() { |
| 414 | + DIR* dir = opendir("/proc/self/fd/"); |
| 415 | + if (dir == nullptr) return -1; |
| 416 | + ssize_t ret = 0; |
| 417 | + dirent* ent; |
| 418 | + while ((ent = readdir(dir)) != nullptr) ret++; |
| 419 | + closedir(dir); |
| 420 | + return ret; |
| 421 | +} |
| 422 | + |
| 423 | +struct FdLeakDetector { |
| 424 | + int startCount; |
| 425 | + |
| 426 | + FdLeakDetector() { |
| 427 | + // This log statement is load bearing. We have to log something before |
| 428 | + // counting FDs to make sure the logging system is initialized, otherwise |
| 429 | + // the sockets it opens will look like a leak. |
| 430 | + ALOGW("FdLeakDetector counting FDs."); |
| 431 | + startCount = countFds(); |
| 432 | + } |
| 433 | + ~FdLeakDetector() { |
| 434 | + int endCount = countFds(); |
| 435 | + if (startCount != endCount) { |
| 436 | + ADD_FAILURE() << "fd count changed (" << startCount << " -> " << endCount |
| 437 | + << ") fd leak?"; |
| 438 | + } |
| 439 | + } |
| 440 | +}; |
| 441 | + |
407 | 442 | TEST_F(BinderLibTest, NopTransaction) { |
408 | 443 | Parcel data, reply; |
409 | 444 | EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply), |
@@ -805,6 +840,100 @@ TEST_F(BinderLibTest, PassParcelFileDescriptor) { |
805 | 840 | EXPECT_EQ(0, read(read_end.get(), readbuf.data(), datasize)); |
806 | 841 | } |
807 | 842 |
|
| 843 | +TEST_F(BinderLibTest, RecvOwnedFileDescriptors) { |
| 844 | + FdLeakDetector fd_leak_detector; |
| 845 | + |
| 846 | + Parcel data; |
| 847 | + Parcel reply; |
| 848 | + EXPECT_EQ(NO_ERROR, |
| 849 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, |
| 850 | + &reply)); |
| 851 | + unique_fd a, b; |
| 852 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 853 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); |
| 854 | +} |
| 855 | + |
| 856 | +// Used to trigger fdsan error (b/239222407). |
| 857 | +TEST_F(BinderLibTest, RecvOwnedFileDescriptorsAndWriteInt) { |
| 858 | + GTEST_SKIP() << "triggers fdsan false positive: b/370824489"; |
| 859 | + |
| 860 | + FdLeakDetector fd_leak_detector; |
| 861 | + |
| 862 | + Parcel data; |
| 863 | + Parcel reply; |
| 864 | + EXPECT_EQ(NO_ERROR, |
| 865 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, |
| 866 | + &reply)); |
| 867 | + reply.setDataPosition(reply.dataSize()); |
| 868 | + reply.writeInt32(0); |
| 869 | + reply.setDataPosition(0); |
| 870 | + unique_fd a, b; |
| 871 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 872 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); |
| 873 | +} |
| 874 | + |
| 875 | +// Used to trigger fdsan error (b/239222407). |
| 876 | +TEST_F(BinderLibTest, RecvOwnedFileDescriptorsAndTruncate) { |
| 877 | + GTEST_SKIP() << "triggers fdsan false positive: b/370824489"; |
| 878 | + |
| 879 | + FdLeakDetector fd_leak_detector; |
| 880 | + |
| 881 | + Parcel data; |
| 882 | + Parcel reply; |
| 883 | + EXPECT_EQ(NO_ERROR, |
| 884 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, |
| 885 | + &reply)); |
| 886 | + reply.setDataSize(reply.dataSize() - sizeof(flat_binder_object)); |
| 887 | + unique_fd a, b; |
| 888 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 889 | + EXPECT_EQ(BAD_TYPE, reply.readUniqueFileDescriptor(&b)); |
| 890 | +} |
| 891 | + |
| 892 | +TEST_F(BinderLibTest, RecvUnownedFileDescriptors) { |
| 893 | + FdLeakDetector fd_leak_detector; |
| 894 | + |
| 895 | + Parcel data; |
| 896 | + Parcel reply; |
| 897 | + EXPECT_EQ(NO_ERROR, |
| 898 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, |
| 899 | + &reply)); |
| 900 | + unique_fd a, b; |
| 901 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 902 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); |
| 903 | +} |
| 904 | + |
| 905 | +// Used to trigger fdsan error (b/239222407). |
| 906 | +TEST_F(BinderLibTest, RecvUnownedFileDescriptorsAndWriteInt) { |
| 907 | + FdLeakDetector fd_leak_detector; |
| 908 | + |
| 909 | + Parcel data; |
| 910 | + Parcel reply; |
| 911 | + EXPECT_EQ(NO_ERROR, |
| 912 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, |
| 913 | + &reply)); |
| 914 | + reply.setDataPosition(reply.dataSize()); |
| 915 | + reply.writeInt32(0); |
| 916 | + reply.setDataPosition(0); |
| 917 | + unique_fd a, b; |
| 918 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 919 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); |
| 920 | +} |
| 921 | + |
| 922 | +// Used to trigger fdsan error (b/239222407). |
| 923 | +TEST_F(BinderLibTest, RecvUnownedFileDescriptorsAndTruncate) { |
| 924 | + FdLeakDetector fd_leak_detector; |
| 925 | + |
| 926 | + Parcel data; |
| 927 | + Parcel reply; |
| 928 | + EXPECT_EQ(NO_ERROR, |
| 929 | + m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, |
| 930 | + &reply)); |
| 931 | + reply.setDataSize(reply.dataSize() - sizeof(flat_binder_object)); |
| 932 | + unique_fd a, b; |
| 933 | + EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); |
| 934 | + EXPECT_EQ(BAD_TYPE, reply.readUniqueFileDescriptor(&b)); |
| 935 | +} |
| 936 | + |
808 | 937 | TEST_F(BinderLibTest, PromoteLocal) { |
809 | 938 | sp<IBinder> strong = new BBinder(); |
810 | 939 | wp<IBinder> weak = strong; |
@@ -1438,6 +1567,40 @@ class BinderLibTestService : public BBinder |
1438 | 1567 | if (ret != size) return UNKNOWN_ERROR; |
1439 | 1568 | return NO_ERROR; |
1440 | 1569 | } |
| 1570 | + case BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION: { |
| 1571 | + unique_fd fd1(memfd_create("memfd1", MFD_CLOEXEC)); |
| 1572 | + if (!fd1.ok()) { |
| 1573 | + PLOG(ERROR) << "memfd_create failed"; |
| 1574 | + return UNKNOWN_ERROR; |
| 1575 | + } |
| 1576 | + unique_fd fd2(memfd_create("memfd2", MFD_CLOEXEC)); |
| 1577 | + if (!fd2.ok()) { |
| 1578 | + PLOG(ERROR) << "memfd_create failed"; |
| 1579 | + return UNKNOWN_ERROR; |
| 1580 | + } |
| 1581 | + status_t ret; |
| 1582 | + ret = reply->writeFileDescriptor(fd1.release(), true); |
| 1583 | + if (ret != NO_ERROR) { |
| 1584 | + return ret; |
| 1585 | + } |
| 1586 | + ret = reply->writeFileDescriptor(fd2.release(), true); |
| 1587 | + if (ret != NO_ERROR) { |
| 1588 | + return ret; |
| 1589 | + } |
| 1590 | + return NO_ERROR; |
| 1591 | + } |
| 1592 | + case BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION: { |
| 1593 | + status_t ret; |
| 1594 | + ret = reply->writeFileDescriptor(STDOUT_FILENO, false); |
| 1595 | + if (ret != NO_ERROR) { |
| 1596 | + return ret; |
| 1597 | + } |
| 1598 | + ret = reply->writeFileDescriptor(STDERR_FILENO, false); |
| 1599 | + if (ret != NO_ERROR) { |
| 1600 | + return ret; |
| 1601 | + } |
| 1602 | + return NO_ERROR; |
| 1603 | + } |
1441 | 1604 | case BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION: |
1442 | 1605 | alarm(10); |
1443 | 1606 | return NO_ERROR; |
|
0 commit comments