Moderate firefox Logic Error 🔧 Commit mapped

Overview

Moderate
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionSandbox escape due to incorrect boundary conditions in the WebRTC component
ComponentCore
Bug ClassLogic Error
Tracker2054622
Fix commit7429bd5bf2d2 (firefox) +74/-38
CISA KEVNot listed
CreditedMozilla
Disclosed2026-09-15

Changed Functions

FunctionChangeNotes
if
third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
modified
if
third_party/libwebrtc/modules/portal/pipewire_utils.cc
modified
ScopedBuf
third_party/libwebrtc/modules/portal/pipewire_utils.h
modified
ScopedBuf
third_party/libwebrtc/modules/portal/pipewire_utils.h
modified
if
third_party/libwebrtc/modules/portal/pipewire_utils.h
modified
if
third_party/libwebrtc/modules/video_capture/linux/video_capture_pipewire.cc
modified
if
third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_egl_dmabuf.cc
modified
if
third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
modified

Files Changed

  • third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
  • third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_egl_dmabuf.cc
  • third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
  • third_party/libwebrtc/modules/portal/pipewire_utils.cc
  • third_party/libwebrtc/modules/portal/pipewire_utils.h
  • third_party/libwebrtc/modules/video_capture/linux/video_capture_pipewire.cc
  • third_party/libwebrtc/moz-patch-stack/5c10f93376.no-op-cherry-pick-msg
  • third_party/libwebrtc/moz-patch-stack/c84dbe590a.no-op-cherry-pick-msg
diff --git a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
index 2ddc03dd7bf..657eb346e8e 100644
--- a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
+++ b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
@@ -1052,20 +1052,15 @@ bool SharedScreenCastStreamPrivate::ProcessMemFDBuffer(
   uint8_t* src = nullptr;
 
   const uint64_t maxsize = static_cast<uint64_t>(spa_buffer->datas[0].maxsize);
-  const uint64_t mapoffset =
-      static_cast<uint64_t>(spa_buffer->datas[0].mapoffset);
-
-  map.initialize(
-      static_cast<uint8_t*>(mmap(nullptr, maxsize + mapoffset, PROT_READ,
-                                 MAP_PRIVATE, spa_buffer->datas[0].fd, 0)),
-      maxsize + mapoffset, spa_buffer->datas[0].fd);
+  map.initialize(spa_buffer->datas[0].fd, maxsize,
+                 spa_buffer->datas[0].mapoffset, ScopedBuf::BufferType::kMemFd);
 
   if (!map) {
     RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " << std::strerror(errno);
     return false;
   }
 
-  src = SPA_MEMBER(map.get(), mapoffset, uint8_t);
+  src = map.get();
 
   const uint64_t src_stride = spa_buffer->datas[0].chunk->stride;
 
diff --git a/third_party/libwebrtc/modules/portal/pipewire_utils.cc b/third_party/libwebrtc/modules/portal/pipewire_utils.cc
index 7008696b7d2..bdea4318e7a 100644
--- a/third_party/libwebrtc/modules/portal/pipewire_utils.cc
+++ b/third_party/libwebrtc/modules/portal/pipewire_utils.cc
@@ -11,13 +11,18 @@
 #include "modules/portal/pipewire_utils.h"
 
 #include <pipewire/pipewire.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
 
+#include <cstddef>
+#include <cstdint>
 #include <optional>
 #include <string>
 #include <string_view>
 #include <tuple>
 #include <vector>
 
+#include "rtc_base/checks.h"
 #include "rtc_base/sanitizer.h"
 #include "rtc_base/string_encode.h"
 #include "rtc_base/string_to_number.h"
@@ -120,4 +125,41 @@ PipeWireInitializer::~PipeWireInitializer() {
   }
 }
 
+void ScopedBuf::initialize(int fd,
+                           size_t maxsize,
+                           off_t mapoffset,
+                           BufferType buffer_type,
+                           AccessMode mode) {
+  // PipeWire supports shared memory mappings <= 4GB in size.
+  RTC_CHECK_GE(mapoffset, 0);
+  RTC_CHECK_LE(mapoffset, UINT32_MAX);
+  RTC_CHECK_LE(maxsize, UINT32_MAX);
+
+  if (buffer_type == BufferType::kMemFd) {
+    struct stat sb;
+    if (fstat(fd, &sb) != 0 ||
+        static_cast<int64_t>(mapoffset) + static_cast<int64_t>(maxsize) >
+            static_cast<int64_t>(sb.st_size)) {
+      return;
+    }
+  }
+
+  int prot =
+      mode == AccessMode::kReadWrite ? (PROT_READ | PROT_WRITE) : PROT_READ;
+  int flags =
+      (buffer_type == BufferType::kDmaBuf || mode == AccessMode::kReadWrite)
+          ? MAP_SHARED
+          : MAP_PRIVATE;
+
+  map_ =
+      static_cast<uint8_t*>(mmap(nullptr, maxsize, prot, flags, fd, mapoffset));
+  map_size_ = maxsize;
+  fd_ = fd;
+  buffer_type_ = buffer_type;
+
+  if (buffer_type_ == BufferType::kDmaBuf && map_ != MAP_FAILED) {
+    SyncDmaBuf(fd_, DMA_BUF_SYNC_START);
+  }
+}
+
 }  // namespace webrtc
