diff options
author | 2024-12-13 23:14:50 +0000 | |
---|---|---|
committer | 2024-12-16 14:19:55 -0800 | |
commit | 750d69b248d1f7c90c8dbe6f1eee322cf0fc59e7 (patch) | |
tree | d508411e2b403911c76192df7570f48f1229754f /libs/binder/Parcel.cpp | |
parent | 575fdb3495cba6c3f5f47495b1b2c14f493256fe (diff) |
libbinder: remove overeager fdsan crash
In the continueWrite case, if a Parcel contians FDs,
we try to tag the FDs we own in Parcel a second time.
This causes a crash.
Bug: 384097481
Test: with fuzzer, on device and host
Ignore-AOSP-First: fuzzing
Change-Id: I01b2312c316fa457781a4a0c1a81bfd845d0e60e
Diffstat (limited to 'libs/binder/Parcel.cpp')
-rw-r--r-- | libs/binder/Parcel.cpp | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index d09d5a8c1d..e2eea6c458 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -156,7 +156,7 @@ enum { #ifdef BINDER_WITH_KERNEL_IPC static void acquire_object(const sp<ProcessState>& proc, const flat_binder_object& obj, - const void* who) { + const void* who, bool tagFds) { switch (obj.hdr.type) { case BINDER_TYPE_BINDER: if (obj.binder) { @@ -173,7 +173,7 @@ static void acquire_object(const sp<ProcessState>& proc, const flat_binder_objec return; } case BINDER_TYPE_FD: { - if (obj.cookie != 0) { // owned + if (tagFds && obj.cookie != 0) { // owned FdTag(obj.handle, nullptr, who); } return; @@ -611,7 +611,7 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) { } } - acquire_object(proc, *flat, this); + acquire_object(proc, *flat, this, true /*tagFds*/); } } #else @@ -1797,7 +1797,7 @@ restart_write: // Need to write meta-data? if (nullMetaData || val.binder != 0) { kernelFields->mObjects[kernelFields->mObjectsSize] = mDataPos; - acquire_object(ProcessState::self(), val, this); + acquire_object(ProcessState::self(), val, this, true /*tagFds*/); kernelFields->mObjectsSize++; } @@ -2883,15 +2883,17 @@ void Parcel::releaseObjects() #endif // BINDER_WITH_KERNEL_IPC } -void Parcel::acquireObjects() -{ +void Parcel::reacquireObjects(size_t objectsSize) { auto* kernelFields = maybeKernelFields(); if (kernelFields == nullptr) { return; } #ifdef BINDER_WITH_KERNEL_IPC - size_t i = kernelFields->mObjectsSize; + LOG_ALWAYS_FATAL_IF(objectsSize > kernelFields->mObjectsSize, + "Object size %zu out of range of %zu", objectsSize, + kernelFields->mObjectsSize); + size_t i = objectsSize; if (i == 0) { return; } @@ -2901,8 +2903,10 @@ void Parcel::acquireObjects() while (i > 0) { i--; const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(data + objects[i]); - acquire_object(proc, *flat, this); + acquire_object(proc, *flat, this, false /*tagFds*/); // they are already tagged } +#else + (void) objectsSize; #endif // BINDER_WITH_KERNEL_IPC } @@ -3119,12 +3123,8 @@ status_t Parcel::continueWrite(size_t desired) return NO_MEMORY; } - // Little hack to only acquire references on objects - // we will be keeping. - size_t oldObjectsSize = kernelFields->mObjectsSize; - kernelFields->mObjectsSize = objectsSize; - acquireObjects(); - kernelFields->mObjectsSize = oldObjectsSize; + // only acquire references on objects we are keeping + reacquireObjects(objectsSize); } if (rpcFields) { if (status_t status = truncateRpcObjects(objectsSize); status != OK) { |