[Python-checkins] [3.7] bpo-29778: Ensure python3.dll is loaded from correct locations when Python is embedded (GH-21297) (#21298)

Steve Dower webhook-mailer at python.org
Mon Jul 6 13:25:04 EDT 2020


https://github.com/python/cpython/commit/110dd153662a13b8ae1bb06348e5b1f118ab26d7
commit: 110dd153662a13b8ae1bb06348e5b1f118ab26d7
branch: 3.7
author: Steve Dower <steve.dower at python.org>
committer: GitHub <noreply at github.com>
date: 2020年07月06日T13:24:59-04:00
summary:
[3.7] bpo-29778: Ensure python3.dll is loaded from correct locations when Python is embedded (GH-21297) (#21298)
* bpo-29778: Ensure python3.dll is loaded from correct locations when Python is embedded.
* Add CVE number
files:
A Misc/NEWS.d/next/Security/2020-07-03-17-21-37.bpo-29778.cR_fGS.rst
M PC/getpathp.c
M PCbuild/pyproject.props
M PCbuild/python.props
M Python/dynload_win.c
diff --git a/Misc/NEWS.d/next/Security/2020-07-03-17-21-37.bpo-29778.cR_fGS.rst b/Misc/NEWS.d/next/Security/2020-07-03-17-21-37.bpo-29778.cR_fGS.rst
new file mode 100644
index 0000000000000..998ffb1ee6667
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2020-07-03-17-21-37.bpo-29778.cR_fGS.rst
@@ -0,0 +1,2 @@
+Ensure :file:`python3.dll` is loaded from correct locations when Python is
+embedded (CVE-2020-15523).
diff --git a/PC/getpathp.c b/PC/getpathp.c
index dc4e43fe7d3b6..f7022aea1f557 100644
--- a/PC/getpathp.c
+++ b/PC/getpathp.c
@@ -161,27 +161,37 @@ reduce(wchar_t *dir)
 static int
 change_ext(wchar_t *dest, const wchar_t *src, const wchar_t *ext)
 {
- size_t src_len = wcsnlen_s(src, MAXPATHLEN+1);
- size_t i = src_len;
- if (i >= MAXPATHLEN+1) {
- Py_FatalError("buffer overflow in getpathp.c's reduce()");
- }
+ if (src && src != dest) {
+ size_t src_len = wcsnlen_s(src, MAXPATHLEN+1);
+ size_t i = src_len;
+ if (i >= MAXPATHLEN+1) {
+ Py_FatalError("buffer overflow in getpathp.c's reduce()");
+ }
 
- while (i > 0 && src[i] != '.' && !is_sep(src[i]))
- --i;
+ while (i > 0 && src[i] != '.' && !is_sep(src[i]))
+ --i;
 
- if (i == 0) {
- dest[0] = '0円';
- return -1;
- }
+ if (i == 0) {
+ dest[0] = '0円';
+ return -1;
+ }
+
+ if (is_sep(src[i])) {
+ i = src_len;
+ }
 
- if (is_sep(src[i])) {
- i = src_len;
+ if (wcsncpy_s(dest, MAXPATHLEN+1, src, i)) {
+ dest[0] = '0円';
+ return -1;
+ }
+ } else {
+ wchar_t *s = wcsrchr(dest, L'.');
+ if (s) {
+ s[0] = '0円';
+ }
 }
 
- if (wcsncpy_s(dest, MAXPATHLEN+1, src, i) ||
- wcscat_s(dest, MAXPATHLEN+1, ext))
- {
+ if (wcscat_s(dest, MAXPATHLEN+1, ext)) {
 dest[0] = '0円';
 return -1;
 }
@@ -337,6 +347,19 @@ search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path, const wchar_t *lan
 }
 
 
+static int
+get_dllpath(wchar_t *dllpath)
+{
+#ifdef Py_ENABLE_SHARED
+ extern HANDLE PyWin_DLLhModule;
+ if (PyWin_DLLhModule && GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN)) {
+ return 0;
+ }
+#endif
+ return -1;
+}
+
+
 #ifdef Py_ENABLE_SHARED
 
 /* a string loaded from the DLL at startup.*/
@@ -509,31 +532,6 @@ getpythonregpath(HKEY keyBase, int skipcore)
 #endif /* Py_ENABLE_SHARED */
 
 
-static _PyInitError
-get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config)
-{
- wchar_t dll_path[MAXPATHLEN+1];
- memset(dll_path, 0, sizeof(dll_path));
-
-#ifdef Py_ENABLE_SHARED
- extern HANDLE PyWin_DLLhModule;
- if (PyWin_DLLhModule) {
- if (!GetModuleFileNameW(PyWin_DLLhModule, dll_path, MAXPATHLEN)) {
- dll_path[0] = 0;
- }
- }
-#else
- dll_path[0] = 0;
-#endif
-
- config->dll_path = _PyMem_RawWcsdup(dll_path);
- if (config->dll_path == NULL) {
- return _Py_INIT_NO_MEMORY();
- }
- return _Py_INIT_OK();
-}
-
-
 static _PyInitError
 get_program_full_path(const _PyCoreConfig *core_config,
 PyCalculatePath *calculate, _PyPathConfig *config)
@@ -675,12 +673,11 @@ calculate_init(PyCalculatePath *calculate,
 static int
 get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config)
 {
- if (config->dll_path[0]) {
- if (!change_ext(spbuffer, config->dll_path, L"._pth") &&
- exists(spbuffer))
- {
- return 1;
- }
+ if (get_dllpath(spbuffer) &&
+ !change_ext(spbuffer, spbuffer, L"._pth") &&
+ exists(spbuffer))
+ {
+ return 1;
 }
 if (config->program_full_path[0]) {
 if (!change_ext(spbuffer, config->program_full_path, L"._pth") &&
@@ -967,11 +964,6 @@ calculate_path_impl(const _PyCoreConfig *core_config,
 {
 _PyInitError err;
 
- err = get_dll_path(calculate, config);
- if (_Py_INIT_FAILED(err)) {
- return err;
- }
-
 err = get_program_full_path(core_config, calculate, config);
 if (_Py_INIT_FAILED(err)) {
 return err;
@@ -992,9 +984,13 @@ calculate_path_impl(const _PyCoreConfig *core_config,
 calculate_pyvenv_file(calculate);
 
 /* Calculate zip archive path from DLL or exe path */
- change_ext(calculate->zip_path,
- config->dll_path[0] ? config->dll_path : config->program_full_path,
- L".zip");
+ if (get_dllpath(calculate->zip_path) ||
+ change_ext(calculate->zip_path, calculate->zip_path, L".zip"))
+ {
+ if (change_ext(calculate->zip_path, config->program_full_path, L".zip")) {
+ calculate->zip_path[0] = L'0円';
+ }
+ }
 
 calculate_home_prefix(calculate, prefix);
 
@@ -1054,28 +1050,39 @@ int
 _Py_CheckPython3(void)
 {
 wchar_t py3path[MAXPATHLEN+1];
- wchar_t *s;
 if (python3_checked) {
 return hPython3 != NULL;
 }
 python3_checked = 1;
 
 /* If there is a python3.dll next to the python3y.dll,
- assume this is a build tree; use that DLL */
- wcscpy(py3path, _Py_path_config.dll_path);
- s = wcsrchr(py3path, L'\\');
- if (!s) {
- s = py3path;
+ use that DLL */
+ if (!get_dllpath(py3path)) {
+ reduce(py3path);
+ join(py3path, PY3_DLLNAME);
+ hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+ if (hPython3 != NULL) {
+ return 1;
+ }
 }
- wcscpy(s, L"\\python3.dll");
- hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
- if (hPython3 != NULL) {
- return 1;
+
+ /* If we can locate python3.dll in our application dir,
+ use that DLL */
+ wcscpy(py3path, Py_GetPrefix());
+ if (py3path[0]) {
+ join(py3path, PY3_DLLNAME);
+ hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+ if (hPython3 != NULL) {
+ return 1;
+ }
 }
 
- /* Check sys.prefix\DLLs\python3.dll */
+ /* For back-compat, also search {sys.prefix}\DLLs, though
+ that has not been a normal install layout for a while */
 wcscpy(py3path, Py_GetPrefix());
- wcscat(py3path, L"\\DLLs\\python3.dll");
- hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+ if (py3path[0]) {
+ join(py3path, L"DLLs\\" PY3_DLLNAME);
+ hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+ }
 return hPython3 != NULL;
 }
diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props
index c07bac3c24211..0f7561744249f 100644
--- a/PCbuild/pyproject.props
+++ b/PCbuild/pyproject.props
@@ -24,12 +24,12 @@
 <_PlatformPreprocessorDefinition>_WIN32;</_PlatformPreprocessorDefinition>
 <_PlatformPreprocessorDefinition Condition="$(Platform) == 'x64'">_WIN64;_M_X64;</_PlatformPreprocessorDefinition>
 <_PydPreprocessorDefinition Condition="$(TargetExt) == '.pyd'">Py_BUILD_CORE_MODULE;</_PydPreprocessorDefinition>
+ <_Py3NamePreprocessorDefinition>PY3_DLLNAME=L"$(Py3DllName)";</_Py3NamePreprocessorDefinition>
 </PropertyGroup>
 <ItemDefinitionGroup>
 <ClCompile>
 <AdditionalIncludeDirectories>$(PySourcePath)Include;$(PySourcePath)PC;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN32;$(_PlatformPreprocessorDefinition)$(_DebugPreprocessorDefinition)$(_PydPreprocessorDefinition)%(PreprocessorDefinitions)</PreprocessorDefinitions>
- 
+ <PreprocessorDefinitions>WIN32;$(_Py3NamePreprocessorDefinition)$(_PlatformPreprocessorDefinition)$(_DebugPreprocessorDefinition)$(_PydPreprocessorDefinition)%(PreprocessorDefinitions)</PreprocessorDefinitions>
 <Optimization>MaxSpeed</Optimization>
 <IntrinsicFunctions>true</IntrinsicFunctions>
 <StringPooling>true</StringPooling>
diff --git a/PCbuild/python.props b/PCbuild/python.props
index 8be1daa696323..1034e7f3da3fe 100644
--- a/PCbuild/python.props
+++ b/PCbuild/python.props
@@ -177,6 +177,8 @@
 
 <!-- The name of the resulting pythonXY.dll (without the extension) -->
 <PyDllName>python$(MajorVersionNumber)$(MinorVersionNumber)$(PyDebugExt)</PyDllName>
+ <!-- The name of the resulting pythonX.dll (without the extension) -->
+ <Py3DllName>python3$(PyDebugExt)</Py3DllName>
 
 <!-- The version and platform tag to include in .pyd filenames -->
 <PydTag Condition="$(ArchName) == 'win32'">.cp$(MajorVersionNumber)$(MinorVersionNumber)-win32</PydTag>
diff --git a/Python/dynload_win.c b/Python/dynload_win.c
index 51325be658af8..8d67d2e7bad6c 100644
--- a/Python/dynload_win.c
+++ b/Python/dynload_win.c
@@ -192,9 +192,7 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
 char funcname[258], *import_python;
 const wchar_t *wpathname;
 
-#ifndef _DEBUG
 _Py_CheckPython3();
-#endif
 
 wpathname = _PyUnicode_AsUnicode(pathname);
 if (wpathname == NULL)


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /