Loading libs/binder/Parcel.cpp +41 −0 Original line number Diff line number Diff line Loading @@ -569,6 +569,47 @@ bool Parcel::hasFileDescriptors() const return mHasFds; } std::vector<sp<IBinder>> Parcel::debugReadAllStrongBinders() const { std::vector<sp<IBinder>> ret; size_t initPosition = dataPosition(); for (size_t i = 0; i < mObjectsSize; i++) { binder_size_t offset = mObjects[i]; const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + offset); if (flat->hdr.type != BINDER_TYPE_BINDER) continue; setDataPosition(offset); sp<IBinder> binder = readStrongBinder(); if (binder != nullptr) ret.push_back(binder); } setDataPosition(initPosition); return ret; } std::vector<int> Parcel::debugReadAllFileDescriptors() const { std::vector<int> ret; size_t initPosition = dataPosition(); for (size_t i = 0; i < mObjectsSize; i++) { binder_size_t offset = mObjects[i]; const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + offset); if (flat->hdr.type != BINDER_TYPE_FD) continue; setDataPosition(offset); int fd = readFileDescriptor(); LOG_ALWAYS_FATAL_IF(fd == -1); ret.push_back(fd); } setDataPosition(initPosition); return ret; } status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool* result) const { if (len > INT32_MAX || offset > INT32_MAX) { // Don't accept size_t values which may have come from an inadvertent conversion from a Loading libs/binder/include/binder/Parcel.h +6 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,12 @@ public: bool hasFileDescriptors() const; status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool* result) const; // returns all binder objects in the Parcel std::vector<sp<IBinder>> debugReadAllStrongBinders() const; // returns all file descriptors in the Parcel // does not dup std::vector<int> debugReadAllFileDescriptors() const; // Zeros data when reallocating. Other mitigations may be added // in the future. // Loading libs/binder/include/binder/ParcelableHolder.h +2 −2 Original line number Diff line number Diff line Loading @@ -86,7 +86,7 @@ public: *ret = nullptr; return android::BAD_VALUE; } *ret = std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get())); *ret = std::static_pointer_cast<T>(mParcelable); return android::OK; } this->mParcelPtr->setDataPosition(0); Loading @@ -105,7 +105,7 @@ public: return status; } this->mParcelPtr = nullptr; *ret = std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get())); *ret = std::static_pointer_cast<T>(mParcelable); return android::OK; } Loading libs/binder/tests/binderParcelUnitTest.cpp +37 −0 Original line number Diff line number Diff line Loading @@ -20,9 +20,12 @@ #include <cutils/ashmem.h> #include <gtest/gtest.h> using android::BBinder; using android::IBinder; using android::IPCThreadState; using android::OK; using android::Parcel; using android::sp; using android::status_t; using android::String16; using android::String8; Loading Loading @@ -75,6 +78,40 @@ TEST(Parcel, EnforceNoDataAvail) { EXPECT_EQ(p.enforceNoDataAvail().exceptionCode(), Status::Exception::EX_NONE); } TEST(Parcel, DebugReadAllBinders) { sp<IBinder> binder1 = sp<BBinder>::make(); sp<IBinder> binder2 = sp<BBinder>::make(); Parcel p; p.writeInt32(4); p.writeStrongBinder(binder1); p.writeStrongBinder(nullptr); p.writeInt32(4); p.writeStrongBinder(binder2); p.writeInt32(4); auto ret = p.debugReadAllStrongBinders(); ASSERT_EQ(ret.size(), 2); EXPECT_EQ(ret[0], binder1); EXPECT_EQ(ret[1], binder2); } TEST(Parcel, DebugReadAllFds) { Parcel p; p.writeInt32(4); p.writeFileDescriptor(STDOUT_FILENO, false /*takeOwnership*/); p.writeInt32(4); p.writeFileDescriptor(STDIN_FILENO, false /*takeOwnership*/); p.writeInt32(4); auto ret = p.debugReadAllFileDescriptors(); ASSERT_EQ(ret.size(), 2); EXPECT_EQ(ret[0], STDOUT_FILENO); EXPECT_EQ(ret[1], STDIN_FILENO); } // Tests a second operation results in a parcel at the same location as it // started. void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) { Loading libs/binder/tests/parcel_fuzzer/binder.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,8 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { }, PARCEL_READ_NO_STATUS(size_t, allowFds), PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors), PARCEL_READ_NO_STATUS(std::vector<android::sp<android::IBinder>>, debugReadAllStrongBinders), PARCEL_READ_NO_STATUS(std::vector<int>, debugReadAllFileDescriptors), [] (const ::android::Parcel& p, uint8_t len) { std::string interface(len, 'a'); FUZZ_LOG() << "about to enforceInterface: " << interface; Loading Loading
libs/binder/Parcel.cpp +41 −0 Original line number Diff line number Diff line Loading @@ -569,6 +569,47 @@ bool Parcel::hasFileDescriptors() const return mHasFds; } std::vector<sp<IBinder>> Parcel::debugReadAllStrongBinders() const { std::vector<sp<IBinder>> ret; size_t initPosition = dataPosition(); for (size_t i = 0; i < mObjectsSize; i++) { binder_size_t offset = mObjects[i]; const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + offset); if (flat->hdr.type != BINDER_TYPE_BINDER) continue; setDataPosition(offset); sp<IBinder> binder = readStrongBinder(); if (binder != nullptr) ret.push_back(binder); } setDataPosition(initPosition); return ret; } std::vector<int> Parcel::debugReadAllFileDescriptors() const { std::vector<int> ret; size_t initPosition = dataPosition(); for (size_t i = 0; i < mObjectsSize; i++) { binder_size_t offset = mObjects[i]; const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + offset); if (flat->hdr.type != BINDER_TYPE_FD) continue; setDataPosition(offset); int fd = readFileDescriptor(); LOG_ALWAYS_FATAL_IF(fd == -1); ret.push_back(fd); } setDataPosition(initPosition); return ret; } status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool* result) const { if (len > INT32_MAX || offset > INT32_MAX) { // Don't accept size_t values which may have come from an inadvertent conversion from a Loading
libs/binder/include/binder/Parcel.h +6 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,12 @@ public: bool hasFileDescriptors() const; status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool* result) const; // returns all binder objects in the Parcel std::vector<sp<IBinder>> debugReadAllStrongBinders() const; // returns all file descriptors in the Parcel // does not dup std::vector<int> debugReadAllFileDescriptors() const; // Zeros data when reallocating. Other mitigations may be added // in the future. // Loading
libs/binder/include/binder/ParcelableHolder.h +2 −2 Original line number Diff line number Diff line Loading @@ -86,7 +86,7 @@ public: *ret = nullptr; return android::BAD_VALUE; } *ret = std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get())); *ret = std::static_pointer_cast<T>(mParcelable); return android::OK; } this->mParcelPtr->setDataPosition(0); Loading @@ -105,7 +105,7 @@ public: return status; } this->mParcelPtr = nullptr; *ret = std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get())); *ret = std::static_pointer_cast<T>(mParcelable); return android::OK; } Loading
libs/binder/tests/binderParcelUnitTest.cpp +37 −0 Original line number Diff line number Diff line Loading @@ -20,9 +20,12 @@ #include <cutils/ashmem.h> #include <gtest/gtest.h> using android::BBinder; using android::IBinder; using android::IPCThreadState; using android::OK; using android::Parcel; using android::sp; using android::status_t; using android::String16; using android::String8; Loading Loading @@ -75,6 +78,40 @@ TEST(Parcel, EnforceNoDataAvail) { EXPECT_EQ(p.enforceNoDataAvail().exceptionCode(), Status::Exception::EX_NONE); } TEST(Parcel, DebugReadAllBinders) { sp<IBinder> binder1 = sp<BBinder>::make(); sp<IBinder> binder2 = sp<BBinder>::make(); Parcel p; p.writeInt32(4); p.writeStrongBinder(binder1); p.writeStrongBinder(nullptr); p.writeInt32(4); p.writeStrongBinder(binder2); p.writeInt32(4); auto ret = p.debugReadAllStrongBinders(); ASSERT_EQ(ret.size(), 2); EXPECT_EQ(ret[0], binder1); EXPECT_EQ(ret[1], binder2); } TEST(Parcel, DebugReadAllFds) { Parcel p; p.writeInt32(4); p.writeFileDescriptor(STDOUT_FILENO, false /*takeOwnership*/); p.writeInt32(4); p.writeFileDescriptor(STDIN_FILENO, false /*takeOwnership*/); p.writeInt32(4); auto ret = p.debugReadAllFileDescriptors(); ASSERT_EQ(ret.size(), 2); EXPECT_EQ(ret[0], STDOUT_FILENO); EXPECT_EQ(ret[1], STDIN_FILENO); } // Tests a second operation results in a parcel at the same location as it // started. void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) { Loading
libs/binder/tests/parcel_fuzzer/binder.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,8 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { }, PARCEL_READ_NO_STATUS(size_t, allowFds), PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors), PARCEL_READ_NO_STATUS(std::vector<android::sp<android::IBinder>>, debugReadAllStrongBinders), PARCEL_READ_NO_STATUS(std::vector<int>, debugReadAllFileDescriptors), [] (const ::android::Parcel& p, uint8_t len) { std::string interface(len, 'a'); FUZZ_LOG() << "about to enforceInterface: " << interface; Loading