diff --git a/third_party/libwebrtc/modules/portal/pipewire_utils.h b/third_party/libwebrtc/modules/portal/pipewire_utils.h
index d0734c19be0..e3769294f22 100644
--- a/third_party/libwebrtc/modules/portal/pipewire_utils.h
+++ b/third_party/libwebrtc/modules/portal/pipewire_utils.h
@@ -16,6 +16,7 @@
 #include <sys/mman.h>
 
 #include <cerrno>
+#include <cstddef>
 #include <cstdint>
 #include <string>
 #include <string_view>
@@ -102,12 +103,17 @@ static bool SyncDmaBuf(int fd, uint64_t start_or_end) {
 
 class ScopedBuf {
  public:
+  enum class AccessMode { kReadOnly, kReadWrite };
+  enum class BufferType { kMemFd, kDmaBuf };
+
   ScopedBuf() {}
-  ScopedBuf(uint8_t* map, int map_size, int fd, bool is_dma_buf = false)
-      : map_(map), map_size_(map_size), fd_(fd), is_dma_buf_(is_dma_buf) {}
+  ScopedBuf(const ScopedBuf&) = delete;
+  ScopedBuf& operator=(const ScopedBuf&) = delete;
+  ScopedBuf(ScopedBuf&&) = delete;
+  ScopedBuf& operator=(ScopedBuf&&) = delete;
   ~ScopedBuf() {
     if (map_ != MAP_FAILED) {
-      if (is_dma_buf_) {
+      if (buffer_type_ == BufferType::kDmaBuf) {
         SyncDmaBuf(fd_, DMA_BUF_SYNC_END);
       }
       munmap(map_, map_size_);
@@ -116,24 +122,19 @@ class ScopedBuf {
 
   explicit operator bool() { return map_ != MAP_FAILED; }
 
-  void initialize(uint8_t* map, int map_size, int fd, bool is_dma_buf = false) {
-    map_ = map;
-    map_size_ = map_size;
-    is_dma_buf_ = is_dma_buf;
-    fd_ = fd;
-
-    if (is_dma_buf_) {
-      SyncDmaBuf(fd_, DMA_BUF_SYNC_START);
-    }
-  }
+  void initialize(int fd,
+                  size_t maxsize,
+                  off_t mapoffset,
+                  BufferType buffer_type,
+                  AccessMode mode = AccessMode::kReadOnly);
 
   uint8_t* get() { return map_; }
 
  protected:
   uint8_t* map_ = static_cast<uint8_t*>(MAP_FAILED);
-  int map_size_;
-  int fd_;
-  bool is_dma_buf_;
+  size_t map_size_ = 0;
+  int fd_ = -1;
+  BufferType buffer_type_ = BufferType::kMemFd;
 };
 
 }  // namespace webrtc
diff --git a/third_party/libwebrtc/modules/video_capture/linux/video_capture_pipewire.cc b/third_party/libwebrtc/modules/video_capture/linux/video_capture_pipewire.cc
index 54586e26737..2b3b619c384 100644
--- a/third_party/libwebrtc/modules/video_capture/linux/video_capture_pipewire.cc
+++ b/third_party/libwebrtc/modules/video_capture/linux/video_capture_pipewire.cc
@@ -24,7 +24,6 @@
 #include <spa/utils/defs.h>
 #include <spa/utils/result.h>
 #include <spa/utils/type.h>
-#include <sys/mman.h>
 
 #include <algorithm>
 #include <cerrno>
@@ -483,12 +482,11 @@ void VideoCaptureModulePipeWire::ProcessBuffers() {
     if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf ||
         spaBuffer->datas[0].type == SPA_DATA_MemFd) {
       ScopedBuf frame;
-      frame.initialize(
-          static_cast<uint8_t*>(
-              mmap(nullptr, spaBuffer->datas[0].maxsize, PROT_READ, MAP_SHARED,
-                   spaBuffer->datas[0].fd, spaBuffer->datas[0].mapoffset)),
-          spaBuffer->datas[0].maxsize, spaBuffer->datas[0].fd,
-          spaBuffer->datas[0].type == SPA_DATA_DmaBuf);
+      frame.initialize(spaBuffer->datas[0].fd, spaBuffer->datas[0].maxsize,
+                       spaBuffer->datas[0].mapoffset,
+                       spaBuffer->datas[0].type == SPA_DATA_DmaBuf
+                           ? ScopedBuf::BufferType::kDmaBuf
+                           : ScopedBuf::BufferType::kMemFd);
 
       if (!frame) {
         RTC_LOG(LS_ERROR) << "Failed to mmap the memory: "
diff --git a/third_party/libwebrtc/moz-patch-stack/5c10f93376.no-op-cherry-pick-msg b/third_party/libwebrtc/moz-patch-stack/5c10f93376.no-op-cherry-pick-msg
new file mode 100644
index 00000000000..fb9139275fd
--- /dev/null
+++ b/third_party/libwebrtc/moz-patch-stack/5c10f93376.no-op-cherry-pick-msg
@@ -0,0 +1 @@
+We cherry-picked this in bug 2054622.
\ No newline at end of file
diff --git a/third_party/libwebrtc/moz-patch-stack/c84dbe590a.no-op-cherry-pick-msg b/third_party/libwebrtc/moz-patch-stack/c84dbe590a.no-op-cherry-pick-msg
new file mode 100644
index 00000000000..fb9139275fd
--- /dev/null
+++ b/third_party/libwebrtc/moz-patch-stack/c84dbe590a.no-op-cherry-pick-msg
@@ -0,0 +1 @@
+We cherry-picked this in bug 2054622.
\ No newline at end of file
diff --git a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_egl_dmabuf.cc b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_egl_dmabuf.cc
index 36be3fa8ee0..58f745ede5b 100644
--- a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_egl_dmabuf.cc
+++ b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_egl_dmabuf.cc
@@ -60,10 +60,9 @@ bool TestEglDrmDevice::ImageFromDmaBuf(
   const size_t plane_stride = plane.stride;
   const size_t buffer_size_bytes = plane_stride * size.height();
 
-  uint8_t* map = static_cast<uint8_t*>(
-      mmap(nullptr, buffer_size_bytes, PROT_READ, MAP_SHARED, plane.fd, 0));
   ScopedBuf scoped_buf;
-  scoped_buf.initialize(map, buffer_size_bytes, plane.fd, true);
+  scoped_buf.initialize(plane.fd, buffer_size_bytes, 0,
+                        ScopedBuf::BufferType::kDmaBuf);
 
   if (!scoped_buf) {
     RTC_LOG(LS_ERROR) << "TestEglDrmDevice: Failed to mmap DMA-BUF";
diff --git a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
index 14780310efb..183bb1cf308 100644
--- a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
+++ b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
@@ -195,10 +195,9 @@ void TestScreenCastStreamProvider::RecordFrame(RgbaColor rgba_color,
   ScopedBuf scoped_buf;
 
   if (spa_data->type == SPA_DATA_DmaBuf) {
-    uint8_t* map =
-        static_cast<uint8_t*>(mmap(nullptr, buffer_size, PROT_READ | PROT_WRITE,
-                                   MAP_SHARED, spa_data->fd, 0));
-    scoped_buf.initialize(map, buffer_size, spa_data->fd, true);
+    scoped_buf.initialize(spa_data->fd, buffer_size, 0,
+                          ScopedBuf::BufferType::kDmaBuf,
+                          ScopedBuf::AccessMode::kReadWrite);
     if (!scoped_buf) {
       RTC_LOG(LS_ERROR) << "Failed to mmap DMA-BUF for recording";
       pw_stream_queue_buffer(pw_stream_, buffer);
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_egl_dmabuf.cc b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_egl_dmabuf.cc
index 36be3fa8ee0..58f745ede5b 100644
--- a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_egl_dmabuf.cc
+++ b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_egl_dmabuf.cc
@@ -60,10 +60,9 @@ bool TestEglDrmDevice::ImageFromDmaBuf(
   const size_t plane_stride = plane.stride;
   const size_t buffer_size_bytes = plane_stride * size.height();
 
-  uint8_t* map = static_cast<uint8_t*>(
-      mmap(nullptr, buffer_size_bytes, PROT_READ, MAP_SHARED, plane.fd, 0));
   ScopedBuf scoped_buf;
-  scoped_buf.initialize(map, buffer_size_bytes, plane.fd, true);
+  scoped_buf.initialize(plane.fd, buffer_size_bytes, 0,
+                        ScopedBuf::BufferType::kDmaBuf);
 
   if (!scoped_buf) {
     RTC_LOG(LS_ERROR) << "TestEglDrmDevice: Failed to mmap DMA-BUF";
diff --git a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
index 14780310efb..183bb1cf308 100644
--- a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
+++ b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
@@ -195,10 +195,9 @@ void TestScreenCastStreamProvider::RecordFrame(RgbaColor rgba_color,
   ScopedBuf scoped_buf;
 
   if (spa_data->type == SPA_DATA_DmaBuf) {
-    uint8_t* map =
-        static_cast<uint8_t*>(mmap(nullptr, buffer_size, PROT_READ | PROT_WRITE,
-                                   MAP_SHARED, spa_data->fd, 0));
-    scoped_buf.initialize(map, buffer_size, spa_data->fd, true);
+    scoped_buf.initialize(spa_data->fd, buffer_size, 0,
+                          ScopedBuf::BufferType::kDmaBuf,
+                          ScopedBuf::AccessMode::kReadWrite);
     if (!scoped_buf) {
       RTC_LOG(LS_ERROR) << "Failed to mmap DMA-BUF for recording";
       pw_stream_queue_buffer(pw_stream_, buffer);
Loading diff…