Firefox · Graphics
CVE-2026-12289
Logic Error in Graphics
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifgfx/layers/ipc/ImageBridgeParent.cpp |
modified |
Files Changed
gfx/layers/ipc/CompositorBridgeParent.cppgfx/layers/ipc/CompositorBridgeParent.hgfx/layers/ipc/CompositorManagerParent.hgfx/layers/ipc/ContentCompositorBridgeParent.cppgfx/layers/ipc/ImageBridgeParent.cppgfx/layers/ipc/ImageBridgeParent.hgfx/layers/wr/WebRenderBridgeParent.cppgfx/layers/wr/WebRenderBridgeParent.h
Patch
diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp
index 2afe2cb373c..bdb031b8854 100644
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -149,6 +149,13 @@ bool CompositorBridgeParentBase::DeallocShmem(ipc::Shmem& aShmem) {
return PCompositorBridgeParent::DeallocShmem(aShmem);
}
+bool CompositorBridgeParentBase::OwnsExternalImageId(
+ const wr::ExternalImageId& aId) const {
+ return mCompositorManager &&
+ (static_cast<uint32_t>(wr::AsUint64(aId) >> 32) ==
+ mCompositorManager->GetNamespace());
+}
+
CompositorBridgeParent::LayerTreeState::LayerTreeState()
: mApzcTreeManagerParent(nullptr),
mApzInputBridgeParent(nullptr),
diff --git a/gfx/layers/ipc/CompositorBridgeParent.h b/gfx/layers/ipc/CompositorBridgeParent.h
index 00f46b06f5b..0530c9e8eba 100644
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -153,6 +153,8 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
// from the Compositor thread.
virtual void EnsureWebRenderBridgeParentInitialized() = 0;
+ bool OwnsExternalImageId(const wr::ExternalImageId& aId) const;
+
protected:
virtual ~CompositorBridgeParentBase();
diff --git a/gfx/layers/ipc/CompositorManagerParent.h b/gfx/layers/ipc/CompositorManagerParent.h
index ea5f0198ff9..c1a1210088a 100644
--- a/gfx/layers/ipc/CompositorManagerParent.h
+++ b/gfx/layers/ipc/CompositorManagerParent.h
@@ -78,6 +78,8 @@ class CompositorManagerParent final : public PCompositorManagerParent {
return mNamespace == static_cast<uint32_t>(wr::AsUint64(aId) >> 32);
}
+ uint32_t GetNamespace() const { return mNamespace; }
+
private:
static StaticMonitor sMonitor;
static StaticRefPtr<CompositorManagerParent> sInstance
diff --git a/gfx/layers/ipc/ContentCompositorBridgeParent.cpp b/gfx/layers/ipc/ContentCompositorBridgeParent.cpp
index f806b1ccf93..bf23dea49cb 100644
--- a/gfx/layers/ipc/ContentCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/ContentCompositorBridgeParent.cpp
@@ -423,6 +423,12 @@ PTextureParent* ContentCompositorBridgeParent::AllocPTextureParent(
const LayersBackend& aLayersBackend, const TextureFlags& aFlags,
const LayersId& aId, const uint64_t& aSerial,
const wr::MaybeExternalImageId& aExternalImageId) {
+ if (aExternalImageId.isSome() &&
+ !OwnsExternalImageId(aExternalImageId.ref())) {
+ NS_ERROR("We do not own this external image id.");
+ return nullptr;
+ }
+
CompositorBridgeParent::LayerTreeState* state = nullptr;
StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock);
diff --git a/gfx/layers/ipc/ImageBridgeParent.cpp b/gfx/layers/ipc/ImageBridgeParent.cpp
index 1926260319b..2dcf9b6bc2b 100644
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -317,8 +317,9 @@ PTextureParent* ImageBridgeParent::AllocPTextureParent(
const LayersBackend& aLayersBackend, const TextureFlags& aFlags,
const uint64_t& aSerial, const wr::MaybeExternalImageId& aExternalImageId) {
if (aExternalImageId.isSome()) {
- uint32_t ns = static_cast<uint32_t>(wr::AsUint64(*aExternalImageId) >> 32);
- if (ns == 0) {
+ if (aExternalImageId.isSome() &&
+ !OwnsExternalImageId(aExternalImageId.ref())) {
+ NS_ERROR("We do not own this external image id.");
return nullptr;
}
}
@@ -408,6 +409,12 @@ already_AddRefed<ImageBridgeParent> ImageBridgeParent::GetInstance(
return bridge.forget();
}
+bool ImageBridgeParent::OwnsExternalImageId(
+ const wr::ExternalImageId& aId) const {
+ return (static_cast<uint32_t>(wr::AsUint64(aId) >> 32) ==
+ static_cast<uint32_t>(static_cast<uint64_t>(mContentId) >> 32));
+}
+
bool ImageBridgeParent::AllocShmem(size_t aSize, ipc::Shmem* aShmem) {
if (mClosed) {
return false;
diff --git a/gfx/layers/ipc/ImageBridgeParent.h b/gfx/layers/ipc/ImageBridgeParent.h
index 672a8efa0e3..f300f8edce6 100644
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -126,6 +126,9 @@ class ImageBridgeParent final : public PImageBridgeParent,
static void ShutdownInternal();
void DeferredDestroy();
+
+ bool OwnsExternalImageId(const wr::ExternalImageId& aId) const;
+
nsCOMPtr<nsISerialEventTarget> mThread;
dom::ContentParentId mContentId;
diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp
index ef4b5b085da..adcf06a7266 100644
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -884,6 +884,11 @@ bool WebRenderBridgeParent::AddSharedExternalImage(
return true;
}
+ if (!GetCompositorBridge()->OwnsExternalImageId(aExtId)) {
+ gfxCriticalNote << "We do not own extId:" << wr::AsUint64(aExtId);
+ return false;
+ }
+
auto key = wr::AsUint64(aKey);
auto it = mSharedSurfaceIds.find(key);
if (it != mSharedSurfaceIds.end()) {
@@ -1660,6 +1665,12 @@ bool WebRenderBridgeParent::ProcessWebRenderParentCommands(
case WebRenderParentCommand::TOpAddPipelineIdForCompositable: {
const OpAddPipelineIdForCompositable& op =
cmd.get_OpAddPipelineIdForCompositable();
+ if (wr::AsUint64(op.pipelineId()) >> 32 !=
+ mLateInit->mIdNamespace.mHandle) {
+ success = false;
+ continue;
+ }
+
AddPipelineIdForCompositable(op.pipelineId(), op.handle(), op.owner(),
aTxn, txnForImageBridge);
break;
@@ -1667,6 +1678,12 @@ bool WebRenderBridgeParent::ProcessWebRenderParentCommands(
case WebRenderParentCommand::TOpRemovePipelineIdForCompositable: {
const OpRemovePipelineIdForCompositable& op =
cmd.get_OpRemovePipelineIdForCompositable();
+ if (wr::AsUint64(op.pipelineId()) >> 32 !=
+ mLateInit->mIdNamespace.mHandle) {
+ success = false;
+ continue;
+ }
+
auto* pendingOps =
mLateInit->mApi->GetPendingAsyncImagePipelineOps(aTxn);
@@ -1681,6 +1698,11 @@ bool WebRenderBridgeParent::ProcessWebRenderParentCommands(
case WebRenderParentCommand::TOpUpdateAsyncImagePipeline: {
const OpUpdateAsyncImagePipeline& op =
cmd.get_OpUpdateAsyncImagePipeline();
+ if (wr::AsUint64(op.pipelineId()) >> 32 !=
+ mLateInit->mIdNamespace.mHandle) {
+ success = false;
+ continue;
+ }
auto* pendingOps =
mLateInit->mApi->GetPendingAsyncImagePipelineOps(aTxn);
@@ -1699,6 +1721,12 @@ bool WebRenderBridgeParent::ProcessWebRenderParentCommands(
case WebRenderParentCommand::TOpUpdatedAsyncImagePipeline: {
const OpUpdatedAsyncImagePipeline& op =
cmd.get_OpUpdatedAsyncImagePipeline();
+ if (wr::AsUint64(op.pipelineId()) >> 32 !=
+ mLateInit->mIdNamespace.mHandle) {
+ success = false;
+ continue;
+ }
+
aTxn.InvalidateRenderedFrame(wr::RenderReasons::ASYNC_IMAGE);
auto* pendingOps =
diff --git a/gfx/layers/wr/WebRenderBridgeParent.h b/gfx/layers/wr/WebRenderBridgeParent.h
index 698943773a0..babfe604ae9 100644
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -260,6 +260,11 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
return aFontKey.mNamespace == mLateInit->mIdNamespace;
}
+ bool OwnsExternalImageId(const wr::ExternalImageId& aId) const {
+ return static_cast<uint32_t>(wr::AsUint64(aId) >> 32) ==
+ mLateInit->mIdNamespace.mHandle;
+ }
+
void FlushRendering(wr::RenderReasons aReasons, bool aBlocking);
/**
Loading diff…
References
On This Page