diff options
author | 2022-07-15 20:14:01 +0000 | |
---|---|---|
committer | 2022-07-15 21:10:12 +0000 | |
commit | 53b6ffe5af3951e8784c451ef8c4ff19f3d6b196 (patch) | |
tree | 8ab28ff57d9c124871514dd5aca03ce39eebf022 | |
parent | ec602d42c63c9ace5c429db98bbf5974a76cac78 (diff) |
libbinder: Remove Parcel argument from Parcel::release_func
This enforces a clearer separation of concerns between the data owner
and the parcel code. It happened to reveal an edge case where FDs are
prematurely closed (tracking a fix in b/239222407).
Test: TH
Bug: 239222407
Change-Id: I54ff0c8e4a8f64afd529092d2038dac40c853371
-rw-r--r-- | libs/binder/IPCThreadState.cpp | 25 | ||||
-rw-r--r-- | libs/binder/Parcel.cpp | 13 | ||||
-rw-r--r-- | libs/binder/RpcState.cpp | 10 | ||||
-rw-r--r-- | libs/binder/include/binder/IPCThreadState.h | 5 | ||||
-rw-r--r-- | libs/binder/include/binder/Parcel.h | 6 |
5 files changed, 28 insertions, 31 deletions
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index d53621946a..b50cfb3d19 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -972,18 +972,15 @@ status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) freeBuffer); } else { err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer); - freeBuffer(nullptr, - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(binder_size_t)); + freeBuffer(reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), + tr.data_size, + reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), + tr.offsets_size / sizeof(binder_size_t)); } } else { - freeBuffer(nullptr, - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(binder_size_t)); + freeBuffer(reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, + reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), + tr.offsets_size / sizeof(binder_size_t)); continue; } } @@ -1473,17 +1470,13 @@ void IPCThreadState::logExtendedError() { ee.id, ee.command, ee.param); } -void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data, - size_t /*dataSize*/, - const binder_size_t* /*objects*/, - size_t /*objectsSize*/) -{ +void IPCThreadState::freeBuffer(const uint8_t* data, size_t /*dataSize*/, + const binder_size_t* /*objects*/, size_t /*objectsSize*/) { //ALOGI("Freeing parcel %p", &parcel); IF_LOG_COMMANDS() { alog << "Writing BC_FREE_BUFFER for " << data << endl; } ALOG_ASSERT(data != NULL, "Called with NULL data"); - if (parcel != nullptr) parcel->closeFileDescriptors(); IPCThreadState* state = self(); state->mOut.writeInt32(BC_FREE_BUFFER); state->mOut.writePointer((uintptr_t)data); diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 537527e2c1..72c1a1a820 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -2706,7 +2706,9 @@ void Parcel::freeDataNoInit() LOG_ALLOC("Parcel %p: freeing other owner data", this); //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid()); auto* kernelFields = maybeKernelFields(); - mOwner(this, mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr, + // Close FDs before freeing, otherwise they will leak for kernel binder. + closeFileDescriptors(); + mOwner(mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr, kernelFields ? kernelFields->mObjectsSize : 0); } else { LOG_ALLOC("Parcel %p: freeing allocated data", this); @@ -2891,8 +2893,13 @@ status_t Parcel::continueWrite(size_t desired) if (objects && kernelFields && kernelFields->mObjects) { memcpy(objects, kernelFields->mObjects, objectsSize * sizeof(binder_size_t)); } - //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid()); - mOwner(this, mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr, + // 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(); + } + mOwner(mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr, kernelFields ? kernelFields->mObjectsSize : 0); mOwner = nullptr; diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp index 633fea9b03..1c5654c597 100644 --- a/libs/binder/RpcState.cpp +++ b/libs/binder/RpcState.cpp @@ -586,13 +586,12 @@ status_t RpcState::transactAddress(const sp<RpcSession::RpcConnection>& connecti return waitForReply(connection, session, reply); } -static void cleanup_reply_data(Parcel* p, const uint8_t* data, size_t dataSize, - const binder_size_t* objects, size_t objectsCount) { - (void)p; +static void cleanup_reply_data(const uint8_t* data, size_t dataSize, const binder_size_t* objects, + size_t objectsCount) { delete[] const_cast<uint8_t*>(data); (void)dataSize; LOG_ALWAYS_FATAL_IF(objects != nullptr); - LOG_ALWAYS_FATAL_IF(objectsCount != 0, "%zu objects remaining", objectsCount); + (void)objectsCount; } status_t RpcState::waitForReply(const sp<RpcSession::RpcConnection>& connection, @@ -799,9 +798,8 @@ status_t RpcState::processTransact( std::move(ancillaryFds)); } -static void do_nothing_to_transact_data(Parcel* p, const uint8_t* data, size_t dataSize, +static void do_nothing_to_transact_data(const uint8_t* data, size_t dataSize, const binder_size_t* objects, size_t objectsCount) { - (void)p; (void)data; (void)dataSize; (void)objects; diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h index 8ce3bc9dc9..c01e92f043 100644 --- a/libs/binder/include/binder/IPCThreadState.h +++ b/libs/binder/include/binder/IPCThreadState.h @@ -217,9 +217,8 @@ private: void clearCaller(); static void threadDestructor(void *st); - static void freeBuffer(Parcel* parcel, - const uint8_t* data, size_t dataSize, - const binder_size_t* objects, size_t objectsSize); + static void freeBuffer(const uint8_t* data, size_t dataSize, const binder_size_t* objects, + size_t objectsSize); static void logExtendedError(); const sp<ProcessState> mProcess; diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index 91febbd7bb..54692398c6 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -598,9 +598,9 @@ public: void print(TextOutput& to, uint32_t flags = 0) const; private: - typedef void (*release_func)(Parcel* parcel, - const uint8_t* data, size_t dataSize, - const binder_size_t* objects, size_t objectsSize); + // `objects` and `objectsSize` always 0 for RPC Parcels. + typedef void (*release_func)(const uint8_t* data, size_t dataSize, const binder_size_t* objects, + size_t objectsSize); uintptr_t ipcData() const; size_t ipcDataSize() const; |