summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@python.org>2020-07-06 18:55:43 (GMT)
committerGitHub <noreply@github.com>2020-07-06 18:55:43 (GMT)
commit46cbf6148a46883110883488d3e9febbe46ba861 (patch)
tree1ed21b0a6c6161ffa67420dbdfecec67a0cb951d
parentcfc7ff8d05f7a949a88b8a8dd506fb5c1c30d3e9 (diff)
downloadcpython-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.rst2
-rw-r--r--PC/getpathp.c117
-rw-r--r--PCbuild/pyproject.props4
-rw-r--r--PCbuild/python.props2
-rw-r--r--Python/dynload_win.c2
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)