diff options
author | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2010-08-31 08:23:30 (GMT) |
---|---|---|
committer | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2010-09-03 08:22:25 (GMT) |
commit | 5738dcd705e7edde816940f9c0ab2c364c81ad20 (patch) | |
tree | e6be0a4b0f11289a7f0e8f6b4d4cce1de28aee8e /src/corelib/plugin/qsystemlibrary.cpp | |
parent | dac9e5dd5644d29d6a8dde752e7c594727f16661 (diff) | |
download | Qt-5738dcd705e7edde816940f9c0ab2c364c81ad20.zip Qt-5738dcd705e7edde816940f9c0ab2c364c81ad20.tar.gz Qt-5738dcd705e7edde816940f9c0ab2c364c81ad20.tar.bz2 |
Ensure that we load system libraries from the correct location.
This was a security hole that has been there for a while, but the
public awareness have recently rised so the threat is more imminent
now.
The solution is to fix all places where we dynamically load system
libraries. More specifically, we now load all system libraries with
an absolute path that points to a library in the system directory
(usually c:\windows\system32).
We therefore introduce a small class named QSystemLibrary that only loads
libraries located in the system path. This shares some of the API with
QLibrary (in order to make the patch as small as possible).
We don't fix QLibrary due to risk of regressions. In
addition, applications can fix the code that calls QLibrary themselves.
The problem does not apply to Windows CE, since the search order is
documented as not searching in the current directory.
However, it touches some CE-specific code - therefore QSystemLibrary
is sometimes used on WinCE (however, it will just do a normal
LoadLibrary() since its safe anyway).
This change does not affect the testability plugin (it is not clearly
documented where that plugin is located, and the plugin should never
be used in production code anyway)
Loading OpenSSL libraries
The ssl libraries are handled specially, and searched in this order
(we cannot expect them to always be in the system folder):
1. Application path
2. System libraries path
3. Trying all paths inside the PATH environment variable
Task-number: QT-3825
Reviewed-by: Thiago Macieira
Reviewed-by: Peter Hartmann
Diffstat (limited to 'src/corelib/plugin/qsystemlibrary.cpp')
-rw-r--r-- | src/corelib/plugin/qsystemlibrary.cpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/corelib/plugin/qsystemlibrary.cpp b/src/corelib/plugin/qsystemlibrary.cpp new file mode 100644 index 0000000..7e9fdde --- /dev/null +++ b/src/corelib/plugin/qsystemlibrary.cpp @@ -0,0 +1,90 @@ +#include "qsystemlibrary_p.h" +#include <QtCore/qvarlengtharray.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qfileinfo.h> + +/*! + + \internal + \class QSystemLibrary + + The purpose of this class is to load only libraries that are located in + well-known and trusted locations on the filesystem. It does not suffer from + the security problem that QLibrary has, therefore it will never search in + the current directory. + + The search order is the same as the order in DLL Safe search mode Windows, + except that we don't search: + * The current directory + * The 16-bit system directory. (normally c:\windows\system) + * The Windows directory. (normally c:\windows) + + This means that the effective search order is: + 1. Application path. + 2. System libraries path. + 3. Trying all paths inside the PATH environment variable. + + Note, when onlySystemDirectory is true it will skip 1) and 3). + + DLL Safe search mode is documented in the "Dynamic-Link Library Search + Order" document on MSDN. + + Since library loading code is sometimes shared between Windows and WinCE, + this class can also be used on WinCE. However, its implementation just + calls the LoadLibrary() function. This is ok since it is documented as not + loading from the current directory on WinCE. This behaviour is documented + in the documentation for LoadLibrary for Windows CE at MSDN. + (http://msdn.microsoft.com/en-us/library/ms886736.aspx) +*/ +#if !defined(QT_BOOTSTRAPPED) +extern QString qAppFileName(); +#endif + +static QString qSystemDirectory() +{ + QVarLengthArray<wchar_t, MAX_PATH> fullPath; + + UINT retLen = ::GetSystemDirectory(fullPath.data(), MAX_PATH); + if (retLen > MAX_PATH) { + fullPath.resize(retLen); + retLen = ::GetSystemDirectory(fullPath.data(), retLen); + } + // in some rare cases retLen might be 0 + return QString::fromWCharArray(fullPath.constData(), int(retLen)); +} + +HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirectory/*= true*/) +{ +#if defined(Q_OS_WINCE) + return ::LoadLibrary(lpFileName); +#else + QStringList searchOrder; + +#if !defined(QT_BOOTSTRAPPED) + if (!onlySystemDirectory) + searchOrder << QFileInfo(qAppFileName()).path(); +#endif + searchOrder << qSystemDirectory(); + + if (!onlySystemDirectory) { + const QString PATH(QLatin1String(qgetenv("PATH").constData())); + searchOrder << PATH.split(QLatin1Char(';'), QString::SkipEmptyParts); + } + QString fileName = QString::fromWCharArray(libraryName); + fileName.append(QLatin1String(".dll")); + + // Start looking in the order specified + for (int i = 0; i < searchOrder.count(); ++i) { + QString fullPathAttempt = searchOrder.at(i); + if (!fullPathAttempt.endsWith(QLatin1Char('\\'))) { + fullPathAttempt.append(QLatin1Char('\\')); + } + fullPathAttempt.append(fileName); + HINSTANCE inst = ::LoadLibrary((const wchar_t *)fullPathAttempt.utf16()); + if (inst != 0) + return inst; + } + return 0; +#endif +} + |