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

Commit 361d88e6 authored by John Reck's avatar John Reck Committed by Android (Google) Code Review
Browse files

Merge "Fix UAF in VkSemaphore management" into main

parents 8621fe01 4db23fdb
Loading
Loading
Loading
Loading
+66 −56
Original line number Diff line number Diff line
@@ -527,26 +527,41 @@ Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
    return Frame(surface->logicalWidth(), surface->logicalHeight(), bufferAge);
}

struct DestroySemaphoreInfo {
class SharedSemaphoreInfo : public LightRefBase<SharedSemaphoreInfo> {
    PFN_vkDestroySemaphore mDestroyFunction;
    VkDevice mDevice;
    VkSemaphore mSemaphore;
    GrBackendSemaphore mGrBackendSemaphore;

    DestroySemaphoreInfo(PFN_vkDestroySemaphore destroyFunction, VkDevice device,
    SharedSemaphoreInfo(PFN_vkDestroySemaphore destroyFunction, VkDevice device,
                        VkSemaphore semaphore)
            : mDestroyFunction(destroyFunction), mDevice(device), mSemaphore(semaphore) {}
            : mDestroyFunction(destroyFunction), mDevice(device), mSemaphore(semaphore) {
        mGrBackendSemaphore.initVulkan(semaphore);
    }

    ~SharedSemaphoreInfo() { mDestroyFunction(mDevice, mSemaphore, nullptr); }

    friend class LightRefBase<SharedSemaphoreInfo>;
    friend class sp<SharedSemaphoreInfo>;

    ~DestroySemaphoreInfo() { mDestroyFunction(mDevice, mSemaphore, nullptr); }
public:
    VkSemaphore semaphore() const { return mSemaphore; }

    GrBackendSemaphore* grBackendSemaphore() { return &mGrBackendSemaphore; }
};

static void destroy_semaphore(void* context) {
    DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(context);
    delete info;
    SharedSemaphoreInfo* info = reinterpret_cast<SharedSemaphoreInfo*>(context);
    info->decStrong(0);
}

VulkanManager::VkDrawResult VulkanManager::finishFrame(SkSurface* surface) {
    ATRACE_NAME("Vulkan finish frame");

    sp<SharedSemaphoreInfo> sharedSemaphore;
    GrFlushInfo flushInfo;

    {
        VkExportSemaphoreCreateInfo exportInfo;
        exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
        exportInfo.pNext = nullptr;
@@ -558,21 +573,19 @@ VulkanManager::VkDrawResult VulkanManager::finishFrame(SkSurface* surface) {
        semaphoreInfo.flags = 0;
        VkSemaphore semaphore;
        VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
    ALOGE_IF(VK_SUCCESS != err, "VulkanManager::makeSwapSemaphore(): Failed to create semaphore");

    GrBackendSemaphore backendSemaphore;
    backendSemaphore.initVulkan(semaphore);
        ALOGE_IF(VK_SUCCESS != err,
                 "VulkanManager::makeSwapSemaphore(): Failed to create semaphore");

    GrFlushInfo flushInfo;
        if (err == VK_SUCCESS) {
            sharedSemaphore = sp<SharedSemaphoreInfo>::make(mDestroySemaphore, mDevice, semaphore);
            flushInfo.fNumSemaphores = 1;
        flushInfo.fSignalSemaphores = &backendSemaphore;
            flushInfo.fSignalSemaphores = sharedSemaphore->grBackendSemaphore();
            flushInfo.fFinishedProc = destroy_semaphore;
        flushInfo.fFinishedContext =
                new DestroySemaphoreInfo(mDestroySemaphore, mDevice, semaphore);
    } else {
        semaphore = VK_NULL_HANDLE;
            sharedSemaphore->incStrong(0);
            flushInfo.fFinishedContext = sharedSemaphore.get();
        }
    }

    GrDirectContext* context = GrAsDirectContext(surface->recordingContext());
    ALOGE_IF(!context, "Surface is not backed by gpu");
    GrSemaphoresSubmitted submitted = context->flush(
@@ -581,13 +594,11 @@ VulkanManager::VkDrawResult VulkanManager::finishFrame(SkSurface* surface) {
    VkDrawResult drawResult{
            .submissionTime = systemTime(),
    };
    if (semaphore != VK_NULL_HANDLE) {
        if (submitted == GrSemaphoresSubmitted::kYes) {
            if (mFrameBoundaryANDROID) {
    if (sharedSemaphore) {
        if (submitted == GrSemaphoresSubmitted::kYes && mFrameBoundaryANDROID) {
            // retrieve VkImage used as render target
            VkImage image = VK_NULL_HANDLE;
                GrBackendRenderTarget backendRenderTarget =
                        SkSurfaces::GetBackendRenderTarget(
            GrBackendRenderTarget backendRenderTarget = SkSurfaces::GetBackendRenderTarget(
                    surface, SkSurfaces::BackendHandleAccess::kFlushRead);
            if (backendRenderTarget.isValid()) {
                GrVkImageInfo info;
@@ -601,17 +612,16 @@ VulkanManager::VkDrawResult VulkanManager::finishFrame(SkSurface* surface) {
            }
            // frameBoundaryANDROID needs to know about mSwapSemaphore, but
            // it won't wait on it.
                mFrameBoundaryANDROID(mDevice, semaphore, image);
            }
            mFrameBoundaryANDROID(mDevice, sharedSemaphore->semaphore(), image);
        }
        VkSemaphoreGetFdInfoKHR getFdInfo;
        getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
        getFdInfo.pNext = nullptr;
        getFdInfo.semaphore = semaphore;
        getFdInfo.semaphore = sharedSemaphore->semaphore();
        getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;

        int fenceFd = -1;
        err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
        VkResult err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
        ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd");
        drawResult.presentFence.reset(fenceFd);
    } else {
@@ -732,15 +742,15 @@ status_t VulkanManager::createReleaseFence(int* nativeFence, GrDirectContext* gr
        return INVALID_OPERATION;
    }

    GrBackendSemaphore backendSemaphore;
    backendSemaphore.initVulkan(semaphore);
    auto sharedSemaphore = sp<SharedSemaphoreInfo>::make(mDestroySemaphore, mDevice, semaphore);

    // Even if Skia fails to submit the semaphore, it will still call the destroy_semaphore callback
    GrFlushInfo flushInfo;
    flushInfo.fNumSemaphores = 1;
    flushInfo.fSignalSemaphores = &backendSemaphore;
    flushInfo.fSignalSemaphores = sharedSemaphore->grBackendSemaphore();
    flushInfo.fFinishedProc = destroy_semaphore;
    flushInfo.fFinishedContext = new DestroySemaphoreInfo(mDestroySemaphore, mDevice, semaphore);
    sharedSemaphore->incStrong(0);
    flushInfo.fFinishedContext = sharedSemaphore.get();
    GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
    grContext->submit();