From e3d95da23cf81f072d1788ded1c332fa7b5d4047 Mon Sep 17 00:00:00 2001 From: starlet-dx <15929766099@163.com> Date: Tue, 18 Jun 2024 16:48:05 +0800 Subject: [PATCH] Fix CVE-2023-49797 --- backport-CVE-2023-49797-pre.patch | 95 ++++++ backport-CVE-2023-49797.patch | 513 ++++++++++++++++++++++++++++++ python-pyinstaller.spec | 9 +- 3 files changed, 616 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2023-49797-pre.patch create mode 100644 backport-CVE-2023-49797.patch diff --git a/backport-CVE-2023-49797-pre.patch b/backport-CVE-2023-49797-pre.patch new file mode 100644 index 0000000..e66fafe --- /dev/null +++ b/backport-CVE-2023-49797-pre.patch @@ -0,0 +1,95 @@ +From 709262381451878dadb9e9d26190167a2ab5e67c Mon Sep 17 00:00:00 2001 +From: Rok Mandeljc +Date: Thu, 3 Aug 2023 13:49:03 +0200 +Subject: [PATCH] rthooks: win32com: fully isolate the genpy cache + +Instead of extending the `win32.com.gen_py` sub-module search paths +(the `__path__` attribute) with the new location of the isolated +cache, override it completely. This prevents the global cache from +being accessed, which might result in errors when the global cache +contains some, but not all, required modules. +--- + .../hooks/rthooks/pyi_rth_win32comgenpy.py | 44 +++++++------------ + news/6257.bugfix.rst | 3 ++ + 2 files changed, 18 insertions(+), 29 deletions(-) + create mode 100644 news/6257.bugfix.rst + +diff --git a/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py b/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py +index 3671c3ab2e..aed2515b08 100644 +--- a/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py ++++ b/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py +@@ -9,12 +9,12 @@ + # SPDX-License-Identifier: Apache-2.0 + #----------------------------------------------------------------------------- + +-# The win32.client.gencache code must be allowed to create the cache in %temp% (user's temp). It is necessary to get the +-# gencache code to use a suitable directory other than the default in lib\site-packages\win32com\client\gen_py. +-# PyInstaller does not provide this directory structure and the frozen executable could be placed in a non-writable +-# directory like 'C:\Program Files. That's the reason for %temp% directory. +-# +-# http://www.py2exe.org/index.cgi/UsingEnsureDispatch ++# Put the cache generated by `win32com.client.gencache` into isolated temporary directory. Historically, this was ++# required due to earlier versions of `pywin32` using the `site-packages\win32com\client\gen_py` directory for ++# the cache by default. Nowadays, the default location for the cache seems to be in the configured temporary directory ++# (pointed to by TEMP or TMP, for example %LOCALAPPDATA%\Temp), so strictly speaking, the relocation is not necessary ++# anymore. But for the time being, we are keeping it around to isolate the frozen application from the rest of the ++# system. + + + def _pyi_rthook(): +@@ -23,36 +23,22 @@ def _pyi_rthook(): + import shutil + import tempfile + +- # Put gen_py cache in temp directory. ++ import win32com ++ ++ # Create temporary directory. The actual cache directory needs to be named `gen_py`, so create a sub-directory. + supportdir = tempfile.mkdtemp() +- # gen_py has to be put into directory 'gen_py'. ++ + genpydir = os.path.join(supportdir, 'gen_py') ++ os.makedirs(genpydir, exist_ok=True) + +- # Create 'gen_py' directory. This directory does not need to contain '__init__.py' file. +- try: +- # win32com gencache cannot be put directly to 'supportdir' with any random name. It has to be put in a directory +- # called 'gen_py'. This is the reason why to create this directory in supportdir'. +- os.makedirs(genpydir) +- # Remove temp directory at application exit and ignore any errors. +- atexit.register(shutil.rmtree, supportdir, ignore_errors=True) +- except OSError: +- pass ++ # Remove the teporary directory at application exit, ignoring errors. ++ atexit.register(shutil.rmtree, supportdir, ignore_errors=True) + + # Override the default path to gen_py cache. +- import win32com # noqa: E402 +- + win32com.__gen_path__ = genpydir + +- # The attribute __loader__ makes module 'pkg_resources' working but On Windows it breaks pywin32 (win32com) and test +- # 'basic/test_pyttsx' will fail. Just removing that attribute for win32com fixes that and gencache is created +- # properly. +- if hasattr(win32com, '__loader__'): +- del win32com.__loader__ +- +- # Ensure genpydir is in 'gen_py' module paths. +- import win32com.gen_py # noqa: E402 +- +- win32com.gen_py.__path__.insert(0, genpydir) ++ # Override the sub-module paths for win32com.gen_py run-time sub-package. ++ win32com.gen_py.__path__ = [genpydir] + + + _pyi_rthook() +diff --git a/news/6257.bugfix.rst b/news/6257.bugfix.rst +new file mode 100644 +index 0000000000..3cb746a332 +--- /dev/null ++++ b/news/6257.bugfix.rst +@@ -0,0 +1,3 @@ ++(Windows) Fix ``win32com`` run-time hook to fully isolate the ``gen_py`` ++cache. This prevents the access to global cache, which results in errors ++when the global cache contains some, but not all, required modules. +\ No newline at end of file diff --git a/backport-CVE-2023-49797.patch b/backport-CVE-2023-49797.patch new file mode 100644 index 0000000..7558ed0 --- /dev/null +++ b/backport-CVE-2023-49797.patch @@ -0,0 +1,513 @@ +From 5a53dc58295b26eb8af1f146df990a657bc916d1 Mon Sep 17 00:00:00 2001 +From: Rok Mandeljc +Date: Sat, 5 Aug 2023 12:50:28 +0200 +Subject: [PATCH] rthooks: secure temp directories used by matplotlib and + win32com rthooks + +The run-time hooks that relocate the package's configuration/cache +directory into isolated temporary directory create this directory using +the `tempfile.mkdtemp` function. According to its documentation, the +function creates the temporary directory "in the most secure manner +possible", and the created directory should be "readable, writable, and +searchable only by the creating user ID". + +However, this does not apply to Windows, where the 0o700 POSIX +permissions mask passed to the underyling `os.mkdir` call has no effect. +Consequently, the access to the created temporary directory is in fact +gated only by the access to the parent directory. So as long as `TEMP` +and `TMP` point to `%LOCALAPPDATA%\Temp`, the created temporary +directories are typically inaccessible to other users, who do not have +access to the user's home directory. On the other hand, if the temporary +directory base is relocated to a system-wide location (e.g., `c:\temp`), +the temporary directories created by the run-time hooks might become +accessible to other users as well. A malicious user with local access +might thus modify the contents of the temporary directory, interfering +with the application. If the application is running in privileged mode +and developer mode is enabled on the system, they might also attempt +a symlink attack due to lack of hardened mode for `shutil.rmtree` +(used for clean up) on Windows. + +Therefore, we replace the use of `tempfile.mkdtemp` with custom function +that uses original `mkdtemp` on POSIX and provides a Windows-specific +implementation that secures the access to created directory via security +descriptor passed to the `CreateDirectoryW` call. This is a +`ctypes`-based port of the code that we already have in bootloader for +mitigating the same issue with temporary directory in onefile builds. + +In order to share the implementation among the two run-time hooks that +require it, the code is provided by a new `_pyi_rth_utils` PyInstaller +"fake" package, which is bundled with the frozen application on demand +(i.e., if it is referenced in any of collected run-time hooks). + +Origin: +https://github.com/pyinstaller/pyinstaller/commit/5a53dc58295b26eb8af1f146df990a657bc916d1 +--- + MANIFEST.in | 2 +- + .../fake-modules/_pyi_rth_utils/__init__.py | 56 ++++ + .../fake-modules/_pyi_rth_utils/_win32.py | 262 ++++++++++++++++++ + .../hook-_pyi_rth_utils.py | 25 ++ + .../hooks/rthooks/pyi_rth_mplconfig.py | 8 +- + .../hooks/rthooks/pyi_rth_win32comgenpy.py | 8 +- + news/7827.bugfix.rst | 5 + + setup.cfg | 1 + + setup.py | 1 + + 9 files changed, 361 insertions(+), 7 deletions(-) + create mode 100644 PyInstaller/fake-modules/_pyi_rth_utils/__init__.py + create mode 100644 PyInstaller/fake-modules/_pyi_rth_utils/_win32.py + create mode 100644 PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py + create mode 100644 news/7827.bugfix.rst + +diff --git a/MANIFEST.in b/MANIFEST.in +index a77f401..2c702a1 100755 +--- a/MANIFEST.in ++++ b/MANIFEST.in +@@ -12,6 +12,6 @@ recursive-include PyInstaller/bootloader/Windows-64bit-intel * + recursive-include PyInstaller/bootloader/Darwin-64bit * + include pyproject.toml + # These files need to be explicitly included +-include PyInstaller/fake-modules/*.py ++recursive-include PyInstaller/fake-modules *.py + include PyInstaller/hooks/rthooks.dat + include PyInstaller/lib/README.rst +diff --git a/PyInstaller/fake-modules/_pyi_rth_utils/__init__.py b/PyInstaller/fake-modules/_pyi_rth_utils/__init__.py +new file mode 100644 +index 0000000..2d3af0e +--- /dev/null ++++ b/PyInstaller/fake-modules/_pyi_rth_utils/__init__.py +@@ -0,0 +1,56 @@ ++# ----------------------------------------------------------------------------- ++# Copyright (c) 2023, PyInstaller Development Team. ++# ++# Distributed under the terms of the GNU General Public License (version 2 ++# or later) with exception for distributing the bootloader. ++# ++# The full license is in the file COPYING.txt, distributed with this software. ++# ++# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception) ++# ----------------------------------------------------------------------------- ++ ++import os ++import sys ++import errno ++import tempfile ++ ++# Helper for creating temporary directories with access restricted to the user running the process. ++# On POSIX systems, this is already achieved by `tempfile.mkdtemp`, which uses 0o700 permissions mask. ++# On Windows, however, the POSIX permissions semantics have no effect, and we need to provide our own implementation ++# that restricts the access by passing appropriate security attributes to the `CreateDirectory` function. ++ ++if os.name == 'nt': ++ from . import _win32 ++ ++ def secure_mkdtemp(suffix=None, prefix=None, dir=None): ++ """ ++ Windows-specific replacement for `tempfile.mkdtemp` that restricts access to the user running the process. ++ Based on `mkdtemp` implementation from python 3.11 stdlib. ++ """ ++ ++ prefix, suffix, dir, output_type = tempfile._sanitize_params(prefix, suffix, dir) ++ ++ names = tempfile._get_candidate_names() ++ if output_type is bytes: ++ names = map(os.fsencode, names) ++ ++ for seq in range(tempfile.TMP_MAX): ++ name = next(names) ++ file = os.path.join(dir, prefix + name + suffix) ++ sys.audit("tempfile.mkdtemp", file) ++ try: ++ _win32.secure_mkdir(file) ++ except FileExistsError: ++ continue # try again ++ except PermissionError: ++ # This exception is thrown when a directory with the chosen name already exists on windows. ++ if (os.name == 'nt' and os.path.isdir(dir) and os.access(dir, os.W_OK)): ++ continue ++ else: ++ raise ++ return file ++ ++ raise FileExistsError(errno.EEXIST, "No usable temporary directory name found") ++ ++else: ++ secure_mkdtemp = tempfile.mkdtemp +diff --git a/PyInstaller/fake-modules/_pyi_rth_utils/_win32.py b/PyInstaller/fake-modules/_pyi_rth_utils/_win32.py +new file mode 100644 +index 0000000..41237fb +--- /dev/null ++++ b/PyInstaller/fake-modules/_pyi_rth_utils/_win32.py +@@ -0,0 +1,262 @@ ++# ----------------------------------------------------------------------------- ++# Copyright (c) 2023, PyInstaller Development Team. ++# ++# Distributed under the terms of the GNU General Public License (version 2 ++# or later) with exception for distributing the bootloader. ++# ++# The full license is in the file COPYING.txt, distributed with this software. ++# ++# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception) ++# ----------------------------------------------------------------------------- ++ ++import ctypes ++import ctypes.wintypes ++ ++# Constants from win32 headers ++TOKEN_QUERY = 0x0008 ++ ++TokenUser = 1 # from TOKEN_INFORMATION_CLASS enum ++ ++ERROR_INSUFFICIENT_BUFFER = 122 ++ ++INVALID_HANDLE = -1 ++ ++FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100 ++FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000 ++ ++SDDL_REVISION1 = 1 ++ ++# Structures for ConvertSidToStringSidW ++PSID = ctypes.wintypes.LPVOID ++ ++ ++class SID_AND_ATTRIBUTES(ctypes.Structure): ++ _fields_ = [ ++ ("Sid", PSID), ++ ("Attributes", ctypes.wintypes.DWORD), ++ ] ++ ++ ++class TOKEN_USER(ctypes.Structure): ++ _fields_ = [ ++ ("User", SID_AND_ATTRIBUTES), ++ ] ++ ++ ++PTOKEN_USER = ctypes.POINTER(TOKEN_USER) ++ ++# SECURITY_ATTRIBUTES structure for CreateDirectoryW ++PSECURITY_DESCRIPTOR = ctypes.wintypes.LPVOID ++ ++ ++class SECURITY_ATTRIBUTES(ctypes.Structure): ++ _fields_ = [ ++ ("nLength", ctypes.wintypes.DWORD), ++ ("lpSecurityDescriptor", PSECURITY_DESCRIPTOR), ++ ("bInheritHandle", ctypes.wintypes.BOOL), ++ ] ++ ++ ++# win32 API functions, bound via ctypes. ++# NOTE: we do not use ctypes.windll. to avoid modifying its (global) function prototypes, which might affect ++# user's code. ++kernel32 = ctypes.WinDLL("kernel32") ++advapi32 = ctypes.WinDLL("advapi32") ++ ++kernel32.CloseHandle.restype = ctypes.wintypes.BOOL ++kernel32.CloseHandle.argtypes = (ctypes.wintypes.HANDLE,) ++ ++kernel32.LocalFree.restype = ctypes.wintypes.BOOL ++kernel32.LocalFree.argtypes = (ctypes.wintypes.HLOCAL,) ++ ++kernel32.GetCurrentProcess.restype = ctypes.wintypes.HANDLE ++ ++kernel32.OpenProcessToken.restype = ctypes.wintypes.BOOL ++kernel32.OpenProcessToken.argtypes = ( ++ ctypes.wintypes.HANDLE, ++ ctypes.wintypes.DWORD, ++ ctypes.wintypes.PHANDLE, ++) ++ ++advapi32.ConvertSidToStringSidW.restype = ctypes.wintypes.BOOL ++advapi32.ConvertSidToStringSidW.argtypes = ( ++ PSID, ++ ctypes.POINTER(ctypes.wintypes.LPWSTR), ++) ++ ++advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW.restype = ctypes.wintypes.BOOL ++advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW.argtypes = ( ++ ctypes.wintypes.LPCWSTR, ++ ctypes.wintypes.DWORD, ++ ctypes.POINTER(PSECURITY_DESCRIPTOR), ++ ctypes.wintypes.PULONG, ++) ++ ++ ++def _win_error_to_message(error_code): ++ """ ++ Convert win32 error code to message. ++ """ ++ message_wstr = ctypes.wintypes.LPWSTR(None) ++ ret = kernel32.FormatMessageW( ++ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, ++ None, # lpSource ++ error_code, # dwMessageId ++ 0x400, # dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) ++ ctypes.byref(message_wstr), # pointer to LPWSTR due to FORMAT_MESSAGE_ALLOCATE_BUFFER ++ 64, # due to FORMAT_MESSAGE_ALLOCATE_BUFFER, this is minimum number of characters to allocate ++ ) ++ if ret == 0: ++ return None ++ ++ message = message_wstr.value ++ kernel32.LocalFree(message_wstr) ++ ++ # Strip trailing CR/LF. ++ if message: ++ message = message.strip() ++ return message ++ ++ ++def _get_user_sid(): ++ """ ++ Obtain the SID for the current user. ++ """ ++ process_token = ctypes.wintypes.HANDLE(INVALID_HANDLE) ++ ++ try: ++ # Get access token for the current process ++ ret = kernel32.OpenProcessToken( ++ kernel32.GetCurrentProcess(), ++ TOKEN_QUERY, ++ ctypes.pointer(process_token), ++ ) ++ if ret == 0: ++ error_code = kernel32.GetLastError() ++ raise RuntimeError(f"Failed to open process token! Error code: 0x{error_code:X}") ++ ++ # Query buffer size for user info structure ++ user_info_size = ctypes.wintypes.DWORD(0) ++ ++ ret = advapi32.GetTokenInformation( ++ process_token, ++ TokenUser, ++ None, ++ 0, ++ ctypes.byref(user_info_size), ++ ) ++ ++ # We expect this call to fail with ERROR_INSUFFICIENT_BUFFER ++ if ret == 0: ++ error_code = kernel32.GetLastError() ++ if error_code != ERROR_INSUFFICIENT_BUFFER: ++ raise RuntimeError(f"Failed to query token information buffer size! Error code: 0x{error_code:X}") ++ else: ++ raise RuntimeError("Unexpected return value from GetTokenInformation!") ++ ++ # Allocate buffer ++ user_info = ctypes.create_string_buffer(user_info_size.value) ++ ret = advapi32.GetTokenInformation( ++ process_token, ++ TokenUser, ++ user_info, ++ user_info_size, ++ ctypes.byref(user_info_size), ++ ) ++ if ret == 0: ++ error_code = kernel32.GetLastError() ++ raise RuntimeError(f"Failed to query token information! Error code: 0x{error_code:X}") ++ ++ # Convert SID to string ++ # Technically, we need to pass user_info->User.Sid, but as they are at the beginning of the ++ # buffer, just pass the buffer instead... ++ sid_wstr = ctypes.wintypes.LPWSTR(None) ++ ret = advapi32.ConvertSidToStringSidW( ++ ctypes.cast(user_info, PTOKEN_USER).contents.User.Sid, ++ ctypes.pointer(sid_wstr), ++ ) ++ if ret == 0: ++ error_code = kernel32.GetLastError() ++ raise RuntimeError(f"Failed to convert SID to string! Error code: 0x{error_code:X}") ++ sid = sid_wstr.value ++ kernel32.LocalFree(sid_wstr) ++ except Exception: ++ sid = None ++ finally: ++ # Close the process token ++ if process_token.value != INVALID_HANDLE: ++ kernel32.CloseHandle(process_token) ++ ++ return sid ++ ++ ++# Get and cache current user's SID ++_user_sid = _get_user_sid() ++ ++ ++def secure_mkdir(dir_name): ++ """ ++ Replacement for mkdir that limits the access to created directory to current user. ++ """ ++ ++ # Create security descriptor ++ # Prefer actual user SID over SID S-1-3-4 (current owner), because at the time of writing, Wine does not properly ++ # support the latter. ++ sid = _user_sid or "S-1-3-4" ++ ++ # DACL descriptor (D): ++ # ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid;(resource_attribute) ++ # - ace_type = SDDL_ACCESS_ALLOWED (A) ++ # - rights = SDDL_FILE_ALL (FA) ++ # - account_sid = current user (queried SID) ++ security_desc_str = f"D:(A;;FA;;;{sid})" ++ security_desc = ctypes.wintypes.LPVOID(None) ++ ++ ret = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW( ++ security_desc_str, ++ SDDL_REVISION1, ++ ctypes.byref(security_desc), ++ None, ++ ) ++ if ret == 0: ++ error_code = kernel32.GetLastError() ++ raise RuntimeError( ++ f"Failed to create security descriptor! Error code: 0x{error_code:X}, " ++ f"message: {_win_error_to_message(error_code)}" ++ ) ++ ++ security_attr = SECURITY_ATTRIBUTES() ++ security_attr.nLength = ctypes.sizeof(SECURITY_ATTRIBUTES) ++ security_attr.lpSecurityDescriptor = security_desc ++ security_attr.bInheritHandle = False ++ ++ # Create directory ++ ret = kernel32.CreateDirectoryW( ++ dir_name, ++ security_attr, ++ ) ++ if ret == 0: ++ # Call failed; store error code immediately, to avoid it being overwritten in cleanup below. ++ error_code = kernel32.GetLastError() ++ ++ # Free security descriptor ++ kernel32.LocalFree(security_desc) ++ ++ # Exit on succeess ++ if ret != 0: ++ return ++ ++ # Construct OSError from win error code ++ error_message = _win_error_to_message(error_code) ++ ++ # Strip trailing dot to match error message from os.mkdir(). ++ if error_message and error_message[-1] == '.': ++ error_message = error_message[:-1] ++ ++ raise OSError( ++ None, # errno ++ error_message, # strerror ++ dir_name, # filename ++ error_code, # winerror ++ None, # filename2 ++ ) +diff --git a/PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py b/PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py +new file mode 100644 +index 0000000..d035df0 +--- /dev/null ++++ b/PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py +@@ -0,0 +1,25 @@ ++# ----------------------------------------------------------------------------- ++# Copyright (c) 2023, PyInstaller Development Team. ++# ++# Distributed under the terms of the GNU General Public License (version 2 ++# or later) with exception for distributing the bootloader. ++# ++# The full license is in the file COPYING.txt, distributed with this software. ++# ++# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception) ++# ----------------------------------------------------------------------------- ++""" ++This hook allows discovery and collection of PyInstaller's internal _pyi_rth_utils module that provides utility ++functions for run-time hooks. ++ ++The module is implemented in 'PyInstaller/fake-modules/_pyi_rth_utils.py'. ++""" ++ ++import os ++ ++from PyInstaller import PACKAGEPATH ++ ++ ++def pre_find_module_path(api): ++ module_dir = os.path.join(PACKAGEPATH, 'fake-modules') ++ api.search_dirs = [module_dir] +diff --git a/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py b/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py +index 018d6fe..6ea9425 100755 +--- a/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py ++++ b/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py +@@ -27,10 +27,12 @@ def _pyi_rthook(): + import atexit + import os + import shutil +- import tempfile + +- # Put matplot config dir to temp directory. +- configdir = tempfile.mkdtemp() ++ import _pyi_rth_utils # PyInstaller's run-time hook utilities module ++ ++ # Isolate matplotlib's config dir into temporary directory. ++ # Use our replacement for `tempfile.mkdtemp` function that properly restricts access to directory on all platforms. ++ configdir = _pyi_rth_utils.secure_mkdtemp() + os.environ['MPLCONFIGDIR'] = configdir + + try: +diff --git a/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py b/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py +index aed2515..a9bbbd1 100755 +--- a/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py ++++ b/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py +@@ -21,13 +21,15 @@ def _pyi_rthook(): + import atexit + import os + import shutil +- import tempfile + + import win32com + +- # Create temporary directory. The actual cache directory needs to be named `gen_py`, so create a sub-directory. +- supportdir = tempfile.mkdtemp() ++ import _pyi_rth_utils # PyInstaller's run-time hook utilities module + ++ # Create temporary directory. ++ # Use our replacement for `tempfile.mkdtemp` function that properly restricts access to directory on all platforms. ++ supportdir = _pyi_rth_utils.secure_mkdtemp() ++ # The actual cache directory needs to be named `gen_py`, so create a sub-directory. + genpydir = os.path.join(supportdir, 'gen_py') + os.makedirs(genpydir, exist_ok=True) + +diff --git a/news/7827.bugfix.rst b/news/7827.bugfix.rst +new file mode 100644 +index 0000000..41ea37a +--- /dev/null ++++ b/news/7827.bugfix.rst +@@ -0,0 +1,5 @@ ++(Windows) Ensure that the access to temporary directories created by ++the ``matplotlib`` and ``win32com`` run-time hooks is restricted to ++the user running the frozen application, even if ``TMP`` / ``TEMP`` ++environment directory points to a system-wide location that can be ++accessed to all users. +diff --git a/setup.cfg b/setup.cfg +index 7cd1548..756ae34 100755 +--- a/setup.cfg ++++ b/setup.cfg +@@ -70,6 +70,7 @@ include = + PyInstaller = + bootloader/*/* + fake-modules/*.py ++ fake-modules/_pyi_rth_utils/*.py + hooks/rthooks.dat + lib/README.rst + +diff --git a/setup.py b/setup.py +index 51d2482..ac82bb6 100755 +--- a/setup.py ++++ b/setup.py +@@ -114,6 +114,7 @@ def finalize_options(self): + *(f"bootloader/images/*.{suffix}" for suffix in self.ICON_TYPES), + # These files need to be explicitly included as well. + "fake-modules/*.py", ++ "fake-modules/_pyi_rth_utils/*.py", + "hooks/rthooks.dat", + "lib/README.rst", + ], +-- +2.43.0 + diff --git a/python-pyinstaller.spec b/python-pyinstaller.spec index fa86f99..42fcca1 100644 --- a/python-pyinstaller.spec +++ b/python-pyinstaller.spec @@ -1,11 +1,15 @@ %global _empty_manifest_terminate_build 0 Name: python-pyinstaller Version: 5.13.0 -Release: 1 +Release: 2 Summary: PyInstaller bundles a Python application and all its dependencies into a single package. License: GPL-2.0-only URL: http://www.pyinstaller.org Source0: https://files.pythonhosted.org/packages/51/37/2e0195ef4e4dec35e3f116361c4c780e0c4cd2cd96079199b3218c08fabb/pyinstaller-%{version}.tar.gz +# https://github.com/pyinstaller/pyinstaller/commit/709262381451878dadb9e9d26190167a2ab5e67c +Patch3000: backport-CVE-2023-49797-pre.patch +# https://github.com/pyinstaller/pyinstaller/commit/5a53dc58295b26eb8af1f146df990a657bc916d1 +Patch3001: backport-CVE-2023-49797.patch BuildRequires: python3-devel python3-setuptools zlib-devel BuildRequires: python3-wheel @@ -74,6 +78,9 @@ mv %{buildroot}/doclist.lst . %{_pkgdocdir} %changelog +* Tue Jun 18 2024 yaoxin - 5.13.0-2 +- Fix CVE-2023-49797 + * Mon Jul 10 2023 chenzixuan - 5.13.0-1 - Update to 5.13.0