Loading libs/binder/Parcel.cpp +67 −11 Original line number Diff line number Diff line Loading @@ -1186,6 +1186,10 @@ restart_write: //printf("Writing %ld bytes, padded to %ld\n", len, padded); uint8_t* const data = mData+mDataPos; if (status_t status = validateReadData(mDataPos + padded); status != OK) { return nullptr; // drops status } // Need to pad at end? if (padded != len) { #if BYTE_ORDER == BIG_ENDIAN Loading Loading @@ -1774,6 +1778,10 @@ status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData) const bool enoughObjects = kernelFields->mObjectsSize < kernelFields->mObjectsCapacity; if (enoughData && enoughObjects) { restart_write: if (status_t status = validateReadData(mDataPos + sizeof(val)); status != OK) { return status; } *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val; // remember if it's a file descriptor Loading Loading @@ -2020,6 +2028,10 @@ status_t Parcel::writeAligned(T val) { if ((mDataPos+sizeof(val)) <= mDataCapacity) { restart_write: if (status_t status = validateReadData(mDataPos + sizeof(val)); status != OK) { return status; } memcpy(mData + mDataPos, &val, sizeof(val)); return finishWrite(sizeof(val)); } Loading Loading @@ -2656,14 +2668,14 @@ const flat_binder_object* Parcel::readObject(bool nullMetaData) const } #endif // BINDER_WITH_KERNEL_IPC void Parcel::closeFileDescriptors() { void Parcel::closeFileDescriptors(size_t newObjectsSize) { if (auto* kernelFields = maybeKernelFields()) { #ifdef BINDER_WITH_KERNEL_IPC size_t i = kernelFields->mObjectsSize; if (i > 0) { // ALOGI("Closing file descriptors for %zu objects...", i); } while (i > 0) { while (i > newObjectsSize) { i--; const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(mData + kernelFields->mObjects[i]); Loading @@ -2674,6 +2686,7 @@ void Parcel::closeFileDescriptors() { } } #else // BINDER_WITH_KERNEL_IPC (void)newObjectsSize; LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time"); #endif // BINDER_WITH_KERNEL_IPC } else if (auto* rpcFields = maybeRpcFields()) { Loading Loading @@ -2898,7 +2911,7 @@ void Parcel::freeDataNoInit() //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid()); auto* kernelFields = maybeKernelFields(); // Close FDs before freeing, otherwise they will leak for kernel binder. closeFileDescriptors(); closeFileDescriptors(/*newObjectsSize=*/0); mOwner(mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr, kernelFields ? kernelFields->mObjectsSize : 0); } else { Loading Loading @@ -3035,13 +3048,38 @@ status_t Parcel::continueWrite(size_t desired) objectsSize = 0; } else { if (kernelFields) { #ifdef BINDER_WITH_KERNEL_IPC validateReadData(mDataSize); // hack to sort the objects while (objectsSize > 0) { if (kernelFields->mObjects[objectsSize - 1] < desired) break; if (kernelFields->mObjects[objectsSize - 1] + sizeof(flat_binder_object) <= desired) break; objectsSize--; } #endif // BINDER_WITH_KERNEL_IPC } else { while (objectsSize > 0) { if (rpcFields->mObjectPositions[objectsSize - 1] < desired) break; // Object size varies by type. uint32_t pos = rpcFields->mObjectPositions[objectsSize - 1]; size_t size = sizeof(RpcFields::ObjectType); uint32_t minObjectEnd; if (__builtin_add_overflow(pos, sizeof(RpcFields::ObjectType), &minObjectEnd) || minObjectEnd > mDataSize) { return BAD_VALUE; } const auto type = *reinterpret_cast<const RpcFields::ObjectType*>(mData + pos); switch (type) { case RpcFields::TYPE_BINDER_NULL: break; case RpcFields::TYPE_BINDER: size += sizeof(uint64_t); // address break; case RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR: size += sizeof(int32_t); // fd index break; } if (pos + size <= desired) break; objectsSize--; } } Loading Loading @@ -3090,15 +3128,24 @@ status_t Parcel::continueWrite(size_t desired) if (mData) { memcpy(data, mData, mDataSize < desired ? mDataSize : desired); } #ifdef BINDER_WITH_KERNEL_IPC if (objects && kernelFields && kernelFields->mObjects) { memcpy(objects, kernelFields->mObjects, objectsSize * sizeof(binder_size_t)); // All FDs are owned when `mOwner`, even when `cookie == 0`. When // we switch to `!mOwner`, we need to explicitly mark the FDs as // owned. for (size_t i = 0; i < objectsSize; i++) { flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(data + objects[i]); if (flat->hdr.type == BINDER_TYPE_FD) { flat->cookie = 1; } } } // ALOGI("Freeing data ref of %p (pid=%d)", this, getpid()); if (kernelFields) { // TODO(b/239222407): This seems wrong. We should only free FDs when // they are in a truncated section of the parcel. closeFileDescriptors(); closeFileDescriptors(objectsSize); } #endif // BINDER_WITH_KERNEL_IPC mOwner(mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr, kernelFields ? kernelFields->mObjectsSize : 0); mOwner = nullptr; Loading Loading @@ -3225,11 +3272,19 @@ status_t Parcel::truncateRpcObjects(size_t newObjectsSize) { } while (rpcFields->mObjectPositions.size() > newObjectsSize) { uint32_t pos = rpcFields->mObjectPositions.back(); rpcFields->mObjectPositions.pop_back(); uint32_t minObjectEnd; if (__builtin_add_overflow(pos, sizeof(RpcFields::ObjectType), &minObjectEnd) || minObjectEnd > mDataSize) { return BAD_VALUE; } const auto type = *reinterpret_cast<const RpcFields::ObjectType*>(mData + pos); if (type == RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR) { const auto fdIndex = *reinterpret_cast<const int32_t*>(mData + pos + sizeof(RpcFields::ObjectType)); uint32_t objectEnd; if (__builtin_add_overflow(minObjectEnd, sizeof(int32_t), &objectEnd) || objectEnd > mDataSize) { return BAD_VALUE; } const auto fdIndex = *reinterpret_cast<const int32_t*>(mData + minObjectEnd); if (rpcFields->mFds == nullptr || fdIndex < 0 || static_cast<size_t>(fdIndex) >= rpcFields->mFds->size()) { ALOGE("RPC Parcel contains invalid file descriptor index. index=%d fd_count=%zu", Loading @@ -3239,6 +3294,7 @@ status_t Parcel::truncateRpcObjects(size_t newObjectsSize) { // In practice, this always removes the last element. rpcFields->mFds->erase(rpcFields->mFds->begin() + fdIndex); } rpcFields->mObjectPositions.pop_back(); } return OK; } Loading libs/binder/include/binder/Parcel.h +3 −3 Original line number Diff line number Diff line Loading @@ -648,8 +648,8 @@ public: LIBBINDER_EXPORTED void print(std::ostream& to, uint32_t flags = 0) const; private: // Explicitly close all file descriptors in the parcel. void closeFileDescriptors(); // Close all file descriptors in the parcel at object positions >= newObjectsSize. void closeFileDescriptors(size_t newObjectsSize); // `objects` and `objectsSize` always 0 for RPC Parcels. typedef void (*release_func)(const uint8_t* data, size_t dataSize, const binder_size_t* objects, Loading Loading @@ -1239,7 +1239,7 @@ private: if (__builtin_mul_overflow(size, sizeof(T), &dataLen)) { return -EOVERFLOW; } auto data = reinterpret_cast<const T*>(readInplace(dataLen)); auto data = readInplace(dataLen); if (data == nullptr) return BAD_VALUE; // std::vector::insert and similar methods will require type-dependent // byte alignment when inserting from a const iterator such as `data`, Loading libs/binder/tests/binderLibTest.cpp +155 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ #include <linux/sched.h> #include <sys/epoll.h> #include <sys/mman.h> #include <sys/prctl.h> #include <sys/socket.h> #include <sys/un.h> Loading Loading @@ -110,6 +111,8 @@ enum BinderLibTestTranscationCode { BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, BINDER_LIB_TEST_WRITE_PARCEL_FILE_DESCRIPTOR_TRANSACTION, BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, BINDER_LIB_TEST_EXIT_TRANSACTION, BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION, BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, Loading Loading @@ -536,6 +539,30 @@ class TestDeathRecipient : public IBinder::DeathRecipient, public BinderLibTestE }; }; ssize_t countFds() { return std::distance(std::filesystem::directory_iterator("/proc/self/fd"), std::filesystem::directory_iterator{}); } struct FdLeakDetector { int startCount; FdLeakDetector() { // This log statement is load bearing. We have to log something before // counting FDs to make sure the logging system is initialized, otherwise // the sockets it opens will look like a leak. ALOGW("FdLeakDetector counting FDs."); startCount = countFds(); } ~FdLeakDetector() { int endCount = countFds(); if (startCount != endCount) { ADD_FAILURE() << "fd count changed (" << startCount << " -> " << endCount << ") fd leak?"; } } }; TEST_F(BinderLibTest, CannotUseBinderAfterFork) { // EXPECT_DEATH works by forking the process EXPECT_DEATH({ ProcessState::self(); }, "libbinder ProcessState can not be used after fork"); Loading Loading @@ -1175,6 +1202,100 @@ TEST_F(BinderLibTest, PassParcelFileDescriptor) { EXPECT_EQ(0, read(read_end.get(), readbuf.data(), datasize)); } TEST_F(BinderLibTest, RecvOwnedFileDescriptors) { FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, &reply)); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); } // Used to trigger fdsan error (b/239222407). TEST_F(BinderLibTest, RecvOwnedFileDescriptorsAndWriteInt) { GTEST_SKIP() << "triggers fdsan false positive: b/370824489"; FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, &reply)); reply.setDataPosition(reply.dataSize()); reply.writeInt32(0); reply.setDataPosition(0); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); } // Used to trigger fdsan error (b/239222407). TEST_F(BinderLibTest, RecvOwnedFileDescriptorsAndTruncate) { GTEST_SKIP() << "triggers fdsan false positive: b/370824489"; FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, &reply)); reply.setDataSize(reply.dataSize() - sizeof(flat_binder_object)); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(BAD_TYPE, reply.readUniqueFileDescriptor(&b)); } TEST_F(BinderLibTest, RecvUnownedFileDescriptors) { FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, &reply)); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); } // Used to trigger fdsan error (b/239222407). TEST_F(BinderLibTest, RecvUnownedFileDescriptorsAndWriteInt) { FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, &reply)); reply.setDataPosition(reply.dataSize()); reply.writeInt32(0); reply.setDataPosition(0); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); } // Used to trigger fdsan error (b/239222407). TEST_F(BinderLibTest, RecvUnownedFileDescriptorsAndTruncate) { FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, &reply)); reply.setDataSize(reply.dataSize() - sizeof(flat_binder_object)); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(BAD_TYPE, reply.readUniqueFileDescriptor(&b)); } TEST_F(BinderLibTest, PromoteLocal) { sp<IBinder> strong = new BBinder(); wp<IBinder> weak = strong; Loading Loading @@ -2224,6 +2345,40 @@ public: if (ret != size) return UNKNOWN_ERROR; return NO_ERROR; } case BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION: { unique_fd fd1(memfd_create("memfd1", MFD_CLOEXEC)); if (!fd1.ok()) { PLOGE("memfd_create failed"); return UNKNOWN_ERROR; } unique_fd fd2(memfd_create("memfd2", MFD_CLOEXEC)); if (!fd2.ok()) { PLOGE("memfd_create failed"); return UNKNOWN_ERROR; } status_t ret; ret = reply->writeFileDescriptor(fd1.release(), true); if (ret != NO_ERROR) { return ret; } ret = reply->writeFileDescriptor(fd2.release(), true); if (ret != NO_ERROR) { return ret; } return NO_ERROR; } case BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION: { status_t ret; ret = reply->writeFileDescriptor(STDOUT_FILENO, false); if (ret != NO_ERROR) { return ret; } ret = reply->writeFileDescriptor(STDERR_FILENO, false); if (ret != NO_ERROR) { return ret; } return NO_ERROR; } case BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION: alarm(10); return NO_ERROR; Loading services/inputflinger/dispatcher/DragState.h +6 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #pragma once #include <gui/WindowInfo.h> #include <input/Input.h> #include <utils/StrongPointer.h> #include <string> Loading @@ -25,8 +26,9 @@ namespace android { namespace inputdispatcher { struct DragState { DragState(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t pointerId) : dragWindow(windowHandle), pointerId(pointerId) {} DragState(const sp<android::gui::WindowInfoHandle>& windowHandle, DeviceId deviceId, int32_t pointerId) : dragWindow(windowHandle), deviceId(deviceId), pointerId(pointerId) {} void dump(std::string& dump, const char* prefix = ""); // The window being dragged. Loading @@ -37,6 +39,8 @@ struct DragState { bool isStartDrag = false; // Indicate if the stylus button is down at the start of the drag. bool isStylusButtonDownAtStart = false; // Indicate which device started this drag and drop. const DeviceId deviceId; // Indicate which pointer id is tracked by the drag and drop. const int32_t pointerId; }; Loading services/inputflinger/dispatcher/InputDispatcher.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -2895,7 +2895,8 @@ void InputDispatcher::finishDragAndDrop(ui::LogicalDisplayId displayId, float x, } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId || mDragState->deviceId != entry.deviceId) { return; } Loading Loading @@ -5820,7 +5821,7 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s } // Track the pointer id for drag window and generate the drag state. const size_t id = pointers.begin()->id; mDragState = std::make_unique<DragState>(toWindowHandle, id); mDragState = std::make_unique<DragState>(toWindowHandle, deviceId, id); } // Synthesize cancel for old window and down for new window. Loading Loading
libs/binder/Parcel.cpp +67 −11 Original line number Diff line number Diff line Loading @@ -1186,6 +1186,10 @@ restart_write: //printf("Writing %ld bytes, padded to %ld\n", len, padded); uint8_t* const data = mData+mDataPos; if (status_t status = validateReadData(mDataPos + padded); status != OK) { return nullptr; // drops status } // Need to pad at end? if (padded != len) { #if BYTE_ORDER == BIG_ENDIAN Loading Loading @@ -1774,6 +1778,10 @@ status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData) const bool enoughObjects = kernelFields->mObjectsSize < kernelFields->mObjectsCapacity; if (enoughData && enoughObjects) { restart_write: if (status_t status = validateReadData(mDataPos + sizeof(val)); status != OK) { return status; } *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val; // remember if it's a file descriptor Loading Loading @@ -2020,6 +2028,10 @@ status_t Parcel::writeAligned(T val) { if ((mDataPos+sizeof(val)) <= mDataCapacity) { restart_write: if (status_t status = validateReadData(mDataPos + sizeof(val)); status != OK) { return status; } memcpy(mData + mDataPos, &val, sizeof(val)); return finishWrite(sizeof(val)); } Loading Loading @@ -2656,14 +2668,14 @@ const flat_binder_object* Parcel::readObject(bool nullMetaData) const } #endif // BINDER_WITH_KERNEL_IPC void Parcel::closeFileDescriptors() { void Parcel::closeFileDescriptors(size_t newObjectsSize) { if (auto* kernelFields = maybeKernelFields()) { #ifdef BINDER_WITH_KERNEL_IPC size_t i = kernelFields->mObjectsSize; if (i > 0) { // ALOGI("Closing file descriptors for %zu objects...", i); } while (i > 0) { while (i > newObjectsSize) { i--; const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(mData + kernelFields->mObjects[i]); Loading @@ -2674,6 +2686,7 @@ void Parcel::closeFileDescriptors() { } } #else // BINDER_WITH_KERNEL_IPC (void)newObjectsSize; LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time"); #endif // BINDER_WITH_KERNEL_IPC } else if (auto* rpcFields = maybeRpcFields()) { Loading Loading @@ -2898,7 +2911,7 @@ void Parcel::freeDataNoInit() //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid()); auto* kernelFields = maybeKernelFields(); // Close FDs before freeing, otherwise they will leak for kernel binder. closeFileDescriptors(); closeFileDescriptors(/*newObjectsSize=*/0); mOwner(mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr, kernelFields ? kernelFields->mObjectsSize : 0); } else { Loading Loading @@ -3035,13 +3048,38 @@ status_t Parcel::continueWrite(size_t desired) objectsSize = 0; } else { if (kernelFields) { #ifdef BINDER_WITH_KERNEL_IPC validateReadData(mDataSize); // hack to sort the objects while (objectsSize > 0) { if (kernelFields->mObjects[objectsSize - 1] < desired) break; if (kernelFields->mObjects[objectsSize - 1] + sizeof(flat_binder_object) <= desired) break; objectsSize--; } #endif // BINDER_WITH_KERNEL_IPC } else { while (objectsSize > 0) { if (rpcFields->mObjectPositions[objectsSize - 1] < desired) break; // Object size varies by type. uint32_t pos = rpcFields->mObjectPositions[objectsSize - 1]; size_t size = sizeof(RpcFields::ObjectType); uint32_t minObjectEnd; if (__builtin_add_overflow(pos, sizeof(RpcFields::ObjectType), &minObjectEnd) || minObjectEnd > mDataSize) { return BAD_VALUE; } const auto type = *reinterpret_cast<const RpcFields::ObjectType*>(mData + pos); switch (type) { case RpcFields::TYPE_BINDER_NULL: break; case RpcFields::TYPE_BINDER: size += sizeof(uint64_t); // address break; case RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR: size += sizeof(int32_t); // fd index break; } if (pos + size <= desired) break; objectsSize--; } } Loading Loading @@ -3090,15 +3128,24 @@ status_t Parcel::continueWrite(size_t desired) if (mData) { memcpy(data, mData, mDataSize < desired ? mDataSize : desired); } #ifdef BINDER_WITH_KERNEL_IPC if (objects && kernelFields && kernelFields->mObjects) { memcpy(objects, kernelFields->mObjects, objectsSize * sizeof(binder_size_t)); // All FDs are owned when `mOwner`, even when `cookie == 0`. When // we switch to `!mOwner`, we need to explicitly mark the FDs as // owned. for (size_t i = 0; i < objectsSize; i++) { flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(data + objects[i]); if (flat->hdr.type == BINDER_TYPE_FD) { flat->cookie = 1; } } } // ALOGI("Freeing data ref of %p (pid=%d)", this, getpid()); if (kernelFields) { // TODO(b/239222407): This seems wrong. We should only free FDs when // they are in a truncated section of the parcel. closeFileDescriptors(); closeFileDescriptors(objectsSize); } #endif // BINDER_WITH_KERNEL_IPC mOwner(mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr, kernelFields ? kernelFields->mObjectsSize : 0); mOwner = nullptr; Loading Loading @@ -3225,11 +3272,19 @@ status_t Parcel::truncateRpcObjects(size_t newObjectsSize) { } while (rpcFields->mObjectPositions.size() > newObjectsSize) { uint32_t pos = rpcFields->mObjectPositions.back(); rpcFields->mObjectPositions.pop_back(); uint32_t minObjectEnd; if (__builtin_add_overflow(pos, sizeof(RpcFields::ObjectType), &minObjectEnd) || minObjectEnd > mDataSize) { return BAD_VALUE; } const auto type = *reinterpret_cast<const RpcFields::ObjectType*>(mData + pos); if (type == RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR) { const auto fdIndex = *reinterpret_cast<const int32_t*>(mData + pos + sizeof(RpcFields::ObjectType)); uint32_t objectEnd; if (__builtin_add_overflow(minObjectEnd, sizeof(int32_t), &objectEnd) || objectEnd > mDataSize) { return BAD_VALUE; } const auto fdIndex = *reinterpret_cast<const int32_t*>(mData + minObjectEnd); if (rpcFields->mFds == nullptr || fdIndex < 0 || static_cast<size_t>(fdIndex) >= rpcFields->mFds->size()) { ALOGE("RPC Parcel contains invalid file descriptor index. index=%d fd_count=%zu", Loading @@ -3239,6 +3294,7 @@ status_t Parcel::truncateRpcObjects(size_t newObjectsSize) { // In practice, this always removes the last element. rpcFields->mFds->erase(rpcFields->mFds->begin() + fdIndex); } rpcFields->mObjectPositions.pop_back(); } return OK; } Loading
libs/binder/include/binder/Parcel.h +3 −3 Original line number Diff line number Diff line Loading @@ -648,8 +648,8 @@ public: LIBBINDER_EXPORTED void print(std::ostream& to, uint32_t flags = 0) const; private: // Explicitly close all file descriptors in the parcel. void closeFileDescriptors(); // Close all file descriptors in the parcel at object positions >= newObjectsSize. void closeFileDescriptors(size_t newObjectsSize); // `objects` and `objectsSize` always 0 for RPC Parcels. typedef void (*release_func)(const uint8_t* data, size_t dataSize, const binder_size_t* objects, Loading Loading @@ -1239,7 +1239,7 @@ private: if (__builtin_mul_overflow(size, sizeof(T), &dataLen)) { return -EOVERFLOW; } auto data = reinterpret_cast<const T*>(readInplace(dataLen)); auto data = readInplace(dataLen); if (data == nullptr) return BAD_VALUE; // std::vector::insert and similar methods will require type-dependent // byte alignment when inserting from a const iterator such as `data`, Loading
libs/binder/tests/binderLibTest.cpp +155 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ #include <linux/sched.h> #include <sys/epoll.h> #include <sys/mman.h> #include <sys/prctl.h> #include <sys/socket.h> #include <sys/un.h> Loading Loading @@ -110,6 +111,8 @@ enum BinderLibTestTranscationCode { BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, BINDER_LIB_TEST_WRITE_PARCEL_FILE_DESCRIPTOR_TRANSACTION, BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, BINDER_LIB_TEST_EXIT_TRANSACTION, BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION, BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, Loading Loading @@ -536,6 +539,30 @@ class TestDeathRecipient : public IBinder::DeathRecipient, public BinderLibTestE }; }; ssize_t countFds() { return std::distance(std::filesystem::directory_iterator("/proc/self/fd"), std::filesystem::directory_iterator{}); } struct FdLeakDetector { int startCount; FdLeakDetector() { // This log statement is load bearing. We have to log something before // counting FDs to make sure the logging system is initialized, otherwise // the sockets it opens will look like a leak. ALOGW("FdLeakDetector counting FDs."); startCount = countFds(); } ~FdLeakDetector() { int endCount = countFds(); if (startCount != endCount) { ADD_FAILURE() << "fd count changed (" << startCount << " -> " << endCount << ") fd leak?"; } } }; TEST_F(BinderLibTest, CannotUseBinderAfterFork) { // EXPECT_DEATH works by forking the process EXPECT_DEATH({ ProcessState::self(); }, "libbinder ProcessState can not be used after fork"); Loading Loading @@ -1175,6 +1202,100 @@ TEST_F(BinderLibTest, PassParcelFileDescriptor) { EXPECT_EQ(0, read(read_end.get(), readbuf.data(), datasize)); } TEST_F(BinderLibTest, RecvOwnedFileDescriptors) { FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, &reply)); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); } // Used to trigger fdsan error (b/239222407). TEST_F(BinderLibTest, RecvOwnedFileDescriptorsAndWriteInt) { GTEST_SKIP() << "triggers fdsan false positive: b/370824489"; FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, &reply)); reply.setDataPosition(reply.dataSize()); reply.writeInt32(0); reply.setDataPosition(0); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); } // Used to trigger fdsan error (b/239222407). TEST_F(BinderLibTest, RecvOwnedFileDescriptorsAndTruncate) { GTEST_SKIP() << "triggers fdsan false positive: b/370824489"; FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION, data, &reply)); reply.setDataSize(reply.dataSize() - sizeof(flat_binder_object)); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(BAD_TYPE, reply.readUniqueFileDescriptor(&b)); } TEST_F(BinderLibTest, RecvUnownedFileDescriptors) { FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, &reply)); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); } // Used to trigger fdsan error (b/239222407). TEST_F(BinderLibTest, RecvUnownedFileDescriptorsAndWriteInt) { FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, &reply)); reply.setDataPosition(reply.dataSize()); reply.writeInt32(0); reply.setDataPosition(0); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&b)); } // Used to trigger fdsan error (b/239222407). TEST_F(BinderLibTest, RecvUnownedFileDescriptorsAndTruncate) { FdLeakDetector fd_leak_detector; Parcel data; Parcel reply; EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION, data, &reply)); reply.setDataSize(reply.dataSize() - sizeof(flat_binder_object)); unique_fd a, b; EXPECT_EQ(OK, reply.readUniqueFileDescriptor(&a)); EXPECT_EQ(BAD_TYPE, reply.readUniqueFileDescriptor(&b)); } TEST_F(BinderLibTest, PromoteLocal) { sp<IBinder> strong = new BBinder(); wp<IBinder> weak = strong; Loading Loading @@ -2224,6 +2345,40 @@ public: if (ret != size) return UNKNOWN_ERROR; return NO_ERROR; } case BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_OWNED_TRANSACTION: { unique_fd fd1(memfd_create("memfd1", MFD_CLOEXEC)); if (!fd1.ok()) { PLOGE("memfd_create failed"); return UNKNOWN_ERROR; } unique_fd fd2(memfd_create("memfd2", MFD_CLOEXEC)); if (!fd2.ok()) { PLOGE("memfd_create failed"); return UNKNOWN_ERROR; } status_t ret; ret = reply->writeFileDescriptor(fd1.release(), true); if (ret != NO_ERROR) { return ret; } ret = reply->writeFileDescriptor(fd2.release(), true); if (ret != NO_ERROR) { return ret; } return NO_ERROR; } case BINDER_LIB_TEST_GET_FILE_DESCRIPTORS_UNOWNED_TRANSACTION: { status_t ret; ret = reply->writeFileDescriptor(STDOUT_FILENO, false); if (ret != NO_ERROR) { return ret; } ret = reply->writeFileDescriptor(STDERR_FILENO, false); if (ret != NO_ERROR) { return ret; } return NO_ERROR; } case BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION: alarm(10); return NO_ERROR; Loading
services/inputflinger/dispatcher/DragState.h +6 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #pragma once #include <gui/WindowInfo.h> #include <input/Input.h> #include <utils/StrongPointer.h> #include <string> Loading @@ -25,8 +26,9 @@ namespace android { namespace inputdispatcher { struct DragState { DragState(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t pointerId) : dragWindow(windowHandle), pointerId(pointerId) {} DragState(const sp<android::gui::WindowInfoHandle>& windowHandle, DeviceId deviceId, int32_t pointerId) : dragWindow(windowHandle), deviceId(deviceId), pointerId(pointerId) {} void dump(std::string& dump, const char* prefix = ""); // The window being dragged. Loading @@ -37,6 +39,8 @@ struct DragState { bool isStartDrag = false; // Indicate if the stylus button is down at the start of the drag. bool isStylusButtonDownAtStart = false; // Indicate which device started this drag and drop. const DeviceId deviceId; // Indicate which pointer id is tracked by the drag and drop. const int32_t pointerId; }; Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -2895,7 +2895,8 @@ void InputDispatcher::finishDragAndDrop(ui::LogicalDisplayId displayId, float x, } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId || mDragState->deviceId != entry.deviceId) { return; } Loading Loading @@ -5820,7 +5821,7 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s } // Track the pointer id for drag window and generate the drag state. const size_t id = pointers.begin()->id; mDragState = std::make_unique<DragState>(toWindowHandle, id); mDragState = std::make_unique<DragState>(toWindowHandle, deviceId, id); } // Synthesize cancel for old window and down for new window. Loading