summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app-arch/p7zip/files')
-rw-r--r--app-arch/p7zip/files/9.04-makefile.patch19
-rw-r--r--app-arch/p7zip/files/p7zip73
-rw-r--r--app-arch/p7zip/files/p7zip-9.20.1-CVE-2015-1038.patch315
-rw-r--r--app-arch/p7zip/files/p7zip-9.20.1-QA.patch17
-rw-r--r--app-arch/p7zip/files/p7zip-9.20.1-execstack.patch24
-rw-r--r--app-arch/p7zip/files/p7zip-9.20.1-long_rar_pwd.patch17
-rw-r--r--app-arch/p7zip/files/p7zip-9.38.1-CVE-2015-1038.patch283
-rw-r--r--app-arch/p7zip/files/p7zip-9.38.1-osversion.patch28
8 files changed, 776 insertions, 0 deletions
diff --git a/app-arch/p7zip/files/9.04-makefile.patch b/app-arch/p7zip/files/9.04-makefile.patch
new file mode 100644
index 000000000000..93a99cc9014f
--- /dev/null
+++ b/app-arch/p7zip/files/9.04-makefile.patch
@@ -0,0 +1,19 @@
+--- p7zip_9.04/CPP/7zip/Bundles/Format7zFree/makefile.orig 2010-01-04 13:58:54.527887746 +0100
++++ p7zip_9.04/CPP/7zip/Bundles/Format7zFree/makefile 2010-01-04 13:59:10.290868343 +0100
+@@ -247,8 +247,6 @@
+ MyAes.o \
+ Pbkdf2HmacSha1.o \
+ RandGen.o \
+- Rar20Crypto.o \
+- RarAes.o \
+ Sha1.o \
+ WzAes.o \
+ ZipCrypto.o \
+@@ -298,7 +296,6 @@
+ $(HFS_OBJS) \
+ $(ISO_OBJS) \
+ $(NSIS_OBJS) \
+- $(RAR_OBJS) \
+ $(TAR_OBJS) \
+ $(UDF_OBJS) \
+ $(WIM_OBJS) \
diff --git a/app-arch/p7zip/files/p7zip b/app-arch/p7zip/files/p7zip
new file mode 100644
index 000000000000..9aaf078cbe00
--- /dev/null
+++ b/app-arch/p7zip/files/p7zip
@@ -0,0 +1,73 @@
+#!/bin/bash
+# gzip-like CLI wrapper for p7zip
+set -e
+
+compress=true
+file=
+
+usage ()
+ {
+ echo "Usage: $0 [-d] [-h|--help] [file]"
+ exit 1
+ }
+
+while [ "$#" != "0" ] ; do
+ case "$1" in
+ -d) compress=false ;;
+ -c) echo "$0: ignoring $1 option (not yet implemented)" ;;
+ -h|--help) usage ;;
+ *)
+ if [ "${file}" = "" ] ; then
+ file="$1"
+ else
+ usage
+ fi
+ ;;
+ esac
+ shift
+done
+
+# make sure they're present, before we screw up
+for i in mktemp 7z rm cat tty ; do
+ if ! which $i > /dev/null ; then
+ echo "$0: $i: command not found"
+ exit 1
+ fi
+done
+
+if [ "${file}" != "" ] ; then
+ if ${compress} ; then
+ 7z a ${file}.7z ${file}
+ rm ${file}
+ else
+ case ${file} in
+ *.7z)
+ 7z x ${file}
+ rm ${file}
+ ;;
+ *)
+ echo "$0: ${file}: unknown suffix -- ignored"
+ ;;
+ esac
+ fi
+ exit 0
+fi
+
+tmp=`mktemp`
+trap "rm -f ${tmp}" 0
+
+if ${compress} ; then
+ if tty > /dev/null ; then
+ echo "$0: compressed data not written to a terminal."
+ echo "For help, type: $0 -h"
+ exit 1
+ fi
+ rm -f ${tmp}
+ 7z a ${tmp} -si >/dev/null
+ cat ${tmp}
+else
+ cat > ${tmp}
+ 7z x ${tmp} -so 2>/dev/null | cat
+fi
+
+rm -f ${tmp}
diff --git a/app-arch/p7zip/files/p7zip-9.20.1-CVE-2015-1038.patch b/app-arch/p7zip/files/p7zip-9.20.1-CVE-2015-1038.patch
new file mode 100644
index 000000000000..09dd0f29cce7
--- /dev/null
+++ b/app-arch/p7zip/files/p7zip-9.20.1-CVE-2015-1038.patch
@@ -0,0 +1,315 @@
+Author: Ben Hutchings <ben@decadent.org.uk>
+Date: Tue, 19 May 2015 02:38:40 +0100
+Description: Delay creation of symlinks to prevent arbitrary file writes (CVE-2015-1038)
+Bug: http://sourceforge.net/p/p7zip/bugs/147/
+Bug-Debian: https://bugs.debian.org/774660
+
+Alexander Cherepanov discovered that 7zip is susceptible to a
+directory traversal vulnerability. While extracting an archive, it
+will extract symlinks and then follow them if they are referenced in
+further entries. This can be exploited by a rogue archive to write
+files outside the current directory.
+
+We have to create placeholder files (which we already do) and delay
+creating symlinks until the end of extraction.
+
+Due to the possibility of anti-items (deletions) in the archive, it is
+possible for placeholders to be deleted and replaced before we create
+the symlinks. It's not clear that this can be used for mischief, but
+GNU tar guards against similar problems by checking that the placeholder
+still exists and is the same inode. XXX It also checks 'birth time' but
+this isn't portable. We can probably get away with comparing ctime
+since we don't support hard links.
+
+--- 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/app-arch/p7zip/files/p7zip-9.20.1-QA.patch b/app-arch/p7zip/files/p7zip-9.20.1-QA.patch
new file mode 100644
index 000000000000..8845aca20707
--- /dev/null
+++ b/app-arch/p7zip/files/p7zip-9.20.1-QA.patch
@@ -0,0 +1,17 @@
+From: Julian Ospald <hasufell@gentoo.org>
+Date: Thu Jun 7 14:31:12 UTC 2012
+Subject: fix QA warnings
+
+https://sourceforge.net/tracker/?func=detail&atid=660493&aid=3532590&group_id=111810
+
+--- CPP/7zip/Archive/NtfsHandler.cpp
++++ CPP/7zip/Archive/NtfsHandler.cpp
+@@ -1280,7 +1280,7 @@
+ if (recSizeLog < Header.SectorSizeLog)
+ return false;
+ numSectorsInRec = 1 << (recSizeLog - Header.SectorSizeLog);
+- if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, NULL, 0))
++ if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, 0, NULL))
+ return S_FALSE;
+ if (!mftRec.IsFILE())
+ return S_FALSE;
diff --git a/app-arch/p7zip/files/p7zip-9.20.1-execstack.patch b/app-arch/p7zip/files/p7zip-9.20.1-execstack.patch
new file mode 100644
index 000000000000..1fdff481cf36
--- /dev/null
+++ b/app-arch/p7zip/files/p7zip-9.20.1-execstack.patch
@@ -0,0 +1,24 @@
+diff -Naupr p7zip_9.20.1.orig/Asm/x64/7zCrcT8U.asm p7zip_9.20.1/Asm/x64/7zCrcT8U.asm
+--- p7zip_9.20.1.orig/Asm/x64/7zCrcT8U.asm 2008-08-14 11:18:07.000000000 +0200
++++ p7zip_9.20.1/Asm/x64/7zCrcT8U.asm 2011-07-26 17:43:57.727910278 +0200
+@@ -101,3 +101,8 @@ _CrcUpdateT8:
+ ret
+
+ end
++
++%ifidn __OUTPUT_FORMAT__,elf
++section .note.GNU-stack noalloc noexec nowrite progbits
++%endif
++
+diff -Naupr p7zip_9.20.1.orig/Asm/x86/7zCrcT8U.asm p7zip_9.20.1/Asm/x86/7zCrcT8U.asm
+--- p7zip_9.20.1.orig/Asm/x86/7zCrcT8U.asm 2009-07-14 12:44:15.000000000 +0200
++++ p7zip_9.20.1/Asm/x86/7zCrcT8U.asm 2011-07-26 17:44:23.938864508 +0200
+@@ -99,3 +99,8 @@ _CrcUpdateT8:
+
+
+ ; end
++
++%ifidn __OUTPUT_FORMAT__,elf
++section .note.GNU-stack noalloc noexec nowrite progbits
++%endif
++
diff --git a/app-arch/p7zip/files/p7zip-9.20.1-long_rar_pwd.patch b/app-arch/p7zip/files/p7zip-9.20.1-long_rar_pwd.patch
new file mode 100644
index 000000000000..ea7a90b71d44
--- /dev/null
+++ b/app-arch/p7zip/files/p7zip-9.20.1-long_rar_pwd.patch
@@ -0,0 +1,17 @@
+--- ./CPP/7zip/Crypto/Sha1.cpp 2010-10-20 06:56:08.000000000 +0200
++++ CPP/7zip/Crypto/Sha1.cpp.new 2013-09-15 09:19:51.000000000 +0200
+@@ -148,10 +148,10 @@
+ for (int i = 0; i < kBlockSizeInWords; i++)
+ {
+ UInt32 d = _buffer[i];
+- data[i * 4 + 0 - kBlockSize] = (Byte)(d);
+- data[i * 4 + 1 - kBlockSize] = (Byte)(d >> 8);
+- data[i * 4 + 2 - kBlockSize] = (Byte)(d >> 16);
+- data[i * 4 + 3 - kBlockSize] = (Byte)(d >> 24);
++ data[(int)i * 4 + 0 - (int)kBlockSize] = (Byte)(d);
++ data[(int)i * 4 + 1 - (int)kBlockSize] = (Byte)(d >> 8);
++ data[(int)i * 4 + 2 - (int)kBlockSize] = (Byte)(d >> 16);
++ data[(int)i * 4 + 3 - (int)kBlockSize] = (Byte)(d >> 24);
+ }
+ returnRes = rar350Mode;
+ }
diff --git a/app-arch/p7zip/files/p7zip-9.38.1-CVE-2015-1038.patch b/app-arch/p7zip/files/p7zip-9.38.1-CVE-2015-1038.patch
new file mode 100644
index 000000000000..c4e443679b05
--- /dev/null
+++ b/app-arch/p7zip/files/p7zip-9.38.1-CVE-2015-1038.patch
@@ -0,0 +1,283 @@
+Author: Ben Hutchings <ben@decadent.org.uk>
+Date: Tue, 19 May 2015 02:38:40 +0100
+Description: Delay creation of symlinks to prevent arbitrary file writes (CVE-2015-1038)
+Bug: http://sourceforge.net/p/p7zip/bugs/147/
+Bug-Debian: https://bugs.debian.org/774660
+
+Alexander Cherepanov discovered that 7zip is susceptible to a
+directory traversal vulnerability. While extracting an archive, it
+will extract symlinks and then follow them if they are referenced in
+further entries. This can be exploited by a rogue archive to write
+files outside the current directory.
+
+We have to create placeholder files (which we already do) and delay
+creating symlinks until the end of extraction.
+
+Due to the possibility of anti-items (deletions) in the archive, it is
+possible for placeholders to be deleted and replaced before we create
+the symlinks. It's not clear that this can be used for mischief, but
+GNU tar guards against similar problems by checking that the placeholder
+still exists and is the same inode. XXX It also checks 'birth time' but
+this isn't portable. We can probably get away with comparing ctime
+since we don't support hard links.
+
+--- a/CPP/7zip/UI/Agent/Agent.cpp
++++ b/CPP/7zip/UI/Agent/Agent.cpp
+@@ -1215,7 +1215,7 @@ STDMETHODIMP CAgentFolder::Extract(const
+ HRESULT result = _agentSpec->GetArchive()->Extract(&realIndices.Front(),
+ realIndices.Size(), testMode, extractCallback);
+ if (result == S_OK)
+- result = extractCallbackSpec->SetDirsTimes();
++ result = extractCallbackSpec->SetFinalAttribs();
+ return result;
+ COM_TRY_END
+ }
+--- a/CPP/7zip/UI/Client7z/Client7z.cpp
++++ b/CPP/7zip/UI/Client7z/Client7z.cpp
+@@ -222,8 +222,11 @@ private:
+ COutFileStream *_outFileStreamSpec;
+ CMyComPtr<ISequentialOutStream> _outFileStream;
+
++ CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks;
++
+ public:
+ void Init(IInArchive *archiveHandler, const FString &directoryPath);
++ HRESULT SetFinalAttribs();
+
+ UInt64 NumErrors;
+ bool PasswordIsDefined;
+@@ -441,11 +444,23 @@ STDMETHODIMP CArchiveExtractCallback::Se
+ }
+ _outFileStream.Release();
+ if (_extractMode && _processedFileInfo.AttribDefined)
+- SetFileAttrib(_diskFilePath, _processedFileInfo.Attrib);
++ SetFileAttrib(_diskFilePath, _processedFileInfo.Attrib, &_delayedSymLinks);
+ PrintNewLine();
+ return S_OK;
+ }
+
++HRESULT CArchiveExtractCallback::SetFinalAttribs()
++{
++ HRESULT result = S_OK;
++
++ for (int i = 0; i != _delayedSymLinks.Size(); ++i)
++ if (!_delayedSymLinks[i].Create())
++ result = E_FAIL;
++
++ _delayedSymLinks.Clear();
++
++ return result;
++}
+
+ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
+ {
+@@ -912,6 +927,8 @@ int MY_CDECL main(int numArgs, const cha
+ // extractCallbackSpec->PasswordIsDefined = true;
+ // extractCallbackSpec->Password = L"1";
+ HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback);
++ if (result == S_OK)
++ result = extractCallbackSpec->SetFinalAttribs();
+ if (result != S_OK)
+ {
+ PrintError("Extract Error");
+--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
++++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+@@ -1083,7 +1083,7 @@ STDMETHODIMP CArchiveExtractCallback::Se
+ NumFiles++;
+
+ if (_extractMode && _fi.AttribDefined)
+- SetFileAttrib(_diskFilePath, _fi.Attrib);
++ SetFileAttrib(_diskFilePath, _fi.Attrib, &_delayedSymLinks);
+ RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));
+ return S_OK;
+ COM_TRY_END
+@@ -1149,8 +1149,9 @@ static int GetNumSlashes(const FChar *s)
+ }
+ }
+
+-HRESULT CArchiveExtractCallback::SetDirsTimes()
++HRESULT CArchiveExtractCallback::SetFinalAttribs()
+ {
++ HRESULT result = S_OK;
+ CRecordVector<CExtrRefSortPair> pairs;
+ pairs.ClearAndSetSize(_extractedFolderPaths.Size());
+ unsigned i;
+@@ -1187,5 +1188,12 @@ HRESULT CArchiveExtractCallback::SetDirs
+ (WriteATime && ATimeDefined) ? &ATime : NULL,
+ (WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
+ }
+- return S_OK;
++
++ for (int i = 0; i != _delayedSymLinks.Size(); ++i)
++ if (!_delayedSymLinks[i].Create())
++ result = E_FAIL;
++
++ _delayedSymLinks.Clear();
++
++ return result;
+ }
+--- 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"
+@@ -213,6 +215,8 @@ class CArchiveExtractCallback:
+ bool _saclEnabled;
+ #endif
+
++ CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks;
++
+ void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
+ HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
+ HRESULT GetUnpackSize();
+@@ -293,7 +297,7 @@ public:
+ _baseParentFolder = indexInArc;
+ }
+
+- HRESULT SetDirsTimes();
++ HRESULT SetFinalAttribs();
+ };
+
+ #endif
+--- a/CPP/7zip/UI/Common/Extract.cpp
++++ b/CPP/7zip/UI/Common/Extract.cpp
+@@ -170,7 +170,7 @@ static HRESULT DecompressArchive(
+ else
+ result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs);
+ if (result == S_OK && !options.StdInMode)
+- result = ecs->SetDirsTimes();
++ result = ecs->SetFinalAttribs();
+ return callback->ExtractResult(result);
+ }
+
+--- a/CPP/Windows/FileDir.cpp
++++ b/CPP/Windows/FileDir.cpp
+@@ -343,7 +343,8 @@ static int convert_to_symlink(const char
+ return -1;
+ }
+
+-bool SetFileAttrib(CFSTR fileName, DWORD fileAttributes)
++bool SetFileAttrib(CFSTR fileName, DWORD fileAttributes,
++ CObjectVector<CDelayedSymLink> *delayedSymLinks)
+ {
+ if (!fileName) {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+@@ -375,7 +376,9 @@ bool SetFileAttrib(CFSTR fileName, DWORD
+ 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("SetFileAttrib(%s,%d) : false-3\n",(const char *)name,fileAttributes)))
+ return false;
+ }
+@@ -885,6 +888,43 @@ bool CTempDir::Remove()
+ return !_mustBeDeleted;
+ }
+
++#ifdef ENV_UNIX
++
++CDelayedSymLink::CDelayedSymLink(const char * 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_FILE_DIR_H
+
+ #include "../Common/MyString.h"
++#include "../Common/MyVector.h"
+
+ #include "FileIO.h"
+
+@@ -11,11 +12,14 @@ namespace NWindows {
+ namespace NFile {
+ namespace NDir {
+
++class CDelayedSymLink;
++
+ bool GetWindowsDir(FString &path);
+ bool GetSystemDir(FString &path);
+
+ bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);
+-bool SetFileAttrib(CFSTR path, DWORD attrib);
++bool SetFileAttrib(CFSTR path, DWORD attrib,
++ CObjectVector<CDelayedSymLink> *delayedSymLinks = 0);
+ bool MyMoveFile(CFSTR existFileName, CFSTR newFileName);
+
+ #ifndef UNDER_CE
+@@ -69,6 +73,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(const char * source);
++ bool Create();
++#else // !ENV_UNIX
++public:
++ CDelayedSymLink(const char * source) {}
++ bool Create() { return true; }
++#endif // ENV_UNIX
++};
++
+ #if !defined(UNDER_CE)
+ class CCurrentDirRestorer
+ {
diff --git a/app-arch/p7zip/files/p7zip-9.38.1-osversion.patch b/app-arch/p7zip/files/p7zip-9.38.1-osversion.patch
new file mode 100644
index 000000000000..49e0653e43ef
--- /dev/null
+++ b/app-arch/p7zip/files/p7zip-9.38.1-osversion.patch
@@ -0,0 +1,28 @@
+diff -Naur old/CPP/7zip/UI/FileManager/FM.cpp new/CPP/7zip/UI/FileManager/FM.cpp
+--- old/CPP/7zip/UI/FileManager/FM.cpp 2015-01-18 08:59:09.000000000 -1000
++++ new/CPP/7zip/UI/FileManager/FM.cpp 2015-02-09 11:39:55.575712452 -1000
+@@ -348,24 +348,7 @@
+
+ bool IsLargePageSupported()
+ {
+- #ifdef _WIN64
+ return true;
+- #else
+- OSVERSIONINFO versionInfo;
+- versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+- if (!::GetVersionEx(&versionInfo))
+- return false;
+- if (versionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || versionInfo.dwMajorVersion < 5)
+- return false;
+- if (versionInfo.dwMajorVersion > 5)
+- return true;
+- if (versionInfo.dwMinorVersion < 1)
+- return false;
+- if (versionInfo.dwMinorVersion > 1)
+- return true;
+- // return IsWow64();
+- return false;
+- #endif
+ }
+
+ #if 0 //#ifndef UNDER_CE