From b4a1bad4831eb253a74212ed6cf05055914bc75d Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Fri, 28 Jun 2024 15:50:31 +0000 Subject: [PATCH] Bug 1903064 - Prevent recovery from backups created from an application with a newer appVersion. r=backup-reviewers,sthompson,kpatenio Differential Revision: https://phabricator.services.mozilla.com/D215004 --- .../components/backup/BackupService.sys.mjs | 8 ++++ .../tests/xpcshell/test_BackupService.js | 6 +++ ...BackupService_recoverFromSnapshotFolder.js | 44 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/browser/components/backup/BackupService.sys.mjs b/browser/components/backup/BackupService.sys.mjs index 5d888c9b0358..d64a55f3afd9 100644 --- a/browser/components/backup/BackupService.sys.mjs +++ b/browser/components/backup/BackupService.sys.mjs @@ -2091,6 +2091,14 @@ export class BackupService extends EventTarget { ); } + if ( + Services.vc.compare(AppConstants.MOZ_APP_VERSION, meta.appVersion) < 0 + ) { + throw new Error( + `Cannot recover a backup created on version ${meta.appVersion} in ${AppConstants.MOZ_APP_VERSION}` + ); + } + // Okay, we have a valid backup-manifest.json. Let's create a new profile // and start invoking the recover() method on each BackupResource. let profileSvc = Cc["@mozilla.org/toolkit/profile-service;1"].getService( diff --git a/browser/components/backup/tests/xpcshell/test_BackupService.js b/browser/components/backup/tests/xpcshell/test_BackupService.js index 678cb82c4772..d813a5b16a0a 100644 --- a/browser/components/backup/tests/xpcshell/test_BackupService.js +++ b/browser/components/backup/tests/xpcshell/test_BackupService.js @@ -384,6 +384,12 @@ add_task(async function test_recoverFromSnapshotFolder() { AppConstants.MOZ_APP_NAME, "appName matches MOZ_APP_NAME" ); + // And that appVersion matches MOZ_APP_VERSION + Assert.equal( + manifest.meta.appVersion, + AppConstants.MOZ_APP_VERSION, + "appVersion matches MOZ_APP_VERSION" + ); let testTelemetryStateObject = { clientID: "ed209123-04a1-04a1-04a1-c0ffeec0ffee", diff --git a/browser/components/backup/tests/xpcshell/test_BackupService_recoverFromSnapshotFolder.js b/browser/components/backup/tests/xpcshell/test_BackupService_recoverFromSnapshotFolder.js index d1aad023b828..b14366b85b08 100644 --- a/browser/components/backup/tests/xpcshell/test_BackupService_recoverFromSnapshotFolder.js +++ b/browser/components/backup/tests/xpcshell/test_BackupService_recoverFromSnapshotFolder.js @@ -55,3 +55,47 @@ add_task(async function test_different_appName() { await IOUtils.remove(testRecoveryPath, { recursive: true }); }); + +/** + * Tests that if the backup-manifest.json provides an appVersion greater than + * AppConstants.MOZ_APP_VERSION of the currently running application, then + * recoverFromSnapshotFolder should throw an exception. + */ +add_task(async function test_newer_appVersion() { + let testRecoveryPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "testNewerAppVersion" + ); + + let meta = Object.assign({}, FAKE_METADATA); + // Hopefully this static version number will do for now. + meta.appVersion = "999.0.0"; + Assert.equal( + Services.vc.compare(AppConstants.MOZ_APP_VERSION, meta.appVersion), + -1, + "The current application version is less than 999.0.0." + ); + + let manifest = { + version: ArchiveUtils.SCHEMA_VERSION, + meta, + resources: {}, + }; + let schema = await BackupService.MANIFEST_SCHEMA; + let validationResult = JsonSchema.validate(manifest, schema); + Assert.ok(validationResult.valid, "Schema matches manifest"); + + await IOUtils.writeJSON( + PathUtils.join(testRecoveryPath, BackupService.MANIFEST_FILE_NAME), + manifest + ); + + let bs = new BackupService(); + // This should reject and mention the invalid appVersion from the manifest. + await Assert.rejects( + bs.recoverFromSnapshotFolder(testRecoveryPath), + new RegExp(`${meta.appVersion}`) + ); + + await IOUtils.remove(testRecoveryPath, { recursive: true }); +});