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

Commit f3ef6fd8 authored by Shuzhen Wang's avatar Shuzhen Wang
Browse files

Camera: Fix use-after-free in AidlProviderInfo

Passing a RefBase object as a cookie for linkToDeath is problematic
because RefBase is reference counted, and it may be deleted while the
raw pointer is held.

Instead, create a struct containing a weak pointer to the object. This
way we decouple the life cycle of the AidlProviderInfo from the death
notification cookie.

Flag: EXEMPT bug-fix
Test: Vendor testing, run camera and kill provider, Camera CTS
Bug: 381496144
Change-Id: I477e121a77a7a2501e4ae9f86ce513355f98847a
parent 9aab1380
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -134,10 +134,14 @@ status_t AidlProviderInfo::initializeAidlProvider(
    }

    mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(binderDied));
    AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), /*onUnlinked*/ [](void *cookie) {
            AIBinderCookie *binderCookie = reinterpret_cast<AIBinderCookie *>(cookie);
            delete binderCookie;
        });

    if (!vd_flags::virtual_camera_service_discovery() || interface->isRemote()) {
        binder_status_t link =
                AIBinder_linkToDeath(interface->asBinder().get(), mDeathRecipient.get(), this);
        binder_status_t link = AIBinder_linkToDeath(
            interface->asBinder().get(), mDeathRecipient.get(), new AIBinderCookie{this});
        if (link != STATUS_OK) {
            ALOGW("%s: Unable to link to provider '%s' death notifications (%d)", __FUNCTION__,
                  mProviderName.c_str(), link);
@@ -201,9 +205,12 @@ status_t AidlProviderInfo::initializeAidlProvider(
}

void AidlProviderInfo::binderDied(void *cookie) {
    AidlProviderInfo *provider = reinterpret_cast<AidlProviderInfo *>(cookie);
    AIBinderCookie* binderCookie = reinterpret_cast<AIBinderCookie*>(cookie);
    sp<AidlProviderInfo> provider = binderCookie->providerInfo.promote();
    if (provider != nullptr) {
        ALOGI("Camera provider '%s' has died; removing it", provider->mProviderInstance.c_str());
    provider->mManager->removeProvider(std::string(provider->mProviderInstance));
        provider->mManager->removeProvider(provider->mProviderInstance);
    }
}

status_t AidlProviderInfo::setUpVendorTags() {
@@ -317,7 +324,7 @@ const std::shared_ptr<ICameraProvider> AidlProviderInfo::startProviderInterface(

    interface->setCallback(mCallbacks);
    auto link = AIBinder_linkToDeath(interface->asBinder().get(), mDeathRecipient.get(),
            this);
            new AIBinderCookie{this});
    if (link != STATUS_OK) {
        ALOGW("%s: Unable to link to provider '%s' death notifications",
                __FUNCTION__, mProviderName.c_str());
+3 −0
Original line number Diff line number Diff line
@@ -168,6 +168,9 @@ struct AidlProviderInfo : public CameraProviderManager::ProviderInfo {
                *halCameraIdsAndStreamCombinations,
        bool *earlyExit);
    std::shared_ptr<AidlProviderCallbacks> mCallbacks = nullptr;
    struct AIBinderCookie {
        wp<AidlProviderInfo> providerInfo;
    };
    ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;

};