Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
dd55a5f
bpo-36085: Enable better DLL resolution on Windows
zooba Mar 13, 2019
b01f83b
Improves error handling
zooba Mar 13, 2019
51ade83
Improve ctypes error message and enables adjacent dependency loading
zooba Mar 13, 2019
e8b54a4
Remove invalid ctypes flag
zooba Mar 14, 2019
98db2ef
Merge remote-tracking branch 'cpython/master' into bpo-36085
zooba Mar 14, 2019
49b757b
Merge remote-tracking branch 'cpython/master' into bpo-36085
zooba Mar 18, 2019
ae48b59
Fix uninitialised variable
zooba Mar 18, 2019
3f29c0a
Add NEWS and make nicer interface for add_dll_directory
zooba Mar 18, 2019
e022bb8
Add after_test step to collect more info
zooba Mar 21, 2019
56fa1bd
Change to on_finish
zooba Mar 21, 2019
c50b0ea
Attempt a workaround for the test
zooba Mar 21, 2019
4fd36e4
Try a broader workaround
zooba Mar 21, 2019
88ef129
Handle errors in workaround
zooba Mar 21, 2019
34614af
Test retrieving specific counter instead of all counters
zooba Mar 22, 2019
8311618
Remove default DLL directory setting
zooba Mar 22, 2019
8823f31
Add dll_load_flags to ctypes.CDLL for use on Windows
zooba Mar 26, 2019
5882477
Remove unused import
zooba Mar 26, 2019
f867be2
Remove logging from AppVeyor definition
zooba Mar 26, 2019
f82fce4
Update what's new and ctypes docs
zooba Mar 27, 2019
492ab38
Adds ctypes test for new parameter and add_dll_directory
zooba Mar 27, 2019
01b9c76
Improve ctypes test
zooba Mar 27, 2019
92e1983
Add bpo reference to What's New
zooba Mar 27, 2019
e654a09
Ensure test cleans up added DLL directory
zooba Mar 27, 2019
4a1c712
Improve documentation
zooba Mar 28, 2019
1af7230
Improve error handling
zooba Mar 28, 2019
864c34e
Merge remote-tracking branch 'cpython/master' into bpo-36085
zooba Mar 28, 2019
6ae0b6f
Fix calling convention for 32-bit builds
zooba Mar 28, 2019
7cf3055
Adds import test
zooba Mar 29, 2019
6b1d038
Ensure CRT DLLs are copied for test
zooba Mar 29, 2019
a9f7ae0
Remove trailing whitespace
zooba Mar 29, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Modules/_ctypes/callproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1287,7 +1287,10 @@ static PyObject *load_library(PyObject *self, PyObject *args)
return NULL;

