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

aeab07
From d61a767d6842b530ffb532ddd5a3d233119aad40 Mon Sep 17 00:00:00 2001
aeab07
From: Pierre Ossman <ossman@cendio.se>
aeab07
Date: Tue, 10 Sep 2019 11:05:48 +0200
aeab07
Subject: [PATCH] Make ZlibInStream more robust against failures
aeab07
aeab07
Move the checks around to avoid missing cases where we might access
aeab07
memory that is no longer valid. Also avoid touching the underlying
aeab07
stream implicitly (e.g. via the destructor) as it might also no
aeab07
longer be valid.
aeab07
aeab07
A malicious server could theoretically use this for remote code
aeab07
execution in the client.
aeab07
aeab07
Issue found by Pavel Cheremushkin from Kaspersky Lab
aeab07
---
aeab07
 common/rdr/ZlibInStream.cxx | 13 +++++++------
aeab07
 common/rdr/ZlibInStream.h   |  2 +-
aeab07
 common/rfb/CMsgReader.cxx   |  3 ++-
aeab07
 common/rfb/SMsgReader.cxx   |  3 ++-
aeab07
 common/rfb/TightDecoder.cxx |  3 ++-
aeab07
 common/rfb/zrleDecode.h     |  3 ++-
aeab07
 6 files changed, 16 insertions(+), 11 deletions(-)
aeab07
aeab07
diff --git a/common/rdr/ZlibInStream.cxx b/common/rdr/ZlibInStream.cxx
aeab07
index 4053bd1..a361010 100644
aeab07
--- a/common/rdr/ZlibInStream.cxx
aeab07
+++ b/common/rdr/ZlibInStream.cxx
aeab07
@@ -52,16 +52,16 @@ int ZlibInStream::pos()
aeab07
   return offset + ptr - start;
aeab07
 }
aeab07
 
aeab07
-void ZlibInStream::removeUnderlying()
aeab07
+void ZlibInStream::flushUnderlying()
aeab07
 {
aeab07
   ptr = end = start;
aeab07
-  if (!underlying) return;
aeab07
 
aeab07
   while (bytesIn > 0) {
aeab07
     decompress(true);
aeab07
     end = start; // throw away any data
aeab07
   }
aeab07
-  underlying = 0;
aeab07
+
aeab07
+  setUnderlying(NULL, 0);
aeab07
 }
aeab07
 
aeab07
 void ZlibInStream::reset()
aeab07
@@ -90,7 +90,7 @@ void ZlibInStream::init()
aeab07
 void ZlibInStream::deinit()
aeab07
 {
aeab07
   assert(zs != NULL);
aeab07
-  removeUnderlying();
aeab07
+  setUnderlying(NULL, 0);
aeab07
   inflateEnd(zs);
aeab07
   delete zs;
aeab07
   zs = NULL;
aeab07
@@ -100,8 +100,6 @@ int ZlibInStream::overrun(int itemSize, int nItems, bool wait)
aeab07
 {
aeab07
   if (itemSize > bufSize)
aeab07
     throw Exception("ZlibInStream overrun: max itemSize exceeded");
aeab07
-  if (!underlying)
aeab07
-    throw Exception("ZlibInStream overrun: no underlying stream");
aeab07
 
aeab07
   if (end - ptr != 0)
aeab07
     memmove(start, ptr, end - ptr);
aeab07
@@ -127,6 +125,9 @@ int ZlibInStream::overrun(int itemSize, int nItems, bool wait)
aeab07
 
aeab07
 bool ZlibInStream::decompress(bool wait)
aeab07
 {
aeab07
+  if (!underlying)
aeab07
+    throw Exception("ZlibInStream overrun: no underlying stream");
aeab07
+
aeab07
   zs->next_out = (U8*)end;
aeab07
   zs->avail_out = start + bufSize - end;
aeab07
 
aeab07
diff --git a/common/rdr/ZlibInStream.h b/common/rdr/ZlibInStream.h
aeab07
index 6bd4da4..86ba1ff 100644
aeab07
--- a/common/rdr/ZlibInStream.h
aeab07
+++ b/common/rdr/ZlibInStream.h
aeab07
@@ -38,7 +38,7 @@ namespace rdr {
aeab07
     virtual ~ZlibInStream();
aeab07
 
aeab07
     void setUnderlying(InStream* is, int bytesIn);
aeab07
-    void removeUnderlying();
aeab07
+    void flushUnderlying();
aeab07
     int pos();
aeab07
     void reset();
aeab07
 
aeab07
diff --git a/common/rfb/TightDecoder.cxx b/common/rfb/TightDecoder.cxx
aeab07
index 3a1254a..4273eb7 100644
aeab07
--- a/common/rfb/TightDecoder.cxx
aeab07
+++ b/common/rfb/TightDecoder.cxx
aeab07
@@ -340,7 +340,8 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer,
aeab07
 
aeab07
     zis[streamId].readBytes(netbuf, dataSize);
aeab07
 
aeab07
-    zis[streamId].removeUnderlying();
aeab07
+    zis[streamId].flushUnderlying();
aeab07
+    zis[streamId].setUnderlying(NULL, 0);
aeab07
     delete ms;
aeab07
 
aeab07
     bufptr = netbuf;
aeab07
diff --git a/common/rfb/zrleDecode.h b/common/rfb/zrleDecode.h
aeab07
index 0bfbbe1..a69ca67 100644
aeab07
--- a/common/rfb/zrleDecode.h
aeab07
+++ b/common/rfb/zrleDecode.h
aeab07
@@ -178,7 +178,8 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is,
aeab07
     }
aeab07
   }
aeab07
 
aeab07
-  zis->removeUnderlying();
aeab07
+  zis->flushUnderlying();
aeab07
+  zis->setUnderlying(NULL, 0);
aeab07
 }
aeab07
 
aeab07
 #undef ZRLE_DECODE