diff options
Diffstat (limited to 'package/libvncserver/libvncserver-0004-CVE-2014-6055.patch')
-rw-r--r-- | package/libvncserver/libvncserver-0004-CVE-2014-6055.patch | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/package/libvncserver/libvncserver-0004-CVE-2014-6055.patch b/package/libvncserver/libvncserver-0004-CVE-2014-6055.patch new file mode 100644 index 0000000000..2a6ee76ae3 --- /dev/null +++ b/package/libvncserver/libvncserver-0004-CVE-2014-6055.patch @@ -0,0 +1,150 @@ +Description: fix denial of service and possible code execution via + stack overflows in File Transfer feature +Origin: backport, https://github.com/newsoft/libvncserver/commit/06ccdf016154fde8eccb5355613ba04c59127b2e +Origin: backport, https://github.com/newsoft/libvncserver/commit/f528072216dec01cee7ca35d94e171a3b909e677 +Origin: backport, https://github.com/newsoft/libvncserver/commit/256964b884c980038cd8b2f0d180fbb295b1c748 + +Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar> + +Index: libvncserver-0.9.9+dfsg/libvncserver/rfbserver.c +=================================================================== +--- libvncserver-0.9.9+dfsg.orig/libvncserver/rfbserver.c 2014-09-25 11:20:22.972070915 -0400 ++++ libvncserver-0.9.9+dfsg/libvncserver/rfbserver.c 2014-09-25 11:20:40.368071381 -0400 +@@ -1237,21 +1237,35 @@ + #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); +@@ -1289,7 +1303,8 @@ + 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); + +@@ -1566,7 +1581,9 @@ + /* 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))) ++ goto fail; ++ + cl->fileTransfer.fd=open(filename1, O_RDONLY, 0744); + + /* +@@ -1660,16 +1677,17 @@ + */ + 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) +@@ -1681,7 +1699,8 @@ + } + sizeHtmp = Swap32IfLE(sizeHtmp); + +- rfbFilenameTranslate2UNIX(cl, buffer, filename1); ++ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1))) ++ goto fail; + + /* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */ + /* TODO: Delta Transfer */ +@@ -1810,7 +1829,9 @@ + 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))) ++ goto fail; ++ + retval = mkdir(filename1, 0755); + if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success")); + /* +@@ -1819,7 +1840,9 @@ + 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))) ++ goto fail; ++ + if (stat(filename1,&statbuf)==0) + { + if (S_ISDIR(statbuf.st_mode)) +@@ -1837,8 +1860,12 @@ + { + /* 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))) ++ goto fail; ++ ++ if (!rfbFilenameTranslate2UNIX(cl, p+1, filename2, sizeof(filename2))) ++ goto fail; ++ + 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")); + /* +@@ -1858,6 +1885,10 @@ + /* NOTE: don't forget to free(buffer) if you return early! */ + if (buffer!=NULL) free(buffer); + return TRUE; ++ ++fail: ++ if (buffer!=NULL) free(buffer); ++ return FALSE; + } + + /* |