Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
3aa6b701da
!9 Fix CVE-2023-49797
From: @starlet-dx 
Reviewed-by: @cherry530 
Signed-off-by: @cherry530
2024-06-18 09:20:58 +00:00
starlet-dx
e3d95da23c Fix CVE-2023-49797 2024-06-18 16:48:05 +08:00
openeuler-ci-bot
4e09a19f98
!6 Updated to 5.13.0
From: @Jason_828e 
Reviewed-by: @yangzhao_kl 
Signed-off-by: @yangzhao_kl
2023-07-12 09:32:56 +00:00
chenzixuan
63111c078e Updated to 5.13.0 2023-07-05 06:48:54 +08:00
openeuler-ci-bot
2d38d00a01
!5 Update to 5.10.1
From: @starlet-dx 
Reviewed-by: @caodongxia 
Signed-off-by: @caodongxia
2023-05-16 08:00:15 +00:00
starlet-dx
a13872c06f Update to 5.10.1 2023-05-16 11:03:35 +08:00
openeuler-ci-bot
8299ef4bc3 !2 package init
Merge pull request !2 from huanghaitao/master
2020-08-10 18:30:43 +08:00
hht8
092d8765e4 add yaml 2020-08-06 14:00:28 +08:00
hht8
e801a95031 delete unused bin 2020-08-06 12:09:08 +08:00
hht8
5cc75f2cc7 modify source0 2020-06-29 10:40:04 +08:00
9 changed files with 632 additions and 360 deletions

View File

