aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastien BALLET <slacker6896@gmail.com>2016-06-01 07:41:44 +0700
committerWilly Sudiarto Raharjo <willysr@slackbuilds.org>2016-06-01 07:42:13 +0700
commit69627985551482e085150d040ba6f64dea96f383 (patch)
tree30390e1e4a12ef90198d5b01a25bec33fdd0b8b6
parenta3356a223185926992cc7cadabb0afd9db401a3d (diff)
system/p7zip: Add security patches.
CVE-2015-1038 CVE-2016-2335. Signed-off-by: Willy Sudiarto Raharjo <willysr@slackbuilds.org>
-rw-r--r--system/p7zip/CVE-2015-1038.patch292
-rw-r--r--system/p7zip/CVE-2016-2335.patch17
-rw-r--r--system/p7zip/p7zip.SlackBuild21
3 files changed, 327 insertions, 3 deletions
diff --git a/system/p7zip/CVE-2015-1038.patch b/system/p7zip/CVE-2015-1038.patch
new file mode 100644
index 0000000000000..d0df4b4a980dd
--- /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<IArchiveExtractCallback> 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<IArchiveExtractCallback> 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<ISequentialOutStream> _outFileStream;
+
++ CObjectVector<NWindows::NFile::NDirectory::CDelayedSymLink> _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<NWindows::NFile::NDirectory::CDelayedSymLink> _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<CDelayedSymLink> *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<CDelayedSymLink> *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<CDelayedSymLink> *delayedSymLinks = 0);
+ #ifndef _UNICODE
+-bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes);
++bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes,
++ CObjectVector<CDelayedSymLink> *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 0000000000000..a00d6a3862d79
--- /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 d2753aa9277a9..e9eb5b372c115 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" \