Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca1002f4 authored by Christopher Tate's avatar Christopher Tate Committed by The Android Automerger
Browse files

Close race condition in binderDied()

It was possible for a binderDied() call to occur while the death
recipient list containing the object was being iterated, in which
case we could invalidate an object reference out from under the
iteration, causing a VM abort.  We now interlock the binderDied()
deref operation with the list's locking semantics to prevent this.

Bug 15831054

Change-Id: If0027d3ac4da1153284a425dd9b2819a203481ab
parent 48b1bd2d
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -358,6 +358,8 @@ public:
    void add(const sp<JavaDeathRecipient>& recipient);
    void remove(const sp<JavaDeathRecipient>& recipient);
    sp<JavaDeathRecipient> find(jobject recipient);

    Mutex& lock();  // Use with care; specifically for mutual exclusion during binder death
};

// ----------------------------------------------------------------------------
@@ -392,6 +394,12 @@ public:
                        "*** Uncaught exception returned from death notification!");
            }

            // Serialize with our containing DeathRecipientList so that we can't
            // delete the global ref on mObject while the list is being iterated.
            sp<DeathRecipientList> list = mList.promote();
            if (list != NULL) {
                AutoMutex _l(list->lock());

                // Demote from strong ref to weak after binderDied() has been delivered,
                // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
                mObjectWeak = env->NewWeakGlobalRef(mObject);
@@ -399,6 +407,7 @@ public:
                mObject = NULL;
            }
        }
    }

    void clearReference()
    {
@@ -518,6 +527,10 @@ sp<JavaDeathRecipient> DeathRecipientList::find(jobject recipient) {
    return NULL;
}

Mutex& DeathRecipientList::lock() {
    return mLock;
}

// ----------------------------------------------------------------------------

namespace android {