Don't follow junctions when recursing directories.
When deleting directories recursively, an elevated custom action following junctions in a user-writable location could recurse into any directory, including some that you might not want to be deleted. Therefore, avoid recursing into directories that are actually junctions (aka "reparse points"). This applies to: - The RemoveFoldersEx custom action (which doesn't actually do deletions but would instruct elevated MSI to delete on your behalf). - DTF's custom action runner.
Rob Mensching committed
Mar 22, 2024 at 11:55 UTC
e84b6768772c01e44dd55fb583cf78388ec7e48a
2 files changed
+13
-3
src/dtf/SfxCA/SfxUtil.cpp
+3
-1
@@ -93,7 +93,9 @@ bool DeleteDirectory(const wchar_t* szDir)
93
StringCchCopy(szPath + cchDir + 1, cchPathBuf - (cchDir + 1), fd.cFileName);
94
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
95
{
96
- if (wcscmp(fd.cFileName, L".") != 0 && wcscmp(fd.cFileName, L"..") != 0)
96
+ if (wcscmp(fd.cFileName, L".") != 0
97
+ && wcscmp(fd.cFileName, L"..") != 0
98
+ && ((fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0))
99
{
100
DeleteDirectory(szPath);
101
}
src/ext/Util/ca/RemoveFoldersEx.cpp
+10
-2
@@ -38,6 +38,14 @@ static HRESULT RecursePath(
38
}
39
#endif
40
41
+ // Do NOT follow junctions.
42
+ DWORD dwAttributes = ::GetFileAttributesW(wzPath);
43
+ if (dwAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
44
+ {
45
+ WcaLog(LOGMSG_STANDARD, "Path is a junction; skipping: %ls", wzPath);
46
+ ExitFunction();
47
+ }
48
+
49
// First recurse down to all the child directories.
50
hr = StrAllocFormatted(&sczSearch, L"%s*", wzPath);
51
ExitOnFailure(hr, "Failed to allocate file search string in path: %S", wzPath);
@@ -210,10 +218,10 @@ extern "C" UINT WINAPI WixRemoveFoldersEx(
218
219
hr = PathExpand(&sczExpandedPath, sczPath, PATH_EXPAND_ENVIRONMENT);
220
ExitOnFailure(hr, "Failed to expand path: %S for row: %S", sczPath, sczId);
213
-
221
+
222
hr = PathBackslashTerminate(&sczExpandedPath);
223
ExitOnFailure(hr, "Failed to backslash-terminate path: %S", sczExpandedPath);
216
-
224
+
225
WcaLog(LOGMSG_STANDARD, "Recursing path: %S for row: %S.", sczExpandedPath, sczId);
226
hr = RecursePath(sczExpandedPath, sczId, sczComponent, sczProperty, iMode, f64BitComponent, &dwCounter, &hTable, &hColumns);
227
ExitOnFailure(hr, "Failed while navigating path: %S for row: %S", sczPath, sczId);