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
This commit is contained in:
Mark Smith 2020-05-27 21:22:15 +00:00
Родитель a2f2d585ea
Коммит 7b93c9ae97
6 изменённых файлов: 84 добавлений и 57 удалений

Просмотреть файл

@ -14,15 +14,19 @@ EXPORTS += [
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXPORTS += [ EXPORTS += [
'certificatecheck.h',
'pathhash.h', 'pathhash.h',
'registrycertificates.h',
'uachelper.h', 'uachelper.h',
'updatehelper.cpp', 'updatehelper.cpp',
'updatehelper.h', 'updatehelper.h',
'updateutils_win.h', 'updateutils_win.h',
] ]
if CONFIG['MOZ_MAINTENANCE_SERVICE']:
EXPORTS += [
'certificatecheck.h',
'registrycertificates.h',
]
Library('updatecommon') Library('updatecommon')
DEFINES['NS_NO_XPCOM'] = True DEFINES['NS_NO_XPCOM'] = True
@ -37,21 +41,26 @@ DisableStlWrapping()
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
SOURCES += [ SOURCES += [
'certificatecheck.cpp',
'pathhash.cpp', 'pathhash.cpp',
'registrycertificates.cpp',
'uachelper.cpp', 'uachelper.cpp',
'updatehelper.cpp', 'updatehelper.cpp',
'updateutils_win.cpp', 'updateutils_win.cpp',
] ]
OS_LIBS += [ OS_LIBS += [
'advapi32', 'advapi32',
'crypt32',
'ole32', 'ole32',
'rpcrt4', 'rpcrt4',
'shell32', 'shell32',
'wintrust',
] ]
if CONFIG['MOZ_MAINTENANCE_SERVICE']:
SOURCES += [
'certificatecheck.cpp',
'registrycertificates.cpp',
]
OS_LIBS += [
'crypt32',
'wintrust',
]
SOURCES += [ SOURCES += [
'/other-licenses/nsis/Contrib/CityHash/cityhash/city.cpp', '/other-licenses/nsis/Contrib/CityHash/cityhash/city.cpp',

Просмотреть файл

@ -6,23 +6,26 @@
// Needed for CreateToolhelp32Snapshot // Needed for CreateToolhelp32Snapshot
#include <tlhelp32.h> #include <tlhelp32.h>
#ifndef ONLY_SERVICE_LAUNCHING
# include <stdio.h> #include <stdio.h>
# include <direct.h> #include <direct.h>
# include "mozilla/UniquePtr.h" #include "shlobj.h"
# include "pathhash.h"
# include "shlobj.h"
# include "registrycertificates.h"
# include "uachelper.h"
# include "updatehelper.h"
# include "updateutils_win.h"
// Needed for PathAppendW // Needed for PathAppendW
# include <shlwapi.h> #include <shlwapi.h>
#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::MakeUnique;
using mozilla::UniquePtr; using mozilla::UniquePtr;
#endif
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath, BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
LPCWSTR newFileName); 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. * 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 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 * @param newFileName The filename of another file in the same directory
* @return TRUE if successful * @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 * Starts the upgrade process for update of the service if it is
* already installed. * already installed.
@ -353,8 +357,6 @@ BOOL StartServiceUpdate(LPCWSTR installDir) {
return svcUpdateProcessStarted; return svcUpdateProcessStarted;
} }
#endif
/** /**
* Executes a maintenance service command * Executes a maintenance service command
* *
@ -409,8 +411,6 @@ StartServiceCommand(int argc, LPCWSTR* argv) {
return lastError; return lastError;
} }
#ifndef ONLY_SERVICE_LAUNCHING
/** /**
* Launch a service initiated action for a software update with the * Launch a service initiated action for a software update with the
* specified arguments. * specified arguments.
@ -480,8 +480,6 @@ BOOL WriteStatusFailure(LPCWSTR patchDirPath, int errorCode) {
return TRUE; return TRUE;
} }
#endif
/** /**
* Waits for a service to enter a stopped state. * Waits for a service to enter a stopped state.
* This function does not stop the service, it just blocks until the service * This function does not stop the service, it just blocks until the service
@ -610,8 +608,7 @@ WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds) {
CloseServiceHandle(serviceManager); CloseServiceHandle(serviceManager);
return lastServiceState; return lastServiceState;
} }
#endif
#ifndef ONLY_SERVICE_LAUNCHING
/** /**
* Determines if there is at least one process running for the specified * 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 filename The application to wait for.
* @param maxSeconds The maximum amount of seconds to wait for all * @param maxSeconds The maximum amount of seconds to wait for all
@ -676,6 +673,7 @@ WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds) {
return applicationRunningError; return applicationRunningError;
} }
#ifdef MOZ_MAINTENANCE_SERVICE
/** /**
* Determines if the fallback key exists or not * Determines if the fallback key exists or not
* *
@ -693,8 +691,6 @@ BOOL DoesFallbackKeyExist() {
return TRUE; return TRUE;
} }
#endif
/** /**
* Determines if the file system for the specified file handle is local * 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 * @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; return success;
} }
#endif

Просмотреть файл

@ -2,16 +2,19 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef MOZ_MAINTENANCE_SERVICE
BOOL StartServiceUpdate(LPCWSTR installDir); BOOL StartServiceUpdate(LPCWSTR installDir);
DWORD LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR* argv); DWORD LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR* argv);
BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode); BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds); DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds);
DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds);
DWORD IsProcessRunning(LPCWSTR filename);
BOOL DoesFallbackKeyExist(); BOOL DoesFallbackKeyExist();
BOOL IsLocalFile(LPCWSTR file, BOOL& isLocal); BOOL IsLocalFile(LPCWSTR file, BOOL& isLocal);
DWORD StartServiceCommand(int argc, LPCWSTR* argv); DWORD StartServiceCommand(int argc, LPCWSTR* argv);
BOOL IsUnpromptedElevation(BOOL& isUnpromptedElevation); BOOL IsUnpromptedElevation(BOOL& isUnpromptedElevation);
#endif
DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds);
DWORD IsProcessRunning(LPCWSTR filename);
BOOL GetSecureOutputDirectoryPath(LPWSTR outBuf); BOOL GetSecureOutputDirectoryPath(LPWSTR outBuf);
BOOL GetSecureOutputFilePath(LPCWSTR patchDirPath, LPCWSTR fileExt, BOOL GetSecureOutputFilePath(LPCWSTR patchDirPath, LPCWSTR fileExt,
LPWSTR outBuf); LPWSTR outBuf);
@ -20,9 +23,10 @@ void RemoveSecureOutputFiles(LPCWSTR patchDirPath);
#define PATCH_DIR_PATH L"\\updates\\0" #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 // 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 // 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 // "This is a valid installation directory" check. This key also stores
// the allowed name and issuer for cert checks so that the cert check // the allowed name and issuer for cert checks so that the cert check
// code can still be run unchanged. // code can still be run unchanged.
#define TEST_ONLY_FALLBACK_KEY_PATH \ # define TEST_ONLY_FALLBACK_KEY_PATH \
BASE_SERVICE_REG_KEY L"\\3932ecacee736d366d6436db0f55bce4" BASE_SERVICE_REG_KEY L"\\3932ecacee736d366d6436db0f55bce4"
#endif

Просмотреть файл

@ -287,7 +287,7 @@ int NS_main(int argc, NS_tchar** argv) {
} }
if (!NS_tstrcmp(argv[1], NS_T("wait-for-service-stop"))) { 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]); const int maxWaitSeconds = NS_ttoi(argv[3]);
LPCWSTR serviceName = argv[2]; LPCWSTR serviceName = argv[2];
DWORD serviceState = WaitForServiceStop(serviceName, maxWaitSeconds); DWORD serviceState = WaitForServiceStop(serviceName, maxWaitSeconds);
@ -320,18 +320,8 @@ int NS_main(int argc, NS_tchar** argv) {
#endif #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"))) { if (!NS_tstrcmp(argv[1], NS_T("launch-service"))) {
#ifdef XP_WIN #if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE)
DWORD ret = DWORD ret =
LaunchServiceSoftwareUpdateCommand(argc - 2, (LPCWSTR*)argv + 2); LaunchServiceSoftwareUpdateCommand(argc - 2, (LPCWSTR*)argv + 2);
if (ret != ERROR_SUCCESS) { if (ret != ERROR_SUCCESS) {

Просмотреть файл

@ -1948,7 +1948,9 @@ void PatchIfFile::Finish(int status) {
# include "nsWindowsRestart.cpp" # include "nsWindowsRestart.cpp"
# include "nsWindowsHelpers.h" # include "nsWindowsHelpers.h"
# include "uachelper.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 * Launch the post update application (helper.exe). It takes in the path of the
@ -2239,7 +2241,7 @@ static bool IsUpdateStatusPendingService() {
} }
#endif #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 * Reads the secure update status file and sets isSucceeded to true if the
* status is set to succeeded. * status is set to succeeded.
@ -2448,7 +2450,7 @@ static int ProcessReplaceRequest() {
return 0; return 0;
} }
#ifdef XP_WIN #if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE)
static void WaitForServiceFinishThread(void* param) { static void WaitForServiceFinishThread(void* param) {
// We wait at most 10 minutes, we already waited 5 seconds previously // We wait at most 10 minutes, we already waited 5 seconds previously
// before deciding to show this UI. // 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"); 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. // The service update will only be executed if it is already installed.
// For first time installs of the service, the install will happen from // For first time installs of the service, the install will happen from
// the PostUpdate process. We do the service update process here // the PostUpdate process. We do the service update process here
@ -2662,6 +2665,7 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv,
if (!sUsingService) { if (!sUsingService) {
StartServiceUpdate(gInstallDirPath); StartServiceUpdate(gInstallDirPath);
} }
# endif
} }
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0); EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0);
#elif XP_MACOSX #elif XP_MACOSX
@ -3175,6 +3179,7 @@ int NS_main(int argc, NS_tchar** argv) {
return 1; return 1;
} }
# ifdef MOZ_MAINTENANCE_SERVICE
// Make sure the path to the updater to use for the update is on local. // 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 // We do this check to make sure that file locking is available for
// race condition security checks. // race condition security checks.
@ -3208,9 +3213,9 @@ int NS_main(int argc, NS_tchar** argv) {
&baseKey) == ERROR_SUCCESS) { &baseKey) == ERROR_SUCCESS) {
RegCloseKey(baseKey); RegCloseKey(baseKey);
} else { } else {
# ifdef TEST_UPDATER # ifdef TEST_UPDATER
useService = testOnlyFallbackKeyExists; useService = testOnlyFallbackKeyExists;
# endif # endif
if (!useService) { if (!useService) {
lastFallbackError = FALLBACKKEY_NOKEY_ERROR; lastFallbackError = FALLBACKKEY_NOKEY_ERROR;
} }
@ -3289,6 +3294,7 @@ int NS_main(int argc, NS_tchar** argv) {
lastFallbackError = FALLBACKKEY_LAUNCH_ERROR; lastFallbackError = FALLBACKKEY_LAUNCH_ERROR;
} }
} }
# endif
// If the service can't be used when staging an update, make sure that // 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 // 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; return 0;
} }
# ifdef MOZ_MAINTENANCE_SERVICE
// If we started the service command, and it finished, check the secure // 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 // 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 // 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 // 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 // already happening, or launching the service command failed, then

Просмотреть файл

@ -784,8 +784,12 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
bool aUseServiceOnFailure, bool aUseServiceOnFailure,
const nsAutoString& aInstallPath) const nsAutoString& aInstallPath)
: Runnable(aName), : Runnable(aName),
mUseServiceOnFailure(aUseServiceOnFailure), mState(State::Initializing)
mState(State::Initializing) { # ifdef MOZ_MAINTENANCE_SERVICE
,
mUseServiceOnFailure(aUseServiceOnFailure)
# endif
{
size_t installPathSize = aInstallPath.Length() + 1; size_t installPathSize = aInstallPath.Length() + 1;
mInstallPath = mozilla::MakeUnique<wchar_t[]>(installPathSize); mInstallPath = mozilla::MakeUnique<wchar_t[]>(installPathSize);
if (mInstallPath) { if (mInstallPath) {
@ -798,6 +802,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
} }
NS_IMETHOD Run() override { NS_IMETHOD Run() override {
# ifdef MOZ_MAINTENANCE_SERVICE
// These constants control how often and how many times we poll the // 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 // 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. // 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. // out to 5 seconds of polling.
const unsigned int kMaxStartAttempts = 50; const unsigned int kMaxStartAttempts = 50;
const unsigned int kStartAttemptIntervalMS = 100; const unsigned int kStartAttemptIntervalMS = 100;
# endif
if (mState == State::Initializing) { if (mState == State::Initializing) {
if (!mInstallPath) { if (!mInstallPath) {
@ -823,13 +829,20 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
if (SUCCEEDED(permResult)) { if (SUCCEEDED(permResult)) {
LOG(("Successfully fixed permissions from within Firefox\n")); LOG(("Successfully fixed permissions from within Firefox\n"));
return NS_OK; return NS_OK;
} else if (!mUseServiceOnFailure) { }
# ifdef MOZ_MAINTENANCE_SERVICE
else if (!mUseServiceOnFailure) {
LOG( LOG(
("Error: Unable to fix permissions within Firefox and " ("Error: Unable to fix permissions within Firefox and "
"maintenance service is disabled\n")); "maintenance service is disabled\n"));
return ReportUpdateError(); return ReportUpdateError();
} }
# else
LOG(("Error: Unable to fix permissions\n"));
return ReportUpdateError();
# endif
# ifdef MOZ_MAINTENANCE_SERVICE
SC_HANDLE serviceManager = SC_HANDLE serviceManager =
OpenSCManager(nullptr, nullptr, OpenSCManager(nullptr, nullptr,
SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
@ -867,7 +880,9 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
mState = State::WaitingToStart; mState = State::WaitingToStart;
mCurrentTry = 1; mCurrentTry = 1;
# endif
} }
# ifdef MOZ_MAINTENANCE_SERVICE
if (mState == State::WaitingToStart || if (mState == State::WaitingToStart ||
mState == State::WaitingForFinish) { mState == State::WaitingForFinish) {
SERVICE_STATUS_PROCESS ssp; SERVICE_STATUS_PROCESS ssp;
@ -933,6 +948,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
} }
return RetryInMS(kStartAttemptIntervalMS); return RetryInMS(kStartAttemptIntervalMS);
} }
# endif
// We should not have fallen through all three state checks above // We should not have fallen through all three state checks above
LOG( LOG(
("Error: Reached logically unreachable code when correcting update " ("Error: Reached logically unreachable code when correcting update "
@ -941,10 +957,11 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
} }
private: private:
bool mUseServiceOnFailure;
unsigned int mCurrentTry;
State mState; State mState;
mozilla::UniquePtr<wchar_t[]> mInstallPath; mozilla::UniquePtr<wchar_t[]> mInstallPath;
# ifdef MOZ_MAINTENANCE_SERVICE
bool mUseServiceOnFailure;
unsigned int mCurrentTry;
nsAutoServiceHandle mServiceManager; nsAutoServiceHandle mServiceManager;
nsAutoServiceHandle mService; nsAutoServiceHandle mService;
DWORD mStartServiceArgCount; DWORD mStartServiceArgCount;
@ -955,6 +972,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
nsCOMPtr<nsIRunnable> runnable(this); nsCOMPtr<nsIRunnable> runnable(this);
return NS_DelayedDispatchToCurrentThread(runnable.forget(), aDelayMS); return NS_DelayedDispatchToCurrentThread(runnable.forget(), aDelayMS);
} }
# endif
nsresult ReportUpdateError() { nsresult ReportUpdateError() {
return NS_DispatchToMainThread(NS_NewRunnableFunction( return NS_DispatchToMainThread(NS_NewRunnableFunction(
"nsUpdateProcessor::FixUpdateDirectoryPerms::" "nsUpdateProcessor::FixUpdateDirectoryPerms::"