Blame SOURCES/tigervnc-CVE-2019-15692.patch

aeab07
From 996356b6c65ca165ee1ea46a571c32a1dc3c3821 Mon Sep 17 00:00:00 2001
aeab07
From: Pierre Ossman <ossman@cendio.se>
aeab07
Date: Tue, 10 Sep 2019 15:21:03 +0200
aeab07
Subject: [PATCH] Restrict PixelBuffer dimensions to safe values
aeab07
aeab07
We do a lot of calculations based on pixel coordinates and we need
aeab07
to make sure they do not overflow. Restrict the maximum dimensions
aeab07
we support rather than try to switch over all calculations to use
aeab07
64 bit integers.
aeab07
aeab07
This prevents attackers from from injecting code by specifying a
aeab07
huge framebuffer size and relying on the values overflowing to
aeab07
access invalid areas of the heap.
aeab07
aeab07
This primarily affects the client which gets both the screen
aeab07
dimensions and the pixel contents from the remote side. But the
aeab07
server might also be affected as a client can adjust the screen
aeab07
dimensions, as can applications inside the session.
aeab07
aeab07
Issue found by Pavel Cheremushkin from Kaspersky Lab.
aeab07
---
aeab07
 common/rfb/PixelBuffer.cxx | 22 ++++++++++++++++++++++
aeab07
 1 file changed, 22 insertions(+)
aeab07
aeab07
diff --git a/common/rfb/PixelBuffer.cxx b/common/rfb/PixelBuffer.cxx
aeab07
index ad58324..18f41f8 100644
aeab07
--- a/common/rfb/PixelBuffer.cxx
aeab07
+++ b/common/rfb/PixelBuffer.cxx
aeab07
@@ -31,6 +31,14 @@ using namespace rdr;
aeab07
 
aeab07
 static LogWriter vlog("PixelBuffer");
aeab07
 
aeab07
+// We do a lot of byte offset calculations that assume the result fits
aeab07
+// inside a signed 32 bit integer. Limit the maximum size of pixel
aeab07
+// buffers so that these calculations never overflow.
aeab07
+
aeab07
+const int maxPixelBufferWidth = 16384;
aeab07
+const int maxPixelBufferHeight = 16384;
aeab07
+const int maxPixelBufferStride = 16384;
aeab07
+
aeab07
 
aeab07
 // -=- Generic pixel buffer class
aeab07
 
aeab07
@@ -108,6 +116,11 @@ void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf,
aeab07
 
aeab07
 void PixelBuffer::setSize(int width, int height)
aeab07
 {
aeab07
+  if ((width < 0) || (width > maxPixelBufferWidth))
aeab07
+    throw rfb::Exception("Invalid PixelBuffer width of %d pixels requested", width);
aeab07
+  if ((height < 0) || (height > maxPixelBufferHeight))
aeab07
+    throw rfb::Exception("Invalid PixelBuffer height of %d pixels requested", height);
aeab07
+
aeab07
   width_ = width;
aeab07
   height_ = height;
aeab07
 }
aeab07
@@ -337,6 +350,15 @@ const rdr::U8* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) cons
aeab07
 void FullFramePixelBuffer::setBuffer(int width, int height,
aeab07
                                      rdr::U8* data_, int stride_)
aeab07
 {
aeab07
+  if ((width < 0) || (width > maxPixelBufferWidth))
aeab07
+    throw rfb::Exception("Invalid PixelBuffer width of %d pixels requested", width);
aeab07
+  if ((height < 0) || (height > maxPixelBufferHeight))
aeab07
+    throw rfb::Exception("Invalid PixelBuffer height of %d pixels requested", height);
aeab07
+  if ((stride_ < 0) || (stride_ > maxPixelBufferStride) || (stride_ < width))
aeab07
+    throw rfb::Exception("Invalid PixelBuffer stride of %d pixels requested", stride_);
aeab07
+  if ((width != 0) && (height != 0) && (data_ == NULL))
aeab07
+    throw rfb::Exception("PixelBuffer requested without a valid memory area");
aeab07
+
aeab07
   ModifiablePixelBuffer::setSize(width, height);
aeab07
   stride = stride_;
aeab07
   data = data_;