diff options
author | Steve Dower <steve.dower@python.org> | 2020-07-06 18:55:43 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-06 18:55:43 (GMT) |
commit | 46cbf6148a46883110883488d3e9febbe46ba861 (patch) | |
tree | 1ed21b0a6c6161ffa67420dbdfecec67a0cb951d | |
parent | cfc7ff8d05f7a949a88b8a8dd506fb5c1c30d3e9 (diff) | |
download | cpython-46cbf6148a46883110883488d3e9febbe46ba861.zip cpython-46cbf6148a46883110883488d3e9febbe46ba861.tar.gz cpython-46cbf6148a46883110883488d3e9febbe46ba861.tar.bz2 |
[3.6] bpo-29778: Ensure python3.dll is loaded from correct locations when Python is embedded (GH-21298) (#21354)
* bpo-29778: Ensure python3.dll is loaded from correct locations when Python is embedded (GH-21298)
* bpo-29778: Ensure python3.dll is loaded from correct locations when Python is embedded.
* Add CVE number
* Updates for 3.6
-rw-r--r-- | Misc/NEWS.d/next/Security/2020-07-03-17-21-37.bpo-29778.cR_fGS.rst | 2 | ||||
-rw-r--r-- | PC/getpathp.c | 117 | ||||
-rw-r--r-- | PCbuild/pyproject.props | 4 | ||||
-rw-r--r-- | PCbuild/python.props | 2 | ||||
-rw-r--r-- | Python/dynload_win.c | 2 |
5 files changed, 81 insertions, 46 deletions
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 0000000..998ffb1 --- /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 e86c376..f6f362c 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -118,7 +118,6 @@ static wchar_t prefix[MAXPATHLEN+1]; static wchar_t progpath[MAXPATHLEN+1]; -static wchar_t dllpath[MAXPATHLEN+1]; static wchar_t *module_search_path = NULL; @@ -150,24 +149,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; } @@ -304,6 +316,20 @@ search_for_prefix(wchar_t *argv0_path, const wchar_t *landmark) return 0; } + +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.*/ @@ -467,15 +493,6 @@ get_progpath(void) wchar_t *path = _wgetenv(L"PATH"); wchar_t *prog = Py_GetProgramName(); -#ifdef Py_ENABLE_SHARED - extern HANDLE PyWin_DLLhModule; - /* static init of progpath ensures final char remains \0 */ - if (PyWin_DLLhModule) - if (!GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN)) - dllpath[0] = 0; -#else - dllpath[0] = 0; -#endif if (GetModuleFileNameW(NULL, modulepath, MAXPATHLEN)) { canonicalize(progpath, modulepath); return; @@ -693,7 +710,7 @@ calculate_path(void) { wchar_t spbuffer[MAXPATHLEN+1]; - if ((dllpath[0] && !change_ext(spbuffer, dllpath, L"._pth") && exists(spbuffer)) || + if ((!get_dllpath(spbuffer) && !change_ext(spbuffer, spbuffer, L"._pth") && exists(spbuffer)) || (progpath[0] && !change_ext(spbuffer, progpath, L"._pth") && exists(spbuffer))) { if (!read_pth_file(spbuffer, prefix, &Py_IsolatedFlag, &Py_NoSiteFlag)) { @@ -737,7 +754,11 @@ calculate_path(void) } /* Calculate zip archive path from DLL or exe path */ - change_ext(zip_path, dllpath[0] ? dllpath : progpath, L".zip"); + if (!get_dllpath(zip_path)) { + change_ext(zip_path, zip_path, L".zip"); + } else { + change_ext(zip_path, progpath, L".zip"); + } if (pythonhome == NULL || *pythonhome == '\0') { if (zip_path[0] && exists(zip_path)) { @@ -919,8 +940,6 @@ calculate_path(void) } -/* External interface */ - void Py_SetPath(const wchar_t *path) { @@ -981,25 +1000,39 @@ int _Py_CheckPython3() { wchar_t py3path[MAXPATHLEN+1]; - wchar_t *s; - if (python3_checked) + 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, dllpath); - s = wcsrchr(py3path, L'\\'); - if (!s) - s = py3path; - wcscpy(s, L"\\python3.dll"); - hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - if (hPython3 != NULL) - return 1; + 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; + } + } + + /* 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 1602ebf..104a9d8 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 3022ca5..b82425e 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -175,6 +175,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 0fdf77f..a307188 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) |