diff --git a/SOURCES/LibVNCServer-0.9.10-CVE-2014-6051.patch b/SOURCES/LibVNCServer-0.9.10-CVE-2014-6051.patch new file mode 100644 index 0000000..ee6598c --- /dev/null +++ b/SOURCES/LibVNCServer-0.9.10-CVE-2014-6051.patch @@ -0,0 +1,42 @@ +commit 045a044e8ae79db9244593fbce154cdf6e843273 +Author: newsoft +Date: Fri Aug 15 16:31:13 2014 +0200 + + Fix integer overflow in MallocFrameBuffer() + + Promote integers to uint64_t to avoid integer overflow issue during + frame buffer allocation for very large screen sizes + +diff --git a/libvncclient/vncviewer.c b/libvncclient/vncviewer.c +index 3b16a6f..24bc6f8 100644 +--- a/libvncclient/vncviewer.c ++++ b/libvncclient/vncviewer.c +@@ -82,9 +82,27 @@ static char* ReadPassword(rfbClient* client) { + #endif + } + static rfbBool MallocFrameBuffer(rfbClient* client) { ++uint64_t allocSize; ++ + if(client->frameBuffer) + free(client->frameBuffer); +- client->frameBuffer=malloc(client->width*client->height*client->format.bitsPerPixel/8); ++ ++ /* SECURITY: promote 'width' into uint64_t so that the multiplication does not overflow ++ 'width' and 'height' are 16-bit integers per RFB protocol design ++ SIZE_MAX is the maximum value that can fit into size_t ++ */ ++ allocSize = (uint64_t)client->width * client->height * client->format.bitsPerPixel/8; ++ ++ if (allocSize >= SIZE_MAX) { ++ rfbClientErr("CRITICAL: cannot allocate frameBuffer, requested size is too large\n"); ++ return FALSE; ++ } ++ ++ client->frameBuffer=malloc( (size_t)allocSize ); ++ ++ if (client->frameBuffer == NULL) ++ rfbClientErr("CRITICAL: frameBuffer allocation failed, requested size too large or not enough memory?\n"); ++ + return client->frameBuffer?TRUE:FALSE; + } + diff --git a/SOURCES/LibVNCServer-0.9.10-CVE-2014-6053.patch b/SOURCES/LibVNCServer-0.9.10-CVE-2014-6053.patch new file mode 100644 index 0000000..4f59a7b --- /dev/null +++ b/SOURCES/LibVNCServer-0.9.10-CVE-2014-6053.patch @@ -0,0 +1,22 @@ +commit 6037a9074d52b1963c97cb28ea1096c7c14cbf28 +Author: Nicolas Ruff +Date: Mon Aug 18 15:16:16 2014 +0200 + + Check malloc() return value on client->server ClientCutText message. Client can send up to 2**32-1 bytes of text, and such a large allocation is likely to fail in case of high memory pressure. This would in a server crash (write at address 0). + +diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c +index 5f3b31d..7e43fe3 100644 +--- a/libvncserver/rfbserver.c ++++ b/libvncserver/rfbserver.c +@@ -2461,6 +2461,11 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) + msg.cct.length = Swap32IfLE(msg.cct.length); + + str = (char *)malloc(msg.cct.length); ++ if (str == NULL) { ++ rfbLogPerror("rfbProcessClientNormalMessage: not enough memory"); ++ rfbCloseClient(cl); ++ return; ++ } + + if ((n = rfbReadExact(cl, str, msg.cct.length)) <= 0) { + if (n != 0) diff --git a/SOURCES/LibVNCServer-0.9.10-CVE-2014-6054.patch b/SOURCES/LibVNCServer-0.9.10-CVE-2014-6054.patch new file mode 100644 index 0000000..b8225ac --- /dev/null +++ b/SOURCES/LibVNCServer-0.9.10-CVE-2014-6054.patch @@ -0,0 +1,38 @@ +commit 05a9bd41a8ec0a9d580a8f420f41718bdd235446 +Author: Nicolas Ruff +Date: Mon Aug 18 15:22:48 2014 +0200 + + Do not accept a scaling factor of zero on PalmVNCSetScaleFactor and SetScale client->server messages. This would cause a division by zero and crash the server. + +diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c +index 7e43fe3..df7d74c 100644 +--- a/libvncserver/rfbserver.c ++++ b/libvncserver/rfbserver.c +@@ -2491,6 +2491,13 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) + rfbCloseClient(cl); + return; + } ++ ++ if (msg.ssc.scale == 0) { ++ rfbLogPerror("rfbProcessClientNormalMessage: will not accept a scale factor of zero"); ++ rfbCloseClient(cl); ++ return; ++ } ++ + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg); + rfbLog("rfbSetScale(%d)\n", msg.ssc.scale); + rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale); +@@ -2507,6 +2514,13 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) + rfbCloseClient(cl); + return; + } ++ ++ if (msg.ssc.scale == 0) { ++ rfbLogPerror("rfbProcessClientNormalMessage: will not accept a scale factor of zero"); ++ rfbCloseClient(cl); ++ return; ++ } ++ + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg); + rfbLog("rfbSetScale(%d)\n", msg.ssc.scale); + rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale); diff --git a/SOURCES/LibVNCServer-0.9.10-CVE-2014-6055.patch b/SOURCES/LibVNCServer-0.9.10-CVE-2014-6055.patch new file mode 100644 index 0000000..bbcfc1c --- /dev/null +++ b/SOURCES/LibVNCServer-0.9.10-CVE-2014-6055.patch @@ -0,0 +1,165 @@ +commit 06ccdf016154fde8eccb5355613ba04c59127b2e +Author: Nicolas Ruff +Date: Mon Sep 1 14:36:26 2014 +0200 + + Fix multiple stack-based buffer overflows in file transfer feature + +diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c +index df7d74c..445331a 100644 +--- a/libvncserver/rfbserver.c ++++ b/libvncserver/rfbserver.c +@@ -1241,21 +1241,35 @@ typedef struct { + #define RFB_FILE_ATTRIBUTE_TEMPORARY 0x100 + #define RFB_FILE_ATTRIBUTE_COMPRESSED 0x800 + +-rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, char *path, char *unixPath) ++rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, /* in */ char *path, /* out */ char *unixPath, size_t unixPathMaxLen ) + { + int x; + char *home=NULL; + + FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE); + ++ /* ++ * Do not use strncpy() - truncating the file name would probably have undesirable side effects ++ * Instead check if destination buffer is big enough ++ */ ++ ++ if (strlen(path) >= unixPathMaxLen) ++ return FALSE; ++ + /* C: */ + if (path[0]=='C' && path[1]==':') ++ { + strcpy(unixPath, &path[2]); ++ } + else + { + home = getenv("HOME"); + if (home!=NULL) + { ++ /* Re-check buffer size */ ++ if ((strlen(path) + strlen(home) + 1) >= unixPathMaxLen) ++ return FALSE; ++ + strcpy(unixPath, home); + strcat(unixPath,"/"); + strcat(unixPath, path); +@@ -1293,7 +1307,8 @@ rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer) + FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE); + + /* Client thinks we are Winblows */ +- rfbFilenameTranslate2UNIX(cl, buffer, path); ++ if (!rfbFilenameTranslate2UNIX(cl, buffer, path, sizeof(path))) ++ return FALSE; + + if (DB) rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: \"%s\"->\"%s\"\n",buffer, path); + +@@ -1570,7 +1585,11 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con + /* add some space to the end of the buffer as we will be adding a timespec to it */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + /* The client requests a File */ +- rfbFilenameTranslate2UNIX(cl, buffer, filename1); ++ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1))) ++ { ++ if (buffer!=NULL) free(buffer); ++ return FALSE; ++ } + cl->fileTransfer.fd=open(filename1, O_RDONLY, 0744); + + /* +@@ -1685,7 +1704,11 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con + } + sizeHtmp = Swap32IfLE(sizeHtmp); + +- rfbFilenameTranslate2UNIX(cl, buffer, filename1); ++ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1))) ++ { ++ if (buffer!=NULL) free(buffer); ++ return FALSE; ++ } + + /* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */ + /* TODO: Delta Transfer */ +@@ -1814,7 +1837,12 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + switch (contentParam) { + case rfbCDirCreate: /* Client requests the creation of a directory */ +- rfbFilenameTranslate2UNIX(cl, buffer, filename1); ++ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1))) ++ { ++ if (buffer!=NULL) free(buffer); ++ return FALSE; ++ } ++ + retval = mkdir(filename1, 0755); + if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success")); + /* +@@ -1823,7 +1851,12 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con + if (buffer!=NULL) free(buffer); + return retval; + case rfbCFileDelete: /* Client requests the deletion of a file */ +- rfbFilenameTranslate2UNIX(cl, buffer, filename1); ++ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1))) ++ { ++ if (buffer!=NULL) free(buffer); ++ return FALSE; ++ } ++ + if (stat(filename1,&statbuf)==0) + { + if (S_ISDIR(statbuf.st_mode)) +@@ -1841,8 +1874,18 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con + { + /* Split into 2 filenames ('*' is a seperator) */ + *p = '\0'; +- rfbFilenameTranslate2UNIX(cl, buffer, filename1); +- rfbFilenameTranslate2UNIX(cl, p+1, filename2); ++ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1))) ++ { ++ if (buffer!=NULL) free(buffer); ++ return FALSE; ++ } ++ ++ if (!rfbFilenameTranslate2UNIX(cl, p+1, filename2, sizeof(filename2))) ++ { ++ if (buffer!=NULL) free(buffer); ++ return FALSE; ++ } ++ + retval = rename(filename1,filename2); + if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCFileRename(\"%s\"->\"%s\" -->> \"%s\"->\"%s\") %s\n", buffer, filename1, p+1, filename2, (retval==-1?"Failed":"Success")); + /* + +commit f528072216dec01cee7ca35d94e171a3b909e677 +Author: Nicolas Ruff +Date: Mon Sep 1 14:51:07 2014 +0200 + + Fix stack-based buffer overflow in rfbFileTransferOffer message, FileTime processing + +diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c +index 445331a..23532b0 100644 +--- a/libvncserver/rfbserver.c ++++ b/libvncserver/rfbserver.c +@@ -1683,16 +1683,17 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con + */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + +- /* Parse the FileTime */ ++ /* Parse the FileTime ++ * TODO: FileTime is actually never used afterwards ++ */ + p = strrchr(buffer, ','); + if (p!=NULL) { + *p = '\0'; +- strcpy(szFileTime, p+1); ++ strncpy(szFileTime, p+1, sizeof(szFileTime)); ++ szFileTime[sizeof(szFileTime)-1] = '\x00'; /* ensure NULL terminating byte is present, even if copy overflowed */ + } else + szFileTime[0]=0; + +- +- + /* Need to read in sizeHtmp */ + if ((n = rfbReadExact(cl, (char *)&sizeHtmp, 4)) <= 0) { + if (n != 0) diff --git a/SOURCES/LibVNCServer-0.9.9-CVE-2014-6052.patch b/SOURCES/LibVNCServer-0.9.9-CVE-2014-6052.patch new file mode 100644 index 0000000..c225758 --- /dev/null +++ b/SOURCES/LibVNCServer-0.9.9-CVE-2014-6052.patch @@ -0,0 +1,70 @@ +From 161a1d5c884f5d4c4be9522acbab8f16cb6fd7eb Mon Sep 17 00:00:00 2001 +From: newsoft +Date: Fri, 31 Oct 2014 12:46:28 +0100 +Subject: [PATCH] Check for MallocFrameBuffer() return value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If MallocFrameBuffer() returns FALSE, frame buffer pointer is left to +NULL. Subsequent writes into that buffer could lead to memory +corruption, or even arbitrary code execution. + +Signed-off-by: Petr Písař +--- + libvncclient/rfbproto.c | 10 +++++++--- + libvncclient/vncviewer.c | 3 ++- + 2 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c +index 3ecc011..beb87fc 100644 +--- a/libvncclient/rfbproto.c ++++ b/libvncclient/rfbproto.c +@@ -1807,7 +1807,8 @@ HandleRFBServerMessage(rfbClient* client) + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; +- client->MallocFrameBuffer(client); ++ if (!client->MallocFrameBuffer(client)) ++ return FALSE; + SendFramebufferUpdateRequest(client, 0, 0, rect.r.w, rect.r.h, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", rect.r.w, rect.r.h); + continue; +@@ -2260,7 +2261,8 @@ HandleRFBServerMessage(rfbClient* client) + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; +- client->MallocFrameBuffer(client); ++ if (!client->MallocFrameBuffer(client)) ++ return FALSE; + SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height); + break; +@@ -2276,7 +2278,9 @@ HandleRFBServerMessage(rfbClient* client) + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; +- client->MallocFrameBuffer(client); ++ if (!client->MallocFrameBuffer(client)) ++ return FALSE; ++ + SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height); + break; +diff --git a/libvncclient/vncviewer.c b/libvncclient/vncviewer.c +index b2cce2b..978a9a7 100644 +--- a/libvncclient/vncviewer.c ++++ b/libvncclient/vncviewer.c +@@ -243,7 +243,8 @@ static rfbBool rfbInitConnection(rfbClient* client) + + client->width=client->si.framebufferWidth; + client->height=client->si.framebufferHeight; +- client->MallocFrameBuffer(client); ++ if (!client->MallocFrameBuffer(client)) ++ return FALSE; + + if (!SetFormatAndEncodings(client)) + return FALSE; +-- +1.9.3 + diff --git a/SPECS/libvncserver.spec b/SPECS/libvncserver.spec index cd607e5..f76bbc3 100644 --- a/SPECS/libvncserver.spec +++ b/SPECS/libvncserver.spec @@ -6,7 +6,7 @@ Summary: Library to make writing a vnc server easy Name: libvncserver Version: 0.9.9 -Release: 9%{?dist} +Release: 9%{?dist}.1 # NOTE: --with-tightvnc-filetransfer => GPLv2 License: GPLv2+ Group: System Environment/Libraries @@ -20,6 +20,16 @@ Patch1: LibVNCServer-0.9.9-system_minilzo.patch Patch2: libvncserver-0.9.1-multilib.patch # pkgconfig love (upstreamable) Patch3: LibVNCServer-0.9.9-pkgconfig.patch +# Fix CVE-2014-6051, bug #1157670 +Patch4: LibVNCServer-0.9.10-CVE-2014-6051.patch +# Fix CVE-2014-6052, bug #1157670 +Patch5: LibVNCServer-0.9.9-CVE-2014-6052.patch +# Fix CVE-2014-6053, bug #1157670 +Patch6: LibVNCServer-0.9.10-CVE-2014-6053.patch +# Fix CVE-2014-6054, bug #1157670 +Patch7: LibVNCServer-0.9.10-CVE-2014-6054.patch +# Fix CVE-2014-6055, bug #1157670 +Patch8: LibVNCServer-0.9.10-CVE-2014-6055.patch # upstream name Obsoletes: LibVNCServer < 0.9.1 @@ -66,6 +76,11 @@ rm -f common/lzodefs.h common/lzoconf.h commmon/minilzo.h common/minilzo.c %endif %patch2 -p1 -b .multilib %patch3 -p1 -b .pkgconfig +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 # fix encoding for file in AUTHORS ChangeLog ; do @@ -134,6 +149,17 @@ rm -rf %{buildroot} %changelog +* Fri Oct 31 2014 Petr Pisar - 0.9.9-9.1 +- Fix CVE-2014-6051 (integer overflow in screen size handling) (bug #1157670) +- Fix CVE-2014-6052 (NULL pointer dereference in framebuffer setup) + (bug #1157670) +- Fix CVE-2014-6053 (NULL pointer dereference in ClientCutText message + handling) (bug #1157670) +- Fix CVE-2014-6054 (server divide-by-zero in scaling factor handling) + (bug #1157670) +- Fix CVE-2014-6055 (server stacked-based buffer overflow in file transfer + handling) (bug #1157670) + * Fri Jan 24 2014 Daniel Mach - 0.9.9-9 - Mass rebuild 2014-01-24