8000 [3.7] bpo-29778: Ensure python3.dll is loaded from correct locations … · python/cpython@110dd15 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 110dd15

Browse files
authored
[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
1 parent b98e779 commit 110dd15

File tree

5 files changed

+81
-72
lines changed

5 files changed

+81
-72
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Ensure :file:`python3.dll` is loaded from correct locations when Python is
2+
embedded (CVE-2020-15523).

PC/getpathp.c

Lines changed: 75 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -161,27 +161,37 @@ reduce(wchar_t *dir)
161161
static int
162162
change_ext(wchar_t *dest, const wchar_t *src, const wchar_t *ext)
163163
{
164-
size_t src_len = wcsnlen_s(src, MAXPATHLEN+1);
165-
size_t i = src_len;
166-
if (i >= MAXPATHLEN+1) {
167-
Py_FatalError("buffer overflow in getpathp.c's reduce()");
168-
}
164+
if (src && src != dest) {
165+
size_t src_len = wcsnlen_s(src, MAXPATHLEN+1);
166+
size_t i = src_len;
167+
if (i >= MAXPATHLEN+1) {
168+
Py_FatalError("buffer overflow in getpathp.c's reduce()");
169+
}
169170

170-
while (i > 0 && src[i] != '.' && !is_sep(src[i]))
171-
--i;
171+
while (i > 0 && src[i] != '.' && !is_sep(src[i]))
172+
--i;
172173

173-
if (i == 0) {
174-
dest[0] = '\0';
175-
return -1;
176-
}
174+
if (i == 0) {
175+
dest[0] = '\0';
176+
return -1;
177+
}
178+
179+
if (is_sep(src[i])) {
180+
i = src_len;
181+
}
177182

178-
if (is_sep(src[i])) {
179-
i = src_len;
183+
if (wcsncpy_s(dest, MAXPATHLEN+1, src, i)) {
184+
dest[0] = '\0';
185+
return -1;
186+
}
187+
} else {
188+
wchar_t *s = wcsrchr(dest, L'.');
189+
if (s) {
190+
s[0] = '\0';
191+
}
180192
}
181193

182-
if (wcsncpy_s(dest, MAXPATHLEN+1, src, i) ||
183-
wcscat_s(dest, MAXPATHLEN+1, ext))
184-
{
194+
if (wcscat_s(dest, MAXPATHLEN+1, ext)) {
185195
dest[0] = '\0';
186196
return -1;
187197
}
@@ -337,6 +347,19 @@ search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path, const wchar_t *lan
337347
}
338348

339349

350+
static int
351+
get_dllpath(wchar_t *dllpath)
352+
{
353+
#ifdef Py_ENABLE_SHARED
354+
extern HANDLE PyWin_DLLhModule;
355+
if (PyWin_DLLhModule && GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN)) {
356+
return 0;
357+
}
358+
#endif
359+
return -1;
360+
}
361+
362+
340363
#ifdef Py_ENABLE_SHARED
341364

342365
/* a string loaded from the DLL at startup.*/
@@ -509,31 +532,6 @@ getpythonregpath(HKEY keyBase, int skipcore)
509532
#endif /* Py_ENABLE_SHARED */
510533

511534

512-
static _PyInitError
513-
get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config)
514-
{
515-
wchar_t dll_path[MAXPATHLEN+1];
516-
memset(dll_path, 0, sizeof(dll_path));
517-
518-
#ifdef Py_ENABLE_SHARED
519-
extern HANDLE PyWin_DLLhModule;
520-
if (PyWin_DLLhModule) {
521-
if (!GetModuleFileNameW(PyWin_DLLhModule, dll_path, MAXPATHLEN)) {
522-
dll_path[0] = 0;
523-
}
524-
}
525-
#else
526-
dll_path[0] = 0;
527-
#endif
528-
529-
config->dll_path = _PyMem_RawWcsdup(dll_path);
530-
if (config->dll_path == NULL) {
531-
return _Py_INIT_NO_MEMORY();
532-
}
533-
return _Py_INIT_OK();
534-
}
535-
536-
537535
static _PyInitError
538536
get_program_full_path(const _PyCoreConfig *core_config,
539537
PyCalculatePath *calculate, _PyPathConfig *config)
@@ -675,12 +673,11 @@ calculate_init(PyCalculatePath *calculate,
675673
static int
676674
get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config)
677675
{
678-
if (config->dll_path[0]) {
679-
if (!change_ext(spbuffer, config->dll_path, L"._pth") &&
680-
exists(spbuffer))
681-
{
682-
return 1;
683-
}
676+
if (get_dllpath(spbuffer) &&
677+
!change_ext(spbuffer, spbuffer, L"._pth") &&
678+
exists(spbuffer))
679+
{
680+
return 1;
684681
}
685682
if (config->program_full_path[0]) {
686683
if (!change_ext(spbuffer, config->program_full_path, L"._pth") &&
@@ -967,11 +964,6 @@ calculate_path_impl(const _PyCoreConfig *core_config,
967964
{
968965
_PyInitError err;
969966

970-
err = get_dll_path(calculate, config);
971-
if (_Py_INIT_FAILED(err)) {
972-
return err;
973-
}
974-
975967
err = get_program_full_path(core_config, calculate, config);
976968
if (_Py_INIT_FAILED(err)) {
977969
return err;
@@ -992,9 +984,13 @@ calculate_path_impl(const _PyCoreConfig *core_config,
992984
calculate_pyvenv_file(calculate);
993985

994986
/* Calculate zip archive path from DLL or exe path */
995-
change_ext(calculate->zip_path,
996-
config->dll_path[0] ? config->dll_path : config->program_full_path,
997-
L".zip");
987+
if (get_dllpath(calculate->zip_path) ||
988+
change_ext(calculate->zip_path, calculate->zip_path, L".zip"))
989+
{
990+
if (change_ext(calculate->zip_path, config->program_full_path, L".zip")) {
991+
calculate->zip_path[0] = L'\0';
992+
}
993+
}
998994

999995
calculate_home_prefix(calculate, prefix);
1000996

@@ -1054,28 +1050,39 @@ int
10541050
_Py_CheckPython3(void)
10551051
{
10561052
wchar_t py3path[MAXPATHLEN+1];
1057-
wchar_t *s;
10581053
if (python3_checked) {
10591054
return hPython3 != NULL;
10601055
}
10611056
python3_checked = 1;
10621057

10631058
/* If there is a python3.dll next to the python3y.dll,
1064-
assume this is a build tree; use that DLL */
1065-
wcscpy(py3path, _Py_path_config.dll_path);
1066-
s = wcsrchr(py3path, L'\\');
1067-
if (!s) {
1068-
s = py3path;
1059+
use that DLL */
1060+
if (!get_dllpath(py3path)) {
1061+
reduce(py3path);
1062+
join(py3path, PY3_DLLNAME);
1063+
hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
1064+
if (hPython3 != NULL) {
1065+
return 1;
1066+
}
10691067
}
1070-
wcscpy(s, L"\\python3.dll");
1071-
hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
1072-
if (hPython3 != NULL) {
1073-
return 1;
1068+
1069+
/* If we can locate python3.dll in our application dir,
1070+
use that DLL */
1071+
wcscpy(py3path, Py_GetPrefix());
1072+
if (py3path[0]) {
1073+
join(py3path, PY3_DLLNAME);
1074+
hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
1075+
if (hPython3 != NULL) {
1076+
return 1;
1077+
}
10741078
}
10751079

1076-
/* Check sys.prefix\DLLs\python3.dll */
1080+
/* For back-compat, also search {sys.prefix}\DLLs, though
1081+
that has not been a normal install layout for a while */
10771082
wcscpy(py3path, Py_GetPrefix());
1078-
wcscat(py3path, L"\\DLLs\\python3.dll");
1079-
hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
1083+
if (py3path[0]) {
1084+
join(py3path, L"DLLs\\" PY3_DLLNAME);
1085+
hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
1086+
}
10801087
return hPython3 != NULL;
10811088
}

PCbuild/pyproject.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@
2424
<_PlatformPreprocessorDefinition>_WIN32;</_PlatformPreprocessorDefinition>
2525
<_PlatformPreprocessorDefinition Condition="$(Platform) == 'x64'">_WIN64;_M_X64;</_PlatformPreprocessorDefinition>
2626
<_PydPreprocessorDefinition Condition="$(TargetExt) == '.pyd'">Py_BUILD_CORE_MODULE;</_PydPreprocessorDefinition>
27+
<_Py3NamePreprocessorDefinition>PY3_DLLNAME=L"$(Py3DllName)";</_Py3NamePreprocessorDefinition>
2728
</PropertyGroup>
2829
<ItemDefinitionGroup>
2930
<ClCompile>
3031
<AdditionalIncludeDirectories>$(PySourcePath)Include;$(PySourcePath)PC;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
31-
<PreprocessorDefinitions>WIN32;$(_PlatformPreprocessorDefinition)$(_DebugPreprocessorDefinition)$(_PydPreprocessorDefinition)%(PreprocessorDefinitions)</PreprocessorDefinitions>
32-
32+
<PreprocessorDefinitions>WIN32;$(_Py3NamePreprocessorDefinition)$(_PlatformPreprocessorDefinition)$(_DebugPreprocessorDefinition)$(_PydPreprocessorDefinition)%(PreprocessorDefinitions)</PreprocessorDefinitions>
3333
<Optimization>MaxSpeed</Optimization>
3434
<IntrinsicFunctions>true</IntrinsicFunctions>
3535
<StringPooling>true</StringPooling>

PCbuild/python.props

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@
177177

178178
<!-- The name of the resulting pythonXY.dll (without the extension) -->
179179
<PyDllName>python$(MajorVersionNumber)$(MinorVersionNumber)$(PyDebugExt)</PyDllName>
180+
<!-- The name of the resulting pythonX.dll (without the extension) -->
181+
<Py3DllName>python3$(PyDebugExt)</Py3DllName>
180182

181183
<!-- The version and platform tag to include in .pyd filenames -->
182184
<PydTag Condition="$(ArchName) == 'win32'">.cp$(MajorVersionNumber)$(MinorVersionNumber)-win32</PydTag>

Python/dynload_win.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,7 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
192192
char funcname[258], *import_python;
193193
const wchar_t *wpathname;
194194

195-
#ifndef _DEBUG
196195
_Py_CheckPython3();
197-
#endif
198196

199197
wpathname = _PyUnicode_AsUnicode(pathname);
200198
if (wpathname == NULL)

0 commit comments

Comments
 (0)
0