|
|
|
|
Quelle s0143.patch
Sprache: unbekannt
|
|
Spracherkennung für: .patch vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
From: Jan Grulich <jgrulich@redhat.com>
Date: Mon, 11 May 2026 13: 14: 00 + 0000
Subject: Bug 2029760 - WebRTC backport: Wayland capture: validate buffer
geometry before pixel copy r=pehrsons
Reject Memfd buffers where stride exceeds the mapped region to prevent
out-of-bounds reads. Cap stream dimensions to prevent integer overflow
in frame allocation. Bound cursor bitmap stride to reject oversized
values.
This is a simple backport of an WebRTC upstream change.
Upstream commit: 125a9d22b0edd885012a492fcb2fb2d795e5a106
Differential Revision: https://phabricator.services.mozilla.com/D299701
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/eeff6f8f9ba06980cff396edd90c3d6e52b83cdd
---
.../linux/wayland/shared_screencast_stream.cc | 44 ++++++++++++++-----
.../shared_screencast_stream_unittest.cc | 11 +++++
.../test/test_screencast_stream_provider.cc | 2 +
.../test/test_screencast_stream_provider.h | 8 +++-
4 files changed, 53 insertions(+), 12 deletions(-)
diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/mo dules/desktop_capture/linux/wayland/shared_screencast_stream.cc
index e09a2d8b3e..90985c5ae2 100644
--- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
+++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
@@ -72,6 +72,9 @@ namespace webrtc {
constexpr int kBytesPerPixel = 4;
constexpr int kMaxCursorSize = 1024;
constexpr int kVideoDamageRegionCount = 16;
+// A reasonable maximum size so "width * height * kBytesPerPixel" doesn't
+// overflow
+constexpr int kMaxScreenCastDimension = 16384;
constexpr int CursorMetaSize(int w, int h) {
return (sizeof(struct spa_meta_cursor) + sizeof(struct spa_meta_bitmap) +
@@ -338,6 +341,12 @@ void SharedScreenCastStreamPrivate::OnStreamParamChanged(
has_modifier ? that->spa_video_format_.modifier : DRM_FORMAT_MOD_INVALID;
that->stream_size_ = DesktopSize(that->spa_video_format_.size.width,
that->spa_video_format_.size.height);
+ if (that->stream_size_.is_empty() ||
+ that->stream_size_.width() > kMaxScreenCastDimension ||
+ that->stream_size_.height() > kMaxScreenCastDimension) {
+ that->stream_size_ = DesktopSize();
+ return;
+ }
if (that->observer_) {
that->observer_->OnFormatChanged(
@@ -787,7 +796,11 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) {
if (bitmap && bitmap->size.width > 0 &&
bitmap->size.width <= kMaxCursorSize && bitmap->size.height > 0 &&
- bitmap->size.height <= kMaxCursorSize) {
+ bitmap->size.height <= kMaxCursorSize &&
+ bitmap->stride >=
+ static_cast<int32_t>(bitmap->size.width * kBytesPerPixel) &&
+ bitmap->stride * bitmap->size.height <=
+ kMaxCursorSize * kMaxCursorSize * kBytesPerPixel) {
const uint8_t* bitmap_data =
SPA_MEMBER(bitmap, bitmap->offset, uint8_t);
// TODO(bugs.webrtc.org/436974448): Convert `spa_video_format` to
@@ -1012,29 +1025,38 @@ bool SharedScreenCastStreamPrivate::ProcessMemFDBuffer(
ScopedBuf map;
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,
- spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
- PROT_READ, MAP_PRIVATE, spa_buffer->datas[0].fd, 0)),
- spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
- spa_buffer->datas[0].fd);
+ 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);
if (!map) {
RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " << std::strerror(errno);
return false;
}
- src = SPA_MEMBER(map.get(), spa_buffer->datas[0].mapoffset, uint8_t);
+ src = SPA_MEMBER(map.get(), mapoffset, uint8_t);
- uint32_t buffer_stride = spa_buffer->datas[0].chunk->stride;
- uint32_t src_stride = buffer_stride;
+ const uint64_t src_stride = spa_buffer->datas[0].chunk->stride;
+
+ if (src_stride > INT32_MAX ||
+ src_stride < static_cast<uint64_t>(offset.x() + frame.size().width()) *
+ kBytesPerPixel ||
+ src_stride * (offset.y() + frame.size().height()) > maxsize) {
+ RTC_LOG(LS_ERROR) << "Rejecting MemFd buffer with invalid geometry: stride="
+ << src_stride << " maxsize=" << maxsize;
+ return false;
+ }
uint8_t* updated_src =
src + (src_stride * offset.y()) + (kBytesPerPixel * offset.x());
frame.CopyPixelsFrom(
- updated_src, (src_stride - (kBytesPerPixel * offset.x())),
+ updated_src, static_cast<int>(src_stride),
DesktopRect::MakeWH(frame.size().width(), frame.size().height()));
return true;
diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream_unittest.cc b/modules/desktop_capture/linux/wayland/shared_screencast_stream_unittest.cc
index d51305be43..45f4aa3ee5 100644
--- a/modules/desktop_capture/linux/wayland/shared_screencast_stream_unittest.cc
+++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream_unittest.cc
@@ -395,6 +395,17 @@ TEST_F(MAYBE_PipeWireStreamTest, TestModifierFallback) {
blue_color, TestScreenCastStreamProvider::EmptyData);
emptyFrameEvent.Wait(kShortWait);
+ // Check that a MemFd buffer with an invalid stride is rejected
+ Event invalidStrideEvent;
+ EXPECT_CALL(*this, OnFrameRecorded);
+ EXPECT_CALL(*this, OnFailedToProcessBuffer).WillOnce([&invalidStrideEvent] {
+ invalidStrideEvent.Set();
+ });
+
+ test_screencast_stream_provider_->RecordFrame(
+ blue_color, TestScreenCastStreamProvider::InvalidStride);
+ invalidStrideEvent.Wait(kShortWait);
+
// Test disconnection from stream
EXPECT_CALL(*this, OnStopStreaming);
shared_screencast_stream_->StopScreenCastStream();
diff --git a/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc b/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
index e1eaa369b8..14780310ef 100644
--- a/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
+++ b/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.cc
@@ -235,6 +235,8 @@ void TestScreenCastStreamProvider::RecordFrame(RgbaColor rgba_color,
spa_data->chunk->size = 0;
} else if (frame_defect == CorruptedData) {
spa_data->chunk->flags = SPA_CHUNK_FLAG_CORRUPTED;
+ } else if (frame_defect == InvalidStride) {
+ spa_data->chunk->stride = spa_data->maxsize + 1;
} else if (frame_defect == CorruptedMetadata) {
struct spa_meta_header* spa_header =
static_cast<spa_meta_header*>(spa_buffer_find_meta_data(
diff --git a/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.h b/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.h
index 2262d49200..82feb90e61 100644
--- a/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.h
+++ b/modules/desktop_capture/linux/wayland/test/test_screencast_stream_provider.h
@@ -41,7 +41,13 @@ class TestScreenCastStreamProvider {
virtual ~Observer() = default;
};
- enum FrameDefect { None, EmptyData, CorruptedData, CorruptedMetadata };
+ enum FrameDefect {
+ None,
+ EmptyData,
+ CorruptedData,
+ CorruptedMetadata,
+ InvalidStride
+ };
explicit TestScreenCastStreamProvider(Observer* observer,
uint32_t width,
[Dauer der Verarbeitung: 0.47 Sekunden]
|
2026-08-25
|
|
|
|
|
Neuigkeiten |
| Aktuelles |
| Motto des Tages |
|
Open Source Software |
|
|
|
Jenseits des Üblichen ....
|
|
Besucherstatistik |
|
|
| Statistik |
| #Sources=141584 |
| #Domains=752002 |
|
|