From 69627985551482e085150d040ba6f64dea96f383 Mon Sep 17 00:00:00 2001 From: Sebastien BALLET Date: Wed, 1 Jun 2016 07:41:44 +0700 Subject: system/p7zip: Add security patches. CVE-2015-1038 CVE-2016-2335. Signed-off-by: Willy Sudiarto Raharjo --- system/p7zip/CVE-2015-1038.patch | 292 +++++++++++++++++++++++++++++++++++++++ system/p7zip/CVE-2016-2335.patch | 17 +++ system/p7zip/p7zip.SlackBuild | 21 ++- 3 files changed, 327 insertions(+), 3 deletions(-) create mode 100644 system/p7zip/CVE-2015-1038.patch create mode 100644 system/p7zip/CVE-2016-2335.patch (limited to 'system/p7zip') diff --git a/system/p7zip/CVE-2015-1038.patch b/system/p7zip/CVE-2015-1038.patch new file mode 100644 index 0000000000..d0df4b4a98 --- /dev/null +++ b/system/p7zip/CVE-2015-1038.patch @@ -0,0 +1,292 @@ +--- a/CPP/7zip/UI/Agent/Agent.cpp ++++ b/CPP/7zip/UI/Agent/Agent.cpp +@@ -424,6 +424,8 @@ STDMETHODIMP CAgentFolder::Extract(const + CMyComPtr extractCallback = extractCallbackSpec; + UStringVector pathParts; + CProxyFolder *currentProxyFolder = _proxyFolderItem; ++ HRESULT res; ++ + while (currentProxyFolder->Parent) + { + pathParts.Insert(0, currentProxyFolder->Name); +@@ -445,8 +447,11 @@ STDMETHODIMP CAgentFolder::Extract(const + (UInt64)(Int64)-1); + CUIntVector realIndices; + GetRealIndices(indices, numItems, realIndices); +- return _agentSpec->GetArchive()->Extract(&realIndices.Front(), ++ res = _agentSpec->GetArchive()->Extract(&realIndices.Front(), + realIndices.Size(), testMode, extractCallback); ++ if (res == S_OK && !extractCallbackSpec->CreateSymLinks()) ++ res = E_FAIL; ++ return res; + COM_TRY_END + } + +--- a/CPP/7zip/UI/Agent/ArchiveFolder.cpp ++++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp +@@ -20,6 +20,8 @@ STDMETHODIMP CAgentFolder::CopyTo(const + CMyComPtr extractCallback = extractCallbackSpec; + UStringVector pathParts; + CProxyFolder *currentProxyFolder = _proxyFolderItem; ++ HRESULT res; ++ + while (currentProxyFolder->Parent) + { + pathParts.Insert(0, currentProxyFolder->Name); +@@ -46,8 +48,11 @@ STDMETHODIMP CAgentFolder::CopyTo(const + (UInt64)(Int64)-1); + CUIntVector realIndices; + GetRealIndices(indices, numItems, realIndices); +- return _agentSpec->GetArchive()->Extract(&realIndices.Front(), ++ res = _agentSpec->GetArchive()->Extract(&realIndices.Front(), + realIndices.Size(), BoolToInt(false), extractCallback); ++ if (res == S_OK && !extractCallbackSpec->CreateSymLinks()) ++ res = E_FAIL; ++ return res; + COM_TRY_END + } + +--- a/CPP/7zip/UI/Client7z/Client7z.cpp ++++ b/CPP/7zip/UI/Client7z/Client7z.cpp +@@ -197,8 +197,11 @@ private: + COutFileStream *_outFileStreamSpec; + CMyComPtr _outFileStream; + ++ CObjectVector _delayedSymLinks; ++ + public: + void Init(IInArchive *archiveHandler, const UString &directoryPath); ++ bool CreateSymLinks(); + + UInt64 NumErrors; + bool PasswordIsDefined; +@@ -392,11 +395,22 @@ STDMETHODIMP CArchiveExtractCallback::Se + } + _outFileStream.Release(); + if (_extractMode && _processedFileInfo.AttribDefined) +- NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib); ++ NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib, &_delayedSymLinks); + PrintNewLine(); + return S_OK; + } + ++bool CArchiveExtractCallback::CreateSymLinks() ++{ ++ bool success = true; ++ ++ for (int i = 0; i != _delayedSymLinks.Size(); ++i) ++ success &= _delayedSymLinks[i].Create(); ++ ++ _delayedSymLinks.Clear(); ++ ++ return success; ++} + + STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) + { +--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp ++++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +@@ -453,12 +453,24 @@ STDMETHODIMP CArchiveExtractCallback::Se + NumFiles++; + + if (_extractMode && _fi.AttribDefined) +- NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib); ++ NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib, &_delayedSymLinks); + RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); + return S_OK; + COM_TRY_END + } + ++bool CArchiveExtractCallback::CreateSymLinks() ++{ ++ bool success = true; ++ ++ for (int i = 0; i != _delayedSymLinks.Size(); ++i) ++ success &= _delayedSymLinks[i].Create(); ++ ++ _delayedSymLinks.Clear(); ++ ++ return success; ++} ++ + /* + STDMETHODIMP CArchiveExtractCallback::GetInStream( + const wchar_t *name, ISequentialInStream **inStream) +--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h ++++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h +@@ -6,6 +6,8 @@ + #include "Common/MyCom.h" + #include "Common/Wildcard.h" + ++#include "Windows/FileDir.h" ++ + #include "../../IPassword.h" + + #include "../../Common/FileStreams.h" +@@ -83,6 +85,8 @@ class CArchiveExtractCallback: + UInt64 _packTotal; + UInt64 _unpTotal; + ++ CObjectVector _delayedSymLinks; ++ + void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); + HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); + HRESULT GetUnpackSize(); +@@ -138,6 +142,7 @@ public: + const UStringVector &removePathParts, + UInt64 packSize); + ++ bool CreateSymLinks(); + }; + + #endif +--- a/CPP/7zip/UI/Common/Extract.cpp ++++ b/CPP/7zip/UI/Common/Extract.cpp +@@ -96,6 +96,9 @@ static HRESULT DecompressArchive( + else + result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec); + ++ if (result == S_OK && !extractCallbackSpec->CreateSymLinks()) ++ result = E_FAIL; ++ + return callback->ExtractResult(result); + } + +--- a/CPP/Windows/FileDir.cpp ++++ b/CPP/Windows/FileDir.cpp +@@ -453,9 +453,10 @@ bool SetDirTime(LPCWSTR fileName, const + } + + #ifndef _UNICODE +-bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) ++bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes, ++ CObjectVector *delayedSymLinks) + { +- return MySetFileAttributes(UnicodeStringToMultiByte(fileName, CP_ACP), fileAttributes); ++ return MySetFileAttributes(UnicodeStringToMultiByte(fileName, CP_ACP), fileAttributes, delayedSymLinks); + } + + bool MyRemoveDirectory(LPCWSTR pathName) +@@ -488,7 +489,8 @@ static int convert_to_symlink(const char + return -1; + } + +-bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) ++bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes, ++ CObjectVector *delayedSymLinks) + { + if (!fileName) { + SetLastError(ERROR_PATH_NOT_FOUND); +@@ -520,7 +522,9 @@ bool MySetFileAttributes(LPCTSTR fileNam + stat_info.st_mode = fileAttributes >> 16; + #ifdef ENV_HAVE_LSTAT + if (S_ISLNK(stat_info.st_mode)) { +- if ( convert_to_symlink(name) != 0) { ++ if (delayedSymLinks) ++ delayedSymLinks->Add(CDelayedSymLink(name)); ++ else if ( convert_to_symlink(name) != 0) { + TRACEN((printf("MySetFileAttributes(%s,%d) : false-3\n",name,fileAttributes))) + return false; + } +@@ -924,4 +928,41 @@ bool CTempDirectory::Create(LPCTSTR pref + } + + ++#ifdef ENV_UNIX ++ ++CDelayedSymLink::CDelayedSymLink(LPCSTR source) ++ : _source(source) ++{ ++ struct stat st; ++ ++ if (lstat(_source, &st) == 0) { ++ _dev = st.st_dev; ++ _ino = st.st_ino; ++ } else { ++ _dev = 0; ++ } ++} ++ ++bool CDelayedSymLink::Create() ++{ ++ struct stat st; ++ ++ if (_dev == 0) { ++ errno = EPERM; ++ return false; ++ } ++ if (lstat(_source, &st) != 0) ++ return false; ++ if (_dev != st.st_dev || _ino != st.st_ino) { ++ // Placeholder file has been overwritten or moved by another ++ // symbolic link creation ++ errno = EPERM; ++ return false; ++ } ++ ++ return convert_to_symlink(_source) == 0; ++} ++ ++#endif // ENV_UNIX ++ + }}} +--- a/CPP/Windows/FileDir.h ++++ b/CPP/Windows/FileDir.h +@@ -4,6 +4,7 @@ + #define __WINDOWS_FILEDIR_H + + #include "../Common/MyString.h" ++#include "../Common/MyVector.h" + #include "Defs.h" + + /* GetFullPathName for 7zAES.cpp */ +@@ -13,11 +14,15 @@ namespace NWindows { + namespace NFile { + namespace NDirectory { + ++class CDelayedSymLink; ++ + bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); + +-bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); ++bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes, ++ CObjectVector *delayedSymLinks = 0); + #ifndef _UNICODE +-bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); ++bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes, ++ CObjectVector *delayedSymLinks = 0); + #endif + + bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); +@@ -80,6 +85,31 @@ public: + bool Remove(); + }; + ++// Symbolic links must be created last so that they can't be used to ++// create or overwrite files above the extraction directory. ++class CDelayedSymLink ++{ ++#ifdef ENV_UNIX ++ // Where the symlink should be created. The target is specified in ++ // the placeholder file. ++ AString _source; ++ ++ // Device and inode of the placeholder file. Before creating the ++ // symlink, we must check that these haven't been changed by creation ++ // of another symlink. ++ dev_t _dev; ++ ino_t _ino; ++ ++public: ++ explicit CDelayedSymLink(LPCSTR source); ++ bool Create(); ++#else // !ENV_UNIX ++public: ++ CDelayedSymLink(LPCSTR source) {} ++ bool Create() { return true; } ++#endif // ENV_UNIX ++}; ++ + #ifdef _UNICODE + typedef CTempFile CTempFileW; + #endif diff --git a/system/p7zip/CVE-2016-2335.patch b/system/p7zip/CVE-2016-2335.patch new file mode 100644 index 0000000000..a00d6a3862 --- /dev/null +++ b/system/p7zip/CVE-2016-2335.patch @@ -0,0 +1,17 @@ +Index: p7zip_15.14.1/CPP/7zip/Archive/Udf/UdfIn.cpp +=================================================================== +--- p7zip_15.14.1.orig/CPP/7zip/Archive/Udf/UdfIn.cpp ++++ p7zip_15.14.1/CPP/7zip/Archive/Udf/UdfIn.cpp +@@ -389,7 +389,11 @@ HRESULT CInArchive::ReadFileItem(int vol + return S_FALSE; + CFile &file = Files.Back(); + const CLogVol &vol = LogVols[volIndex]; +- CPartition &partition = Partitions[vol.PartitionMaps[lad.Location.PartitionRef].PartitionIndex]; ++ unsigned partitionRef = lad.Location.PartitionRef; ++ ++ if (partitionRef >= vol.PartitionMaps.Size()) ++ return S_FALSE; ++ CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex]; + + UInt32 key = lad.Location.Pos; + UInt32 value; diff --git a/system/p7zip/p7zip.SlackBuild b/system/p7zip/p7zip.SlackBuild index d2753aa927..e9eb5b372c 100644 --- a/system/p7zip/p7zip.SlackBuild +++ b/system/p7zip/p7zip.SlackBuild @@ -23,8 +23,8 @@ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PRGNAM=p7zip -VERSION=9.20.1 -BUILD=${BUILD:-1} +VERSION=${VERSION:-9.20.1} +BUILD=${BUILD:-2} TAG=${TAG:-_SBo} if [ -z "$ARCH" ]; then @@ -70,7 +70,22 @@ find -L . \ \( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \ -o -perm 511 \) -exec chmod 755 {} \; -o \ \( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \ - -o -perm 440 -o -perm 400 \) -exec chmod 644 {} \; + -o -perm 440 -o -perm 400 \) -exec chmod 644 {} \; + +# patch to fix security issues : +# +# CVE-2015-1038: +# p7zip 9.20.1 allows remote attackers to write to arbitrary files via a symlink attack in an archive. +# https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-1038 +# https://sourceforge.net/p/p7zip/bugs/147/#2f9c +# +# CVE-2016-2335: +# 7zip UDF CInArchive::ReadFileItem Code Execution Vulnerability +# http://www.talosintel.com/reports/TALOS-2016-0094/ +# https://sourceforge.net/p/p7zip/discussion/383043/thread/9d0fb86b/#1dba +# +patch -Np1 < $CWD/CVE-2015-1038.patch +patch -Np1 < $CWD/CVE-2016-2335.patch make all3 \ OPTFLAGS="$SLKCFLAGS" \ -- cgit v1.2.3-65-gdbad