@ -1,81 +0,0 @@
From 22ad4f7200a56da969e9296d8fecf2f0b8368afc Mon Sep 17 00:00:00 2001
From: Dan Yeaw <dyeaw@ford.com>
Date: Mon, 23 Dec 2019 15:31:04 -0500
Subject: [PATCH] Bootloader: Fix GCC warnings for strncpy and strncat.
Fixes Issue #4196. GCC 8.1 and later added checks to prevent using
strncpy and strncat with the bounds depending on the length of the
source str. In order to fix this, a few approaches were made:
1. Where guards already existed to ensure that added paths weren't
larger than the PATH_MAX, changed to strcpy / strcat which don't take a
length parameter.
2. Where path length checks didn't exist, set the bounds of the strncpy
and strncat to PATH_MAX.
Signed-off-by: Dan Yeaw <dyeaw@ford.com>
---
bootloader/src/pyi_path.c | 7 ++++---
bootloader/src/pyi_pythonlib.c | 12 ++++++------
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/bootloader/src/pyi_path.c b/bootloader/src/pyi_path.c
index a449f79..d36e3d2 100644
--- a/bootloader/src/pyi_path.c
+++ b/bootloader/src/pyi_path.c
@@ -56,7 +56,7 @@ pyi_path_dirname(char *result, const char *path)
char *match = NULL;
/* Copy path to result and then just write '\0' to the place with path separator. */
- strncpy(result, path, strlen(path) + 1);
+ strncpy(result, path, PATH_MAX);
/* Remove separator from the end. */
len = strlen(result);
@@ -143,7 +143,7 @@ pyi_path_join(char *result, const char *path1, const char *path2)
memset(result, 0, PATH_MAX);
}
/* Copy path1 to result without null terminator */
- strncpy(result, path1, strlen(path1));
+ strcpy(result, path1);
/* Append trailing slash if missing. */
len = strlen(result);
@@ -156,7 +156,8 @@ pyi_path_join(char *result, const char *path1, const char *path2)
if (path2[len - 1] == PYI_SEP) {
/* Append path2 without slash. */
- strncat(result, path2, len - 2);
+ strcat(result, path2);
+ result[strlen(result) - 1] = PYI_NULLCHAR;
}
else {
/* path2 does not end with slash. */
diff --git a/bootloader/src/pyi_pythonlib.c b/bootloader/src/pyi_pythonlib.c
index ee4b3b2..d90c239 100644
--- a/bootloader/src/pyi_pythonlib.c
+++ b/bootloader/src/pyi_pythonlib.c
@@ -480,15 +480,15 @@ pyi_pylib_start_python(ARCHIVE_STATUS *status)
/* Set sys.path */
if (is_py2) {
/* sys.path = [mainpath] */
- strncpy(pypath, status->mainpath, strlen(status->mainpath));
+ strncpy(pypath, status->mainpath, PATH_MAX);
}
else {
/* sys.path = [base_library, mainpath] */
- strncpy(pypath, status->mainpath, strlen(status->mainpath));
- strncat(pypath, PYI_SEPSTR, strlen(PYI_SEPSTR));
- strncat(pypath, "base_library.zip", strlen("base_library.zip"));
- strncat(pypath, PYI_PATHSEPSTR, strlen(PYI_PATHSEPSTR));
- strncat(pypath, status->mainpath, strlen(status->mainpath));
+ strncpy(pypath, status->mainpath, PATH_MAX);
+ strncat(pypath, PYI_SEPSTR, PATH_MAX);
+ strncat(pypath, "base_library.zip", PATH_MAX);
+ strncat(pypath, PYI_PATHSEPSTR, PATH_MAX);
+ strncat(pypath, status->mainpath, PATH_MAX);
};
/*
--
2.23.0

Binary file not shown.

View File

@ -1,63 +0,0 @@
From a95fbb0f497680cce0a097aa3a143e84943b903f Mon Sep 17 00:00:00 2001
From: Hartmut Goebel <h.goebel@crazy-compilers.com>
Date: Sun, 3 May 2020 15:26:43 +0200
Subject: [PATCH] Bootloader: Reimplement pyi_search_path using strtok().
This avoids some places where we need to cope with strncpy(= and related. Also
the implementation becomes much simpler.
---
bootloader/src/pyi_path.c | 34 +++++++---------------------------
1 file changed, 7 insertions(+), 27 deletions(-)
diff --git a/bootloader/src/pyi_path.c b/bootloader/src/pyi_path.c
index 8736de8cc5..fb417e9269 100644
--- a/bootloader/src/pyi_path.c
+++ b/bootloader/src/pyi_path.c
@@ -205,40 +205,20 @@ pyi_path_exists(char * path)
int
pyi_search_path(char * result, const char * appname)
{
- char * path = pyi_getenv("PATH");
- char dirname[PATH_MAX + 1];
- char filename[PATH_MAX + 1];
+ char *path = pyi_getenv("PATH"); // returns a copy
+ char *dirname;
if (NULL == path) {
return -1;
}
- while (1) {
- char *delim = strchr(path, PYI_PATHSEP);
-
- if (delim) {
- size_t len = delim - path;
-
- if (len > PATH_MAX) {
- len = PATH_MAX;
- }
- strncpy(dirname, path, len);
- *(dirname + len) = '\0';
- }
- else { /* last $PATH element */
- strncpy(dirname, path, PATH_MAX);
- }
- pyi_path_join(filename, dirname, appname);
-
- if (pyi_path_exists(filename)) {
- strncpy(result, filename, PATH_MAX);
+ dirname = strtok(path, PYI_PATHSEPSTR);
+ while (dirname != NULL) {
+ pyi_path_join(result, dirname, appname);
+ if (pyi_path_exists(result)) {
return 0;
}
-
- if (!delim) {
- break;
- }
- path = delim + 1;
+ dirname = strtok(NULL, PYI_PATHSEPSTR);
}
return -1;
}

View File

@ -1,208 +0,0 @@
From b4c0d01e751975090fa7346a2a71dd778c3b412c Mon Sep 17 00:00:00 2001
From: Hartmut Goebel <h.goebel@crazy-compilers.com>
Date: Sun, 3 May 2020 15:43:52 +0200
Subject: [PATCH] Bootloader: Use snprintf() to simplify some string length
checks.
Instead of copying strings and checking whether the string si terminated with
a Null bytes, use snprintf, which tells how much space the new string would
have taken and compare this to the available space.
Since snprintf() add some overhead, This code might be a bit less efficient.
But this sie the bootloader, and most of the functions are called once only.
---
bootloader/src/pyi_archive.c | 21 ++++++++-------------
bootloader/src/pyi_launch.c | 27 +++++++++------------------
bootloader/src/pyi_main.c | 4 ++--
bootloader/src/pyi_path.c | 3 +--
bootloader/src/pyi_pythonlib.c | 14 +++++++++-----
bootloader/src/pyi_utils.c | 7 ++-----
6 files changed, 31 insertions(+), 45 deletions(-)
diff --git a/bootloader/src/pyi_archive.c b/bootloader/src/pyi_archive.c
index ed886e09fb..32b129fb98 100644
--- a/bootloader/src/pyi_archive.c
+++ b/bootloader/src/pyi_archive.c
@@ -455,28 +455,23 @@ int
pyi_arch_set_paths(ARCHIVE_STATUS *status, char const * archivePath,
char const * archiveName)
{
- size_t pathlen, namelen;
-
- pathlen = strnlen(archivePath, PATH_MAX);
- namelen = strnlen(archiveName, PATH_MAX);
-
- if (pathlen+namelen+1 > PATH_MAX) {
- return -1;
+ /* Set homepath to where the archive is */
+ if (snprintf(status->homepath, PATH_MAX, "%s", archivePath) >= PATH_MAX) {
+ return -1;
}
/* Get the archive Path */
- strcpy(status->archivename, archivePath);
- strcat(status->archivename, archiveName);
-
- /* Set homepath to where the archive is */
- strcpy(status->homepath, archivePath);
+ if (snprintf(status->archivename, PATH_MAX,
+ "%s%s", archivePath, archiveName) >= PATH_MAX) {
+ return -1;
+ }
/*
* Initial value of mainpath is homepath. It might be overriden
* by temppath if it is available.
*/
status->has_temp_directory = false;
- strcpy(status->mainpath, status->homepath);
+ strcpy(status->mainpath, status->homepath); // homepath fits into PATH_MAX
return 0;
}
diff --git a/bootloader/src/pyi_launch.c b/bootloader/src/pyi_launch.c
index 3517be6353..432a43416f 100644
--- a/bootloader/src/pyi_launch.c
+++ b/bootloader/src/pyi_launch.c
@@ -79,15 +79,13 @@ checkFile(char *buf, const char *fmt, ...)
static int
splitName(char *path, char *filename, const char *item)
{
- char name[PATH_MAX + 1];
+ char name[PATH_MAX];
VS("LOADER: Splitting item into path and filename\n");
- strncpy(name, item, PATH_MAX + 1);
-
- if (name[PATH_MAX] != '\0') {
+ if (snprintf(name, PATH_MAX, "%s", item) >= PATH_MAX) {
return -1;
}
-
+ // `name` fits into PATH_MAX, so will all substrings
strcpy(path, strtok(name, ":"));
strcpy(filename, strtok(NULL, ":"));
@@ -148,13 +146,11 @@ _get_archive(ARCHIVE_STATUS *archive_pool[], const char *path)
return NULL;
}
- strncpy(archive->archivename, path, PATH_MAX);
- strncpy(archive->homepath, archive_pool[SELF]->homepath, PATH_MAX);
- strncpy(archive->temppath, archive_pool[SELF]->temppath, PATH_MAX);
-
- if (archive->archivename[PATH_MAX-1] != '\0'
- || archive->homepath[PATH_MAX-1] != '\0'
- || archive->temppath[PATH_MAX-1] != '\0') {
+ if ((snprintf(archive->archivename, PATH_MAX, "%s", path) >= PATH_MAX) ||
+ (snprintf(archive->homepath, PATH_MAX, "%s",
+ archive_pool[SELF]->homepath) >= PATH_MAX) ||
+ (snprintf(archive->temppath, PATH_MAX, "%s",
+ archive_pool[SELF]->temppath) >= PATH_MAX)) {
FATALERROR("Archive path exceeds PATH_MAX\n");
free(archive);
return NULL;
@@ -369,7 +365,6 @@ pyi_launch_run_scripts(ARCHIVE_STATUS *status)
{
unsigned char *data;
char buf[PATH_MAX];
- size_t namelen;
TOC * ptoc = status->tocbuff;
PyObject *__main__;
PyObject *__file__;
@@ -400,14 +395,10 @@ pyi_launch_run_scripts(ARCHIVE_STATUS *status)
data = pyi_arch_extract(status, ptoc);
/* Set the __file__ attribute within the __main__ module,
* for full compatibility with normal execution. */
- namelen = strnlen(ptoc->name, PATH_MAX);
- if (namelen >= PATH_MAX-strlen(".py")-1) {
+ if (snprintf(buf, PATH_MAX, "%s.py", ptoc->name) >= PATH_MAX) {
FATALERROR("Name exceeds PATH_MAX\n");
return -1;
}
-
- strcpy(buf, ptoc->name);
- strcat(buf, ".py");
VS("LOADER: Running %s\n", buf);
if (is_py2) {
diff --git a/bootloader/src/pyi_main.c b/bootloader/src/pyi_main.c
index 02b1bec5dc..472cd1ae9a 100644
--- a/bootloader/src/pyi_main.c
+++ b/bootloader/src/pyi_main.c
@@ -126,8 +126,8 @@ pyi_main(int argc, char * argv[])
* we pass it through status variable
*/
if (strcmp(homepath, extractionpath) != 0) {
- strncpy(archive_status->temppath, extractionpath, PATH_MAX);
- if (archive_status->temppath[PATH_MAX-1] != '\0') {
+ if (snprintf(archive_status->temppath, PATH_MAX,
+ "%s", extractionpath) >= PATH_MAX) {
VS("LOADER: temppath exceeds PATH_MAX\n");
return -1;
}
diff --git a/bootloader/src/pyi_path.c b/bootloader/src/pyi_path.c
index fb417e9269..6ed252ffab 100644
--- a/bootloader/src/pyi_path.c
+++ b/bootloader/src/pyi_path.c
@@ -286,8 +286,7 @@ pyi_path_executable(char *execfile, const char *appname)
if (-1 == result) {
/* Searching $PATH failed, user is crazy. */
VS("LOADER: Searching $PATH failed for %s", appname);
- strncpy(buffer, appname, PATH_MAX);
- if (buffer[PATH_MAX-1] != '\0') {
+ if (snprintf(buffer, PATH_MAX, "%s", "appname") >= PATH_MAX) {
VS("LOADER: Appname too large %s\n", appname);
return -1;
}
diff --git a/bootloader/src/pyi_pythonlib.c b/bootloader/src/pyi_pythonlib.c
index caffcd6daa..8144885b17 100644
--- a/bootloader/src/pyi_pythonlib.c
+++ b/bootloader/src/pyi_pythonlib.c
@@ -414,18 +414,16 @@ pyi_pylib_start_python(ARCHIVE_STATUS *status)
};
/* Set sys.path */
- if (is_py2) {
- /* sys.path = [mainpath] */
- strncpy(pypath, status->mainpath, PATH_MAX);
- }
- else {
- /* sys.path = [base_library, mainpath] */
+ /* sys.path = [base_library, mainpath] */
- strncpy(pypath, status->mainpath, PATH_MAX);
- strncat(pypath, PYI_SEPSTR, PATH_MAX);
- strncat(pypath, "base_library.zip", PATH_MAX);
- strncat(pypath, PYI_PATHSEPSTR, PATH_MAX);
- strncat(pypath, status->mainpath, PATH_MAX);
- };
+ if (snprintf(pypath, sizeof pypath, "%s%cbase_library.zip%c%s",
+ status->mainpath, PYI_SEP, PYI_PATHSEP, status->mainpath)
+ >= sizeof pypath) {
+ // This should never happen, since mainpath is < PATH_MAX and pypath is
+ // huge enough
+ FATALERROR("sys.path (based on %s) exceeds buffer[%d] space\n",
+ status->mainpath, sizeof pypath);
+ return -1;
+ }
/*
* On Python 3, we must set sys.path to have base_library.zip before
diff --git a/bootloader/src/pyi_utils.c b/bootloader/src/pyi_utils.c
index e18d611f26..0c89975908 100644
--- a/bootloader/src/pyi_utils.c
+++ b/bootloader/src/pyi_utils.c
@@ -557,11 +557,8 @@ pyi_open_target(const char *path, const char* name_)
char *dir;
size_t len;
- strncpy(fnm, path, PATH_MAX);
- strncpy(name, name_, PATH_MAX);
-
- /* Check if the path names could be copied */
- if (fnm[PATH_MAX-1] != '\0' || name[PATH_MAX-1] != '\0') {
+ if (snprintf(fnm, PATH_MAX, "%s", path) >= PATH_MAX ||
+ snprintf(name, PATH_MAX, "%s", name_) >= PATH_MAX) {
return NULL;
}

View File

@ -0,0 +1,95 @@
From 709262381451878dadb9e9d26190167a2ab5e67c Mon Sep 17 00:00:00 2001
From: Rok Mandeljc <rok.mandeljc@gmail.com>
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

View File

@ -0,0 +1,513 @@
From 5a53dc58295b26eb8af1f146df990a657bc916d1 Mon Sep 17 00:00:00 2001
From: Rok Mandeljc <rok.mandeljc@gmail.com>
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.<dll_name> 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

BIN
pyinstaller-5.13.0.tar.gz Normal file

Binary file not shown.

View File

@ -1,15 +1,17 @@
%global _empty_manifest_terminate_build 0
Name: python-pyinstaller
Version: 3.6
Release: 1
Version: 5.13.0
Release: 2
Summary: PyInstaller bundles a Python application and all its dependencies into a single package.
License: GPL license with a special exception which allows to use PyInstaller to build and distribute non-free programs (including commercial ones)
License: GPL-2.0-only
URL: http://www.pyinstaller.org
Source0: https://files.pythonhosted.org/packages/3c/c9/c3f9bc64eb11eee6a824686deba6129884c8cbdf70e750661773b9865ee0/PyInstaller-3.6.tar.gz
Patch6000: Fix-Gcc-warnings-for-strncpy-and-strncat.patch
Patch6001: Reimplement-pyi-search-path-using-strtok.patch
Patch6002: Use-snprintf-to-simplify-some-string-len.patch
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
%description
PyInstaller bundles a Python application and all its dependencies into a single
@ -35,7 +37,7 @@ package. The user can run the packaged app without installing a Python
interpreter or any modules.
%prep
%autosetup -n PyInstaller-%{version} -p1
%autosetup -n pyinstaller-%{version} -p1
%build
%py3_build
@ -70,10 +72,20 @@ mv %{buildroot}/doclist.lst .
%files -n python3-pyinstaller -f filelist.lst
%dir %{python3_sitelib}/*
%exclude %{python3_sitelib}/PyInstaller/bootloader/{D*,W*,*32*,Linux-64bit}
%files help -f doclist.lst
%{_pkgdocdir}
%changelog
* Tue Jun 18 2024 yaoxin <yao_xin001@hoperun.com> - 5.13.0-2
- Fix CVE-2023-49797
* Mon Jul 10 2023 chenzixuan<chenzixuan@kylinos.cn> - 5.13.0-1
- Update to 5.13.0
* Tue May 16 2023 yaoxin <yao_xin001@hoperun.com> - 5.10.1-1
- Update to 5.10.1
* Mon Jun 22 2020 Python_Bot <Python_Bot@openeuler.org>
- Package Spec generated

4
python-pyinstaller.yaml Normal file
View File

@ -0,0 +1,4 @@
version_control: pypi
src_repo: PyInstaller
tag_prefix: "v"
seperator: ""