From 7b93c9ae97f9bd045c2194dce2d0e6275b21a89e Mon Sep 17 00:00:00 2001 From: Mark Smith Date: Wed, 27 May 2020 21:22:15 +0000 Subject: [PATCH] Bug 1588549 - --disable-maintenance-service should exclude all maintenance service-related code r=bytesized,mhowell Exclude Windows Maintenance Service-related C++ code and avoid linking with unnecessary libraries when building with --disable-maintenance-service. Differential Revision: https://phabricator.services.mozilla.com/D76349 --- toolkit/mozapps/update/common/moz.build | 21 ++++++--- .../mozapps/update/common/updatehelper.cpp | 43 +++++++++---------- toolkit/mozapps/update/common/updatehelper.h | 17 +++++--- .../mozapps/update/tests/TestAUSHelper.cpp | 14 +----- toolkit/mozapps/update/updater/updater.cpp | 18 +++++--- toolkit/xre/nsUpdateDriver.cpp | 28 +++++++++--- 6 files changed, 84 insertions(+), 57 deletions(-) diff --git a/toolkit/mozapps/update/common/moz.build b/toolkit/mozapps/update/common/moz.build index f94c829f6d63..e714bdb2db24 100644 --- a/toolkit/mozapps/update/common/moz.build +++ b/toolkit/mozapps/update/common/moz.build @@ -14,15 +14,19 @@ EXPORTS += [ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': EXPORTS += [ - 'certificatecheck.h', 'pathhash.h', - 'registrycertificates.h', 'uachelper.h', 'updatehelper.cpp', 'updatehelper.h', 'updateutils_win.h', ] + if CONFIG['MOZ_MAINTENANCE_SERVICE']: + EXPORTS += [ + 'certificatecheck.h', + 'registrycertificates.h', + ] + Library('updatecommon') DEFINES['NS_NO_XPCOM'] = True @@ -37,21 +41,26 @@ DisableStlWrapping() if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': SOURCES += [ - 'certificatecheck.cpp', 'pathhash.cpp', - 'registrycertificates.cpp', 'uachelper.cpp', 'updatehelper.cpp', 'updateutils_win.cpp', ] OS_LIBS += [ 'advapi32', - 'crypt32', 'ole32', 'rpcrt4', 'shell32', - 'wintrust', ] + if CONFIG['MOZ_MAINTENANCE_SERVICE']: + SOURCES += [ + 'certificatecheck.cpp', + 'registrycertificates.cpp', + ] + OS_LIBS += [ + 'crypt32', + 'wintrust', + ] SOURCES += [ '/other-licenses/nsis/Contrib/CityHash/cityhash/city.cpp', diff --git a/toolkit/mozapps/update/common/updatehelper.cpp b/toolkit/mozapps/update/common/updatehelper.cpp index 60bb6d508577..b094d9eb75e9 100644 --- a/toolkit/mozapps/update/common/updatehelper.cpp +++ b/toolkit/mozapps/update/common/updatehelper.cpp @@ -6,23 +6,26 @@ // Needed for CreateToolhelp32Snapshot #include -#ifndef ONLY_SERVICE_LAUNCHING -# include -# include -# include "mozilla/UniquePtr.h" -# include "pathhash.h" -# include "shlobj.h" -# include "registrycertificates.h" -# include "uachelper.h" -# include "updatehelper.h" -# include "updateutils_win.h" +#include +#include +#include "shlobj.h" // Needed for PathAppendW -# include +#include + +#include "updatehelper.h" +#include "updateutils_win.h" + +#ifdef MOZ_MAINTENANCE_SERVICE +# include "mozilla/UniquePtr.h" +# include "pathhash.h" +# include "registrycertificates.h" +# include "uachelper.h" using mozilla::MakeUnique; using mozilla::UniquePtr; +#endif BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath, LPCWSTR newFileName); @@ -31,7 +34,7 @@ BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath, * Obtains the path of a file in the same directory as the specified file. * * @param destinationBuffer A buffer of size MAX_PATH + 1 to store the result. - * @param siblingFIlePath The path of another file in the same directory + * @param siblingFilePath The path of another file in the same directory * @param newFileName The filename of another file in the same directory * @return TRUE if successful */ @@ -251,6 +254,7 @@ void RemoveSecureOutputFiles(LPCWSTR patchDirPath) { } } +#ifdef MOZ_MAINTENANCE_SERVICE /** * Starts the upgrade process for update of the service if it is * already installed. @@ -353,8 +357,6 @@ BOOL StartServiceUpdate(LPCWSTR installDir) { return svcUpdateProcessStarted; } -#endif - /** * Executes a maintenance service command * @@ -409,8 +411,6 @@ StartServiceCommand(int argc, LPCWSTR* argv) { return lastError; } -#ifndef ONLY_SERVICE_LAUNCHING - /** * Launch a service initiated action for a software update with the * specified arguments. @@ -480,8 +480,6 @@ BOOL WriteStatusFailure(LPCWSTR patchDirPath, int errorCode) { return TRUE; } -#endif - /** * Waits for a service to enter a stopped state. * This function does not stop the service, it just blocks until the service @@ -610,8 +608,7 @@ WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds) { CloseServiceHandle(serviceManager); return lastServiceState; } - -#ifndef ONLY_SERVICE_LAUNCHING +#endif /** * Determines if there is at least one process running for the specified @@ -649,7 +646,7 @@ IsProcessRunning(LPCWSTR filename) { } /** - * Waits for the specified applicaiton to exit. + * Waits for the specified application to exit. * * @param filename The application to wait for. * @param maxSeconds The maximum amount of seconds to wait for all @@ -676,6 +673,7 @@ WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds) { return applicationRunningError; } +#ifdef MOZ_MAINTENANCE_SERVICE /** * Determines if the fallback key exists or not * @@ -693,8 +691,6 @@ BOOL DoesFallbackKeyExist() { return TRUE; } -#endif - /** * Determines if the file system for the specified file handle is local * @param file path to check the filesystem type for, must be at most MAX_PATH @@ -764,3 +760,4 @@ BOOL IsUnpromptedElevation(BOOL& isUnpromptedElevation) { return success; } +#endif diff --git a/toolkit/mozapps/update/common/updatehelper.h b/toolkit/mozapps/update/common/updatehelper.h index 08531e09aa1a..b34689383577 100644 --- a/toolkit/mozapps/update/common/updatehelper.h +++ b/toolkit/mozapps/update/common/updatehelper.h @@ -2,16 +2,19 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifdef MOZ_MAINTENANCE_SERVICE BOOL StartServiceUpdate(LPCWSTR installDir); DWORD LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR* argv); BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode); DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds); -DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds); -DWORD IsProcessRunning(LPCWSTR filename); BOOL DoesFallbackKeyExist(); BOOL IsLocalFile(LPCWSTR file, BOOL& isLocal); DWORD StartServiceCommand(int argc, LPCWSTR* argv); BOOL IsUnpromptedElevation(BOOL& isUnpromptedElevation); +#endif + +DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds); +DWORD IsProcessRunning(LPCWSTR filename); BOOL GetSecureOutputDirectoryPath(LPWSTR outBuf); BOOL GetSecureOutputFilePath(LPCWSTR patchDirPath, LPCWSTR fileExt, LPWSTR outBuf); @@ -20,9 +23,10 @@ void RemoveSecureOutputFiles(LPCWSTR patchDirPath); #define PATCH_DIR_PATH L"\\updates\\0" -#define SVC_NAME L"MozillaMaintenance" +#ifdef MOZ_MAINTENANCE_SERVICE +# define SVC_NAME L"MozillaMaintenance" -#define BASE_SERVICE_REG_KEY L"SOFTWARE\\Mozilla\\MaintenanceService" +# define BASE_SERVICE_REG_KEY L"SOFTWARE\\Mozilla\\MaintenanceService" // The test only fallback key, as its name implies, is only present on machines // that will use automated tests. Since automated tests always run from a @@ -30,5 +34,6 @@ void RemoveSecureOutputFiles(LPCWSTR patchDirPath); // "This is a valid installation directory" check. This key also stores // the allowed name and issuer for cert checks so that the cert check // code can still be run unchanged. -#define TEST_ONLY_FALLBACK_KEY_PATH \ - BASE_SERVICE_REG_KEY L"\\3932ecacee736d366d6436db0f55bce4" +# define TEST_ONLY_FALLBACK_KEY_PATH \ + BASE_SERVICE_REG_KEY L"\\3932ecacee736d366d6436db0f55bce4" +#endif diff --git a/toolkit/mozapps/update/tests/TestAUSHelper.cpp b/toolkit/mozapps/update/tests/TestAUSHelper.cpp index a44bfa713d0d..6b83a013707a 100644 --- a/toolkit/mozapps/update/tests/TestAUSHelper.cpp +++ b/toolkit/mozapps/update/tests/TestAUSHelper.cpp @@ -287,7 +287,7 @@ int NS_main(int argc, NS_tchar** argv) { } if (!NS_tstrcmp(argv[1], NS_T("wait-for-service-stop"))) { -#ifdef XP_WIN +#if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE) const int maxWaitSeconds = NS_ttoi(argv[3]); LPCWSTR serviceName = argv[2]; DWORD serviceState = WaitForServiceStop(serviceName, maxWaitSeconds); @@ -320,18 +320,8 @@ int NS_main(int argc, NS_tchar** argv) { #endif } - if (!NS_tstrcmp(argv[1], NS_T("is-process-running"))) { -#ifdef XP_WIN - LPCWSTR application = argv[2]; - return (ERROR_NOT_FOUND == IsProcessRunning(application)) ? 0 : 1; -#else - // Not implemented on non-Windows platforms - return 1; -#endif - } - if (!NS_tstrcmp(argv[1], NS_T("launch-service"))) { -#ifdef XP_WIN +#if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE) DWORD ret = LaunchServiceSoftwareUpdateCommand(argc - 2, (LPCWSTR*)argv + 2); if (ret != ERROR_SUCCESS) { diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp index dcc9902c6395..65b22be0ebc7 100644 --- a/toolkit/mozapps/update/updater/updater.cpp +++ b/toolkit/mozapps/update/updater/updater.cpp @@ -1948,7 +1948,9 @@ void PatchIfFile::Finish(int status) { # include "nsWindowsRestart.cpp" # include "nsWindowsHelpers.h" # include "uachelper.h" -# include "pathhash.h" +# ifdef MOZ_MAINTENANCE_SERVICE +# include "pathhash.h" +# endif /** * Launch the post update application (helper.exe). It takes in the path of the @@ -2239,7 +2241,7 @@ static bool IsUpdateStatusPendingService() { } #endif -#ifdef XP_WIN +#if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE) /* * Reads the secure update status file and sets isSucceeded to true if the * status is set to succeeded. @@ -2448,7 +2450,7 @@ static int ProcessReplaceRequest() { return 0; } -#ifdef XP_WIN +#if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE) static void WaitForServiceFinishThread(void* param) { // We wait at most 10 minutes, we already waited 5 seconds previously // before deciding to show this UI. @@ -2652,6 +2654,7 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv, fprintf(stderr, "The post update process was not launched"); } +# ifdef MOZ_MAINTENANCE_SERVICE // The service update will only be executed if it is already installed. // For first time installs of the service, the install will happen from // the PostUpdate process. We do the service update process here @@ -2662,6 +2665,7 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv, if (!sUsingService) { StartServiceUpdate(gInstallDirPath); } +# endif } EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0); #elif XP_MACOSX @@ -3175,6 +3179,7 @@ int NS_main(int argc, NS_tchar** argv) { return 1; } +# ifdef MOZ_MAINTENANCE_SERVICE // Make sure the path to the updater to use for the update is on local. // We do this check to make sure that file locking is available for // race condition security checks. @@ -3208,9 +3213,9 @@ int NS_main(int argc, NS_tchar** argv) { &baseKey) == ERROR_SUCCESS) { RegCloseKey(baseKey); } else { -# ifdef TEST_UPDATER +# ifdef TEST_UPDATER useService = testOnlyFallbackKeyExists; -# endif +# endif if (!useService) { lastFallbackError = FALLBACKKEY_NOKEY_ERROR; } @@ -3289,6 +3294,7 @@ int NS_main(int argc, NS_tchar** argv) { lastFallbackError = FALLBACKKEY_LAUNCH_ERROR; } } +# endif // If the service can't be used when staging an update, make sure that // the UAC prompt is not shown! In this case, just set the status to @@ -3305,6 +3311,7 @@ int NS_main(int argc, NS_tchar** argv) { return 0; } +# ifdef MOZ_MAINTENANCE_SERVICE // If we started the service command, and it finished, check the secure // update status file to make sure that it succeeded, and if it did we // need to launch the PostUpdate process in the unelevated updater which @@ -3322,6 +3329,7 @@ int NS_main(int argc, NS_tchar** argv) { } } } +# endif // If we didn't want to use the service at all, or if an update was // already happening, or launching the service command failed, then diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp index 3328da394127..6af227711642 100644 --- a/toolkit/xre/nsUpdateDriver.cpp +++ b/toolkit/xre/nsUpdateDriver.cpp @@ -784,8 +784,12 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) { bool aUseServiceOnFailure, const nsAutoString& aInstallPath) : Runnable(aName), - mUseServiceOnFailure(aUseServiceOnFailure), - mState(State::Initializing) { + mState(State::Initializing) +# ifdef MOZ_MAINTENANCE_SERVICE + , + mUseServiceOnFailure(aUseServiceOnFailure) +# endif + { size_t installPathSize = aInstallPath.Length() + 1; mInstallPath = mozilla::MakeUnique(installPathSize); if (mInstallPath) { @@ -798,6 +802,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) { } NS_IMETHOD Run() override { +# ifdef MOZ_MAINTENANCE_SERVICE // These constants control how often and how many times we poll the // maintenance service to see if it has stopped. If there is no delay in // the event queue, this works out to 8 minutes of polling. @@ -808,6 +813,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) { // out to 5 seconds of polling. const unsigned int kMaxStartAttempts = 50; const unsigned int kStartAttemptIntervalMS = 100; +# endif if (mState == State::Initializing) { if (!mInstallPath) { @@ -823,13 +829,20 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) { if (SUCCEEDED(permResult)) { LOG(("Successfully fixed permissions from within Firefox\n")); return NS_OK; - } else if (!mUseServiceOnFailure) { + } +# ifdef MOZ_MAINTENANCE_SERVICE + else if (!mUseServiceOnFailure) { LOG( ("Error: Unable to fix permissions within Firefox and " "maintenance service is disabled\n")); return ReportUpdateError(); } +# else + LOG(("Error: Unable to fix permissions\n")); + return ReportUpdateError(); +# endif +# ifdef MOZ_MAINTENANCE_SERVICE SC_HANDLE serviceManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); @@ -867,7 +880,9 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) { mState = State::WaitingToStart; mCurrentTry = 1; +# endif } +# ifdef MOZ_MAINTENANCE_SERVICE if (mState == State::WaitingToStart || mState == State::WaitingForFinish) { SERVICE_STATUS_PROCESS ssp; @@ -933,6 +948,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) { } return RetryInMS(kStartAttemptIntervalMS); } +# endif // We should not have fallen through all three state checks above LOG( ("Error: Reached logically unreachable code when correcting update " @@ -941,10 +957,11 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) { } private: - bool mUseServiceOnFailure; - unsigned int mCurrentTry; State mState; mozilla::UniquePtr mInstallPath; +# ifdef MOZ_MAINTENANCE_SERVICE + bool mUseServiceOnFailure; + unsigned int mCurrentTry; nsAutoServiceHandle mServiceManager; nsAutoServiceHandle mService; DWORD mStartServiceArgCount; @@ -955,6 +972,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) { nsCOMPtr runnable(this); return NS_DelayedDispatchToCurrentThread(runnable.forget(), aDelayMS); } +# endif nsresult ReportUpdateError() { return NS_DispatchToMainThread(NS_NewRunnableFunction( "nsUpdateProcessor::FixUpdateDirectoryPerms::"