Bug 709158 - updater.exe was not verified to be a particular product's/channel's/version of the updater. r=rstrong.

This commit is contained in:
Brian R. Bondy 2012-01-04 23:19:16 -05:00
parent d9f3ef0a5a
commit 28a67f5a40
5 changed files with 124 additions and 2 deletions

View File

@ -39,12 +39,12 @@
#include <shlwapi.h>
#include <stdio.h>
#include <wchar.h>
#include <shlobj.h>
#include "serviceinstall.h"
#include "maintenanceservice.h"
#include "servicebase.h"
#include "workmonitor.h"
#include "shlobj.h"
SERVICE_STATUS gSvcStatus = { 0 };
SERVICE_STATUS_HANDLE gSvcStatusHandle = NULL;

View File

@ -36,6 +36,84 @@
* ***** END LICENSE BLOCK ***** */
#include "servicebase.h"
#include "nsWindowsHelpers.h"
// Shared code between applications and updater.exe
#include "nsWindowsRestart.cpp"
/**
* Verifies if 2 files are byte for byte equivalent.
*
* @param file1Path The first file to verify.
* @param file2Path The second file to verify.
* @param sameContent Out parameter, TRUE if the files are equal
* @return TRUE If there was no error checking the files.
*/
BOOL
VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent)
{
sameContent = FALSE;
nsAutoHandle file1(CreateFileW(file1Path, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL));
if (!file1) {
return FALSE;
}
nsAutoHandle file2(CreateFileW(file2Path, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL));
if (!file2) {
return FALSE;
}
DWORD fileSize1 = GetFileSize(file1, NULL);
DWORD fileSize2 = GetFileSize(file2, NULL);
if (INVALID_FILE_SIZE == fileSize1 || INVALID_FILE_SIZE == fileSize2) {
return FALSE;
}
if (fileSize1 != fileSize2) {
// sameContent is already set to FALSE
return TRUE;
}
char buf1[COMPARE_BLOCKSIZE];
char buf2[COMPARE_BLOCKSIZE];
DWORD numBlocks = fileSize1 / COMPARE_BLOCKSIZE;
DWORD leftOver = fileSize1 % COMPARE_BLOCKSIZE;
DWORD readAmount;
for (DWORD i = 0; i < numBlocks; i++) {
if (!ReadFile(file1, buf1, COMPARE_BLOCKSIZE, &readAmount, NULL) ||
readAmount != COMPARE_BLOCKSIZE) {
return FALSE;
}
if (!ReadFile(file2, buf2, COMPARE_BLOCKSIZE, &readAmount, NULL) ||
readAmount != COMPARE_BLOCKSIZE) {
return FALSE;
}
if (memcmp(buf1, buf2, COMPARE_BLOCKSIZE)) {
// sameContent is already set to FALSE
return TRUE;
}
}
if (leftOver) {
if (!ReadFile(file1, buf1, leftOver, &readAmount, NULL) ||
readAmount != leftOver) {
return FALSE;
}
if (!ReadFile(file2, buf2, leftOver, &readAmount, NULL) ||
readAmount != leftOver) {
return FALSE;
}
if (memcmp(buf1, buf2, leftOver)) {
// sameContent is already set to FALSE
return TRUE;
}
}
sameContent = TRUE;
return TRUE;
}

View File

@ -39,3 +39,9 @@
#include "updatelogging.h"
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra);
BOOL VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent);
// 32KiB for comparing files at a time seems reasonable.
// The bigger the better for speed, but this will be used
// on the stack so I don't want it to be too big.
#define COMPARE_BLOCKSIZE 32768

View File

@ -71,6 +71,7 @@ BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
const int SERVICE_UPDATER_COULD_NOT_BE_STARTED = 16000;
const int SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS = 16001;
const int SERVICE_UPDATER_SIGN_ERROR = 16002;
const int SERVICE_UPDATER_COMPARE_ERROR = 16003;
/**
* Runs an update process as the service using the SYSTEM account.
@ -342,6 +343,41 @@ ProcessWorkItem(LPCWSTR monitoringBasePath,
int argcTmp = 0;
LPWSTR* argvTmp = CommandLineToArgvW(cmdlineBufferWide, &argcTmp);
// Verify that the updater.exe that we are executing is the same
// as the one in the installation directory which we are updating.
// The installation dir that we are installing to is argvTmp[2].
WCHAR installDirUpdater[MAX_PATH + 1];
wcsncpy(installDirUpdater, argvTmp[2], MAX_PATH);
if (!PathAppendSafe(installDirUpdater, L"updater.exe")) {
LOG(("Install directory updater could not be determined.\n"));
result = FALSE;
}
BOOL updaterIsCorrect;
if (result && !VerifySameFiles(updaterPath, installDirUpdater,
updaterIsCorrect)) {
LOG(("Error checking if the updaters are the same.\n"));
result = FALSE;
}
if (result && !updaterIsCorrect) {
LOG(("The updaters do not match, udpater will not run.\n"));
result = FALSE;
}
if (result) {
LOG(("updater.exe was compared successfully to the installation directory"
" updater.exe.\n"));
} else {
SetEvent(serviceRunningEvent);
if (argcTmp < 2 ||
!WriteStatusFailure(argvTmp[1],
SERVICE_UPDATER_COMPARE_ERROR)) {
LOG(("Could not write update.status updater compare failure.\n"));
}
return TRUE;
}
// Check for updater.exe sign problems
BOOL updaterSignProblem = FALSE;
#ifndef DISABLE_UPDATER_AUTHENTICODE_CHECK

View File

@ -146,6 +146,7 @@ const ELEVATION_CANCELED = 9;
const SERVICE_UPDATER_COULD_NOT_BE_STARTED = 16000;
const SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS = 16001;
const SERVICE_UPDATER_SIGN_ERROR = 16002;
const SERVICE_UPDATER_COMPARE_ERROR = 16003;
const CERT_ATTR_CHECK_FAILED_NO_UPDATE = 100;
const CERT_ATTR_CHECK_FAILED_HAS_UPDATE = 101;
@ -1435,7 +1436,8 @@ UpdateService.prototype = {
if (update.errorCode == SERVICE_UPDATER_COULD_NOT_BE_STARTED ||
update.errorCode == SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS ||
update.errorCode == SERVICE_UPDATER_SIGN_ERROR) {
update.errorCode == SERVICE_UPDATER_SIGN_ERROR ||
update.errorCode == SERVICE_UPDATER_COMPARE_ERROR) {
var failCount = getPref("getIntPref",
PREF_APP_UPDATE_SERVICE_ERRORS, 0);
var maxFail = getPref("getIntPref",