CVE-2024-21640: Out-of-bounds Read (CWE-125)
value: Chromium Embedded Framework (CEF) is a simple framework for embedding Chromium-based browsers in other applications.`CefVideoConsumerOSR::OnFrameCaptured` does not check `pixel_format` properly, which leads to out-of-bounds read out of the sandbox. This vulnerability was patched in commit 1f55d2e.


CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 9.6
Published: 2024-01-13T08:15Z
Repository: https://github.com/chromiumembedded/cef
Language: C++
Files changed: libcef/browser/osr/host_display_client_osr.cc, libcef/browser/osr/video_consumer_osr.cc
Commit date: 2024-01-05 12:14:58 -0500
Commit message: osr: Fix potential shared memory OOB access

Diff: diff --git a/libcef/browser/osr/host_display_client_osr.cc b/libcef/browser/osr/host_display_client_osr.cc
index c734f6738..b1aa583fe 100644
--- a/libcef/browser/osr/host_display_client_osr.cc
+++ b/libcef/browser/osr/host_display_client_osr.cc
@@ -73,19 +73,28 @@ gfx::Size CefLayeredWindowUpdaterOSR::GetPixelSize() const {
 void CefLayeredWindowUpdaterOSR::OnAllocatedSharedMemory(
     const gfx::Size& pixel_size,
     base::UnsafeSharedMemoryRegion region) {
   // Make sure |pixel_size| is sane.
   size_t expected_bytes;
-  bool size_result = viz::ResourceSizes::MaybeSizeInBytes(
-      pixel_size, viz::SinglePlaneFormat::kRGBA_8888, &expected_bytes);
-  if (!size_result) {
+  if (!viz::ResourceSizes::MaybeSizeInBytes(
+          pixel_size, viz::SinglePlaneFormat::kRGBA_8888, &expected_bytes)) {
+    DLOG(ERROR) << "OnAllocatedSharedMemory with size that overflows";
+    return;
+  }
+
+  auto mapping = region.Map();
+  if (!mapping.IsValid()) {
+    DLOG(ERROR) << "Shared memory mapping failed.";
+    return;
+  }
+  if (mapping.size() < expected_bytes) {
+    DLOG(ERROR) << "Shared memory size was less than expected.";
     return;
   }
 
   pixel_size_ = pixel_size;
-  shared_memory_ = region.Map();
-  DCHECK(shared_memory_.IsValid());
+  shared_memory_ = std::move(mapping);
 }
 
 void CefLayeredWindowUpdaterOSR::Draw(const gfx::Rect& damage_rect,
                                       DrawCallback draw_callback) {
   if (active_) {
diff --git a/libcef/browser/osr/video_consumer_osr.cc b/libcef/browser/osr/video_consumer_osr.cc
index ee0e0c986..055cd6630 100644
--- a/libcef/browser/osr/video_consumer_osr.cc
+++ b/libcef/browser/osr/video_consumer_osr.cc
@@ -86,10 +86,15 @@ void CefVideoConsumerOSR::OnFrameCaptured(
     const gfx::Rect& content_rect,
     mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
         callbacks) {
   ScopedVideoFrameDone scoped_done(std::move(callbacks));
 
+  if (info->pixel_format != media::PIXEL_FORMAT_ARGB) {
+    DLOG(ERROR) << "Unsupported pixel format " << info->pixel_format;
+    return;
+  }
+
   CHECK(data->is_read_only_shmem_region());
   base::ReadOnlySharedMemoryRegion& shmem_region =
       data->get_read_only_shmem_region();
 
   // The |data| parameter is not nullable and mojo type mapping for

Vulnerable code:   bool size_result = viz::ResourceSizes::MaybeSizeInBytes(
      pixel_size, viz::SinglePlaneFormat::kRGBA_8888, &expected_bytes);
  if (!size_result) {
  shared_memory_ = region.Map();
  DCHECK(shared_memory_.IsValid());
Fixed code:   if (!viz::ResourceSizes::MaybeSizeInBytes(
          pixel_size, viz::SinglePlaneFormat::kRGBA_8888, &expected_bytes)) {
    DLOG(ERROR) << "OnAllocatedSharedMemory with size that overflows";
    return;
  }

  auto mapping = region.Map();
  if (!mapping.IsValid()) {
    DLOG(ERROR) << "Shared memory mapping failed.";
    return;
  }
  if (mapping.size() < expected_bytes) {
    DLOG(ERROR) << "Shared memory size was less than expected.";
  shared_memory_ = std::move(mapping);
  if (info->pixel_format != media::PIXEL_FORMAT_ARGB) {
    DLOG(ERROR) << "Unsupported pixel format " << info->pixel_format;
    return;
  }