Py_BEGIN_ALLOW_THREADS
hMod = LoadLibraryW(name);
/* bpo-36085: Limit DLL search directories to avoid pre-loading
Comment thread
zooba marked this conversation as resolved.
* attacks and enable use of the AddDllDirectory function.
*/
hMod = LoadLibraryExW(name, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
Py_END_ALLOW_THREADS

if (!hMod)
Expand Down
92 changes: 91 additions & 1 deletion Modules/clinic/posixmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,25 @@ static _PyInitError
pymain_init(const _PyArgv *args, PyInterpreterState **interp_p)
{
_PyInitError err;
#ifdef MS_WINDOWS
HMODULE hKernel32;
typedef BOOL (*PSetDefaultDllDirectories)(DWORD directoryFlags);
PSetDefaultDllDirectories SetDefaultDllDirectories;
#endif

/* bpo-36085: Limit DLL resolution to avoid pre-loading attacks and
* enable use of the AddDllDirectory function.
* Embedders will need to call this themselves if they want the
* same functionality, but we always use it via ctypes and importdl
* regardless of whether the process-wide default has been set.
*/
#ifdef MS_WINDOWS
if ((hKernel32 = GetModuleHandleW(L"kernel32.dll")) &&
(SetDefaultDllDirectories = (PSetDefaultDllDirectories)GetProcAddress(
hKernel32, "SetDefaultDllDirectories"))) {
(*SetDefaultDllDirectories)(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
}
#endif

err = _PyRuntime_Initialize();
if (_Py_INIT_FAILED(err)) {
Expand Down
97 changes: 97 additions & 0 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -13161,6 +13161,99 @@ os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
}
#endif /* HAVE_GETRANDOM_SYSCALL */

#ifdef MS_WINDOWS
/* bpo-36085: Helper functions for managing DLL search directories
* on win32
*/

typedef DLL_DIRECTORY_COOKIE (*PAddDllDirectory)(PCWSTR newDirectory);
typedef BOOL (*PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);

/*[clinic input]
os.add_dll_directory

path: path_t

Add a path to the DLL search path.

This search path is used when resolving dependencies for imported
extension modules (the module itself is resolved through sys.path),
and also by ctypes.

Returns an opaque value that may be passed to os.remove_dll_directory
to remove this directory from the search path.
[clinic start generated code]*/

static PyObject *
os_add_dll_directory_impl(PyObject *module, path_t *path)
/*[clinic end generated code: output=8e498e193ddce271 input=bae8b8ffda652600]*/
{
HMODULE hKernel32;
PAddDllDirectory AddDllDirectory;
DLL_DIRECTORY_COOKIE cookie = 0;

/* For Windows 7, we have to load this. As this will be a fairly
infrequent operation, just do it each time. Kernel32 is always
loaded. */
Py_BEGIN_ALLOW_THREADS
if ((hKernel32 = GetModuleHandleW(L"kernel32")) &&
(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
hKernel32, "AddDllDirectory"))) {
cookie = (*AddDllDirectory)(path->wide);
}
Py_END_ALLOW_THREADS

if (!cookie) {
return win32_error_object("AddDllDirectory", path->object);
}

return PyCapsule_New(cookie, "DLL directory cookie", NULL);
}

/*[clinic input]
os.remove_dll_directory

cookie: object

Removes a path from the DLL search path.

The parameter is an opaque value that was returned from
os.add_dll_directory. You can only remove directories that you added
yourself.
[clinic start generated code]*/

static PyObject *
os_remove_dll_directory_impl(PyObject *module, PyObject *cookie)
/*[clinic end generated code: output=cfbb576332208c2a input=178939bb10c7a6cf]*/
{
HMODULE hKernel32;
PRemoveDllDirectory RemoveDllDirectory;
DLL_DIRECTORY_COOKIE cookieValue;

if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
Comment thread
zooba marked this conversation as resolved.
PyErr_SetString(PyExc_TypeError,
"Provided cookie was not returned from os.add_dll_directory");
return NULL;
}

cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
cookie, "DLL directory cookie");

/* For Windows 7, we have to load this. As this will be a fairly
infrequent operation, just do it each time. Kernel32 is always
loaded. */
Py_BEGIN_ALLOW_THREADS
if ((hKernel32 = GetModuleHandleW(L"kernel32")) &&
(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
hKernel32, "RemoveDllDirectory"))) {
(*RemoveDllDirectory)(cookieValue);
Comment thread
zooba marked this conversation as resolved.
Outdated
}
Py_END_ALLOW_THREADS

Py_RETURN_NONE;
}

#endif

static PyMethodDef posix_methods[] = {

Expand Down Expand Up @@ -13349,6 +13442,10 @@ static PyMethodDef posix_methods[] = {
OS_SCANDIR_METHODDEF
OS_FSPATH_METHODDEF
OS_GETRANDOM_METHODDEF
#ifdef MS_WINDOWS
OS_ADD_DLL_DIRECTORY_METHODDEF
OS_REMOVE_DLL_DIRECTORY_METHODDEF
#endif
{NULL, NULL} /* Sentinel */
};

Expand Down
10 changes: 6 additions & 4 deletions Python/dynload_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,14 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
#if HAVE_SXS
cookie = _Py_ActivateActCtx();
#endif
/* We use LoadLibraryEx so Windows looks for dependent DLLs
in directory of pathname first. */
/* XXX This call doesn't exist in Windows CE */
/* bpo-36085: We use LoadLibraryEx with restricted search paths
to avoid DLL preloading attacks and enable use of the
AddDllDirectory function. We add SEARCH_DLL_LOAD_DIR to
ensure DLLs adjacent to the PYD are preferred. */
Py_BEGIN_ALLOW_THREADS
hDLL = LoadLibraryExW(wpathname, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
Py_END_ALLOW_THREADS
#if HAVE_SXS
_Py_DeactivateActCtx(cookie);
Expand Down