diff options
author | Rob Mensching <rob@firegiant.com> | 2025-02-11 05:21:34 -0800 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2025-02-11 15:49:33 -0800 |
commit | f2e9af96142439ebfdbc1e884335bb8874f8a427 (patch) | |
tree | f3ffd15660a7041d1f70d793e2b2200ccbe42af5 /src/burn/engine/cache.cpp | |
parent | 81fb512834c65b0a8f99c3a266879c476e382875 (diff) | |
download | wix-f2e9af96142439ebfdbc1e884335bb8874f8a427.tar.gz wix-f2e9af96142439ebfdbc1e884335bb8874f8a427.tar.bz2 wix-f2e9af96142439ebfdbc1e884335bb8874f8a427.zip |
Harden Burn's BootstrapperApplication and elevated engine extraction
Fixes 8914
Diffstat (limited to 'src/burn/engine/cache.cpp')
-rw-r--r-- | src/burn/engine/cache.cpp | 86 |
1 files changed, 61 insertions, 25 deletions
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp index 5a8388c4..16db4a81 100644 --- a/src/burn/engine/cache.cpp +++ b/src/burn/engine/cache.cpp | |||
@@ -112,13 +112,15 @@ static HRESULT CopyEngineToWorkingFolder( | |||
112 | __in_z LPCWSTR wzWorkingFolderName, | 112 | __in_z LPCWSTR wzWorkingFolderName, |
113 | __in_z LPCWSTR wzExecutableName, | 113 | __in_z LPCWSTR wzExecutableName, |
114 | __in BURN_SECTION* pSection, | 114 | __in BURN_SECTION* pSection, |
115 | __deref_out_z_opt LPWSTR* psczEngineWorkingPath | 115 | __out_z LPWSTR* psczEngineWorkingPath, |
116 | __out HANDLE* phEngineWorkingFile | ||
116 | ); | 117 | ); |
117 | static HRESULT CopyEngineWithSignatureFixup( | 118 | static HRESULT CopyEngineWithSignatureFixup( |
118 | __in HANDLE hEngineFile, | 119 | __in HANDLE hEngineFile, |
119 | __in_z LPCWSTR wzEnginePath, | 120 | __in_z LPCWSTR wzEnginePath, |
120 | __in_z LPCWSTR wzTargetPath, | 121 | __in_z LPCWSTR wzTargetPath, |
121 | __in BURN_SECTION* pSection | 122 | __in BURN_SECTION* pSection, |
123 | __out HANDLE* phEngineFile | ||
122 | ); | 124 | ); |
123 | static HRESULT RemoveBundleOrPackage( | 125 | static HRESULT RemoveBundleOrPackage( |
124 | __in BURN_CACHE* pCache, | 126 | __in BURN_CACHE* pCache, |
@@ -915,33 +917,59 @@ extern "C" HRESULT CacheBundleToWorkingDirectory( | |||
915 | __in BOOL fElevated, | 917 | __in BOOL fElevated, |
916 | __in BURN_CACHE* pCache, | 918 | __in BURN_CACHE* pCache, |
917 | __in_z LPCWSTR wzExecutableName, | 919 | __in_z LPCWSTR wzExecutableName, |
918 | __in BURN_SECTION* pSection, | 920 | __in BURN_SECTION* pSection |
919 | __deref_out_z_opt LPWSTR* psczEngineWorkingPath | ||
920 | ) | 921 | ) |
921 | { | 922 | { |
922 | Assert(pCache->fInitializedCache); | 923 | Assert(pCache->fInitializedCache); |
923 | 924 | ||
924 | HRESULT hr = S_OK; | 925 | HRESULT hr = S_OK; |
925 | LPWSTR sczSourcePath = NULL; | 926 | LPWSTR sczSourcePath = NULL; |
927 | LPWSTR sczEngineWorkingPath = NULL; | ||
928 | HANDLE hEngineWorkingFile = INVALID_HANDLE_VALUE; | ||
929 | |||
930 | // If we already cached the engine, bail. | ||
931 | if (pCache->sczBundleEngineWorkingPath && INVALID_HANDLE_VALUE != pCache->hBundleEngineWorkingFile) | ||
932 | { | ||
933 | ExitFunction(); | ||
934 | } | ||
926 | 935 | ||
927 | // Initialize the source. | 936 | // Initialize the source. |
928 | hr = PathForCurrentProcess(&sczSourcePath, NULL); | 937 | hr = PathForCurrentProcess(&sczSourcePath, NULL); |
929 | ExitOnFailure(hr, "Failed to get current process path."); | 938 | ExitOnFailure(hr, "Failed to get current process path."); |
930 | 939 | ||
931 | // If the bundle is running out of the package cache then we don't need to copy it to | 940 | // If the bundle is running out of the package cache then we don't need to copy it to |
932 | // the working folder since we feel safe in the package cache and will run from there. | 941 | // the working folder (and we don't need to lock the file either) since we feel safe |
942 | // in the package cache and will run from there. | ||
933 | if (CacheBundleRunningFromCache(pCache)) | 943 | if (CacheBundleRunningFromCache(pCache)) |
934 | { | 944 | { |
935 | hr = StrAllocString(psczEngineWorkingPath, sczSourcePath, 0); | 945 | hr = StrAllocString(&sczEngineWorkingPath, sczSourcePath, 0); |
936 | ExitOnFailure(hr, "Failed to use current process path as target path."); | 946 | ExitOnFailure(hr, "Failed to copy current process path as bundle engine working path."); |
937 | } | 947 | } |
938 | else // otherwise, carry on putting the bundle in the working folder. | 948 | else // otherwise, carry on putting the bundle in the working folder and lock it. |
939 | { | 949 | { |
940 | hr = CopyEngineToWorkingFolder(fElevated, pCache, sczSourcePath, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczEngineWorkingPath); | 950 | hr = CopyEngineToWorkingFolder(fElevated, pCache, sczSourcePath, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName, pSection, &sczEngineWorkingPath, &hEngineWorkingFile); |
941 | ExitOnFailure(hr, "Failed to copy engine to working folder."); | 951 | ExitOnFailure(hr, "Failed to copy engine to working folder."); |
942 | } | 952 | |
953 | // Close the engine file handle (if we opened it) then reopen it read-only as quickly as possible to lock it. | ||
954 | ReleaseFileHandle(hEngineWorkingFile); | ||
955 | |||
956 | hr = FileCreateWithRetry(sczEngineWorkingPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 30, 100, &hEngineWorkingFile); | ||
957 | ExitOnFailure(hr, "Failed to lock bundle engine file: %ls", sczEngineWorkingPath); | ||
958 | } | ||
959 | |||
960 | // Clean out any previous values (there shouldn't be any). | ||
961 | ReleaseNullStr(pCache->sczBundleEngineWorkingPath); | ||
962 | ReleaseFileHandle(pCache->hBundleEngineWorkingFile); | ||
963 | |||
964 | pCache->sczBundleEngineWorkingPath = sczEngineWorkingPath; | ||
965 | sczEngineWorkingPath = NULL; | ||
966 | |||
967 | pCache->hBundleEngineWorkingFile = hEngineWorkingFile; | ||
968 | hEngineWorkingFile = INVALID_HANDLE_VALUE; | ||
943 | 969 | ||
944 | LExit: | 970 | LExit: |
971 | ReleaseFileHandle(hEngineWorkingFile); | ||
972 | ReleaseStr(sczEngineWorkingPath); | ||
945 | ReleaseStr(sczSourcePath); | 973 | ReleaseStr(sczSourcePath); |
946 | 974 | ||
947 | return hr; | 975 | return hr; |
@@ -1206,9 +1234,14 @@ extern "C" HRESULT CacheRemoveBaseWorkingFolder( | |||
1206 | 1234 | ||
1207 | if (pCache->fInitializedBaseWorkingFolder) | 1235 | if (pCache->fInitializedBaseWorkingFolder) |
1208 | { | 1236 | { |
1237 | // Release the engine file handle if it is open to ensure the working folder can be deleted. | ||
1238 | ReleaseFileHandle(pCache->hBundleEngineWorkingFile); | ||
1239 | |||
1209 | // Try to clean out everything in the working folder. | 1240 | // Try to clean out everything in the working folder. |
1210 | hr = DirEnsureDeleteEx(pCache->sczBaseWorkingFolder, DIR_DELETE_FILES | DIR_DELETE_RECURSE | DIR_DELETE_SCHEDULE); | 1241 | hr = DirEnsureDeleteEx(pCache->sczBaseWorkingFolder, DIR_DELETE_FILES | DIR_DELETE_RECURSE | DIR_DELETE_SCHEDULE); |
1211 | TraceError(hr, "Could not delete bundle engine working folder."); | 1242 | TraceError(hr, "Could not delete bundle engine working folder."); |
1243 | |||
1244 | pCache->fInitializedBaseWorkingFolder = FALSE; | ||
1212 | } | 1245 | } |
1213 | 1246 | ||
1214 | return hr; | 1247 | return hr; |
@@ -1396,6 +1429,8 @@ extern "C" void CacheUninitialize( | |||
1396 | ReleaseStr(pCache->sczBaseWorkingFolder); | 1429 | ReleaseStr(pCache->sczBaseWorkingFolder); |
1397 | ReleaseStr(pCache->sczAcquisitionFolder); | 1430 | ReleaseStr(pCache->sczAcquisitionFolder); |
1398 | ReleaseStr(pCache->sczSourceProcessFolder); | 1431 | ReleaseStr(pCache->sczSourceProcessFolder); |
1432 | ReleaseStr(pCache->sczBundleEngineWorkingPath) | ||
1433 | ReleaseFileHandle(pCache->hBundleEngineWorkingFile) | ||
1399 | 1434 | ||
1400 | memset(pCache, 0, sizeof(BURN_CACHE)); | 1435 | memset(pCache, 0, sizeof(BURN_CACHE)); |
1401 | } | 1436 | } |
@@ -2094,16 +2129,15 @@ static HRESULT CopyEngineToWorkingFolder( | |||
2094 | __in_z LPCWSTR wzWorkingFolderName, | 2129 | __in_z LPCWSTR wzWorkingFolderName, |
2095 | __in_z LPCWSTR wzExecutableName, | 2130 | __in_z LPCWSTR wzExecutableName, |
2096 | __in BURN_SECTION* pSection, | 2131 | __in BURN_SECTION* pSection, |
2097 | __deref_out_z_opt LPWSTR* psczEngineWorkingPath | 2132 | __out_z LPWSTR* psczEngineWorkingPath, |
2133 | __out HANDLE* phEngineWorkingFile | ||
2098 | ) | 2134 | ) |
2099 | { | 2135 | { |
2100 | HRESULT hr = S_OK; | 2136 | HRESULT hr = S_OK; |
2101 | LPWSTR sczWorkingFolder = NULL; | 2137 | LPWSTR sczWorkingFolder = NULL; |
2102 | LPWSTR sczTargetDirectory = NULL; | 2138 | LPWSTR sczTargetDirectory = NULL; |
2103 | LPWSTR sczTargetPath = NULL; | 2139 | LPWSTR sczTargetPath = NULL; |
2104 | LPWSTR sczSourceDirectory = NULL; | 2140 | HANDLE hTargetFile = INVALID_HANDLE_VALUE; |
2105 | LPWSTR sczPayloadSourcePath = NULL; | ||
2106 | LPWSTR sczPayloadTargetPath = NULL; | ||
2107 | 2141 | ||
2108 | hr = CacheEnsureBaseWorkingFolder(fElevated, pCache, &sczWorkingFolder); | 2142 | hr = CacheEnsureBaseWorkingFolder(fElevated, pCache, &sczWorkingFolder); |
2109 | ExitOnFailure(hr, "Failed to create working path to copy engine."); | 2143 | ExitOnFailure(hr, "Failed to create working path to copy engine."); |
@@ -2118,19 +2152,17 @@ static HRESULT CopyEngineToWorkingFolder( | |||
2118 | ExitOnFailure(hr, "Failed to combine working path with engine file name."); | 2152 | ExitOnFailure(hr, "Failed to combine working path with engine file name."); |
2119 | 2153 | ||
2120 | // Copy the engine without any attached containers to the working path. | 2154 | // Copy the engine without any attached containers to the working path. |
2121 | hr = CopyEngineWithSignatureFixup(pSection->hEngineFile, wzSourcePath, sczTargetPath, pSection); | 2155 | hr = CopyEngineWithSignatureFixup(pSection->hEngineFile, wzSourcePath, sczTargetPath, pSection, &hTargetFile); |
2122 | ExitOnFailure(hr, "Failed to copy engine: '%ls' to working path: %ls", wzSourcePath, sczTargetPath); | 2156 | ExitOnFailure(hr, "Failed to copy engine: '%ls' to working path: %ls", wzSourcePath, sczTargetPath); |
2123 | 2157 | ||
2124 | if (psczEngineWorkingPath) | 2158 | *psczEngineWorkingPath = sczTargetPath; |
2125 | { | 2159 | sczTargetPath = NULL; |
2126 | hr = StrAllocString(psczEngineWorkingPath, sczTargetPath, 0); | 2160 | |
2127 | ExitOnFailure(hr, "Failed to copy target path for engine working path."); | 2161 | *phEngineWorkingFile = hTargetFile; |
2128 | } | 2162 | hTargetFile = INVALID_HANDLE_VALUE; |
2129 | 2163 | ||
2130 | LExit: | 2164 | LExit: |
2131 | ReleaseStr(sczPayloadTargetPath); | 2165 | ReleaseFileHandle(hTargetFile); |
2132 | ReleaseStr(sczPayloadSourcePath); | ||
2133 | ReleaseStr(sczSourceDirectory); | ||
2134 | ReleaseStr(sczTargetPath); | 2166 | ReleaseStr(sczTargetPath); |
2135 | ReleaseStr(sczTargetDirectory); | 2167 | ReleaseStr(sczTargetDirectory); |
2136 | ReleaseStr(sczWorkingFolder); | 2168 | ReleaseStr(sczWorkingFolder); |
@@ -2143,7 +2175,8 @@ static HRESULT CopyEngineWithSignatureFixup( | |||
2143 | __in HANDLE hEngineFile, | 2175 | __in HANDLE hEngineFile, |
2144 | __in_z LPCWSTR wzEnginePath, | 2176 | __in_z LPCWSTR wzEnginePath, |
2145 | __in_z LPCWSTR wzTargetPath, | 2177 | __in_z LPCWSTR wzTargetPath, |
2146 | __in BURN_SECTION* pSection | 2178 | __in BURN_SECTION* pSection, |
2179 | __out HANDLE* phEngineFile | ||
2147 | ) | 2180 | ) |
2148 | { | 2181 | { |
2149 | HRESULT hr = S_OK; | 2182 | HRESULT hr = S_OK; |
@@ -2151,7 +2184,7 @@ static HRESULT CopyEngineWithSignatureFixup( | |||
2151 | LARGE_INTEGER li = { }; | 2184 | LARGE_INTEGER li = { }; |
2152 | DWORD dwZeroOriginals[3] = { }; | 2185 | DWORD dwZeroOriginals[3] = { }; |
2153 | 2186 | ||
2154 | hTarget = ::CreateFileW(wzTargetPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); | 2187 | hTarget = ::CreateFileW(wzTargetPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
2155 | if (INVALID_HANDLE_VALUE == hTarget) | 2188 | if (INVALID_HANDLE_VALUE == hTarget) |
2156 | { | 2189 | { |
2157 | ExitWithLastError(hr, "Failed to create engine file at path: %ls", wzTargetPath); | 2190 | ExitWithLastError(hr, "Failed to create engine file at path: %ls", wzTargetPath); |
@@ -2200,6 +2233,9 @@ static HRESULT CopyEngineWithSignatureFixup( | |||
2200 | ExitOnFailure(hr, "Failed to zero out original data offset."); | 2233 | ExitOnFailure(hr, "Failed to zero out original data offset."); |
2201 | } | 2234 | } |
2202 | 2235 | ||
2236 | *phEngineFile = hTarget; | ||
2237 | hTarget = INVALID_HANDLE_VALUE; | ||
2238 | |||
2203 | LExit: | 2239 | LExit: |
2204 | ReleaseFileHandle(hTarget); | 2240 | ReleaseFileHandle(hTarget); |
2205 | 2241 | ||