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

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