diff options
author | Fredrik Orderud <fredrik.orderud@ge.com> | 2020-04-13 15:50:32 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2020-04-15 13:18:48 +0000 |
commit | 1bee5937bc51af45776c4ad9083f4a67afbaf109 (patch) | |
tree | a0196ddbfa775c7ab123d13bc5b892e1e16b6043 | |
parent | c7e8ee4e622ad90c6860994a0bb8eaa9c8c80566 (diff) |
Windows: Make QStandardPaths::writableLocation low-integrity aware
Return %USERPROFILE%\AppData\LocalLow instead of %USERPROFILE%\AppData\Local
when running in a low-integrity process.
[ChangeLog][QtCore][QStandardPaths] When used in a low-integrity process
on Windows, QStandardPaths::writableLocation returns respective low-integrity
paths.
Fixes: QTBUG-83453
Change-Id: Ie5e4625a34d08e4ef54be4ba45b2dae9e60feb63
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r-- | src/corelib/io/qstandardpaths_win.cpp | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index c2c3b2702b..5055f4020c 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -50,6 +50,7 @@ #include <qt_windows.h> #include <shlobj.h> #include <intshcut.h> +#include <qvarlengtharray.h> #ifndef QT_NO_STANDARDPATHS @@ -92,9 +93,36 @@ static inline void appendTestMode(QString &path) path += QLatin1String("/qttest"); } +static bool isProcessLowIntegrity() { +#ifdef Q_CC_MINGW + // GetCurrentProcessToken was introduced in MinGW w64 in v7 + // Disable function until Qt CI is updated + return false; +#else + HANDLE process_token = GetCurrentProcessToken(); // non-leaking pseudo-handle + + QVarLengthArray<char,256> token_info_buf(256); + auto* token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data()); + DWORD token_info_length = token_info_buf.size(); + if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_info, token_info_length, &token_info_length)) { + // grow bufer and retry GetTokenInformation + token_info_buf.resize(token_info_length); + token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data()); + if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_info, token_info_length, &token_info_length)) + return false; // assume "normal" process + } + + // The GetSidSubAuthorityCount return-code is undefined on failure, so + // there's no point in checking before dereferencing + DWORD integrity_level = *GetSidSubAuthority(token_info->Label.Sid, *GetSidSubAuthorityCount(token_info->Label.Sid) - 1); + return (integrity_level < SECURITY_MANDATORY_MEDIUM_RID); +#endif +} + // Map QStandardPaths::StandardLocation to KNOWNFOLDERID of SHGetKnownFolderPath() static GUID writableSpecialFolderId(QStandardPaths::StandardLocation type) { + // folders for medium & high integrity processes static const GUID folderIds[] = { FOLDERID_Desktop, // DesktopLocation FOLDERID_Documents, // DocumentsLocation @@ -114,9 +142,34 @@ static GUID writableSpecialFolderId(QStandardPaths::StandardLocation type) FOLDERID_RoamingAppData,// AppDataLocation ("Roaming" path) FOLDERID_LocalAppData, // AppConfigLocation ("Local" path) }; - Q_STATIC_ASSERT(sizeof(folderIds) / sizeof(folderIds[0]) == size_t(QStandardPaths::AppConfigLocation + 1)); - return size_t(type) < sizeof(folderIds) / sizeof(folderIds[0]) ? folderIds[type] : GUID(); + + // folders for low integrity processes + static const GUID folderIds_li[] = { + FOLDERID_Desktop, // DesktopLocation + FOLDERID_Documents, // DocumentsLocation + FOLDERID_Fonts, // FontsLocation + FOLDERID_Programs, // ApplicationsLocation + FOLDERID_Music, // MusicLocation + FOLDERID_Videos, // MoviesLocation + FOLDERID_Pictures, // PicturesLocation + GUID(), GUID(), // TempLocation/HomeLocation + FOLDERID_LocalAppDataLow,// AppLocalDataLocation ("Local" path), AppLocalDataLocation = DataLocation + GUID(), // CacheLocation + FOLDERID_LocalAppDataLow,// GenericDataLocation ("Local" path) + GUID(), // RuntimeLocation + FOLDERID_LocalAppDataLow,// ConfigLocation ("Local" path) + GUID(), GUID(), // DownloadLocation/GenericCacheLocation + FOLDERID_LocalAppDataLow,// GenericConfigLocation ("Local" path) + FOLDERID_RoamingAppData, // AppDataLocation ("Roaming" path) + FOLDERID_LocalAppDataLow,// AppConfigLocation ("Local" path) + }; + Q_STATIC_ASSERT(sizeof(folderIds_li) == sizeof(folderIds)); + + static bool low_integrity_process = isProcessLowIntegrity(); + if (size_t(type) < sizeof(folderIds) / sizeof(folderIds[0])) + return low_integrity_process ? folderIds_li[type] : folderIds[type]; + return GUID(); } // Convenience for SHGetKnownFolderPath(). |