From daebaa6ed3fbf4e7943e6c8290ec6b9233b542e9 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 12 Mar 2015 12:32:37 -0700 Subject: [PATCH] Restrict the verification in block-based incremental OTAs BlockImageDiff has three versions. Only the incremental OTAs generated with the latest version (3) can be re-applied to the system that's already on the target build. Otherwise, operations like move will make unconditional changes and damage the system. During the verification phase, abort the OTA update if BlockImageDiff is less than 3 and it doesn't match the checksum of the source build. Change-Id: I3a776495b69e1d174fcb01b10e40c0e912914fd8 --- tools/releasetools/common.py | 35 ++++++++++++++++++++------------ tools/releasetools/ota_from_target_files | 32 +++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index 8941f890f..a596c2616 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -1024,20 +1024,22 @@ def ComputeDifferences(diffs): class BlockDifference: - def __init__(self, partition, tgt, src=None, check_first_block=False): + def __init__(self, partition, tgt, src=None, check_first_block=False, version=None): self.tgt = tgt self.src = src self.partition = partition self.check_first_block = check_first_block - version = 1 - if OPTIONS.info_dict: - version = max( - int(i) for i in - OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(",")) + if version is None: + version = 1 + if OPTIONS.info_dict: + version = max( + int(i) for i in + OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(",")) + self.version = version b = blockimgdiff.BlockImageDiff(tgt, src, threads=OPTIONS.worker_threads, - version=version) + version=self.version) tmpdir = tempfile.mkdtemp() OPTIONS.tempfiles.append(tmpdir) self.path = os.path.join(tmpdir, partition) @@ -1066,12 +1068,19 @@ class BlockDifference: (self.device, self.src.care_map.to_string_raw(), self.src.TotalSha1())) script.Print("Verified %s image..." % (self.partition,)) - script.AppendExtra(('else\n' - ' (range_sha1("%s", "%s") == "%s") ||\n' - ' abort("%s partition has unexpected contents");\n' - 'endif;') % - (self.device, self.tgt.care_map.to_string_raw(), - self.tgt.TotalSha1(), self.partition)) + # Abort the OTA update if it doesn't support resumable OTA (i.e. version<3) + # and the checksum doesn't match the one in the source partition. + if self.version < 3: + script.AppendExtra(('else\n' + ' abort("%s partition has unexpected contents");\n' + 'endif;') % (self.partition)) + else: + script.AppendExtra(('else\n' + ' (range_sha1("%s", "%s") == "%s") ||\n' + ' abort("%s partition has unexpected contents");\n' + 'endif;') % + (self.device, self.tgt.care_map.to_string_raw(), + self.tgt.TotalSha1(), self.partition)) def _WriteUpdate(self, script, output_zip): partition = self.partition diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files index 945f11a0b..25309a49c 100755 --- a/tools/releasetools/ota_from_target_files +++ b/tools/releasetools/ota_from_target_files @@ -740,8 +740,16 @@ def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip): system_src = GetImage("system", OPTIONS.source_tmp, OPTIONS.source_info_dict) system_tgt = GetImage("system", OPTIONS.target_tmp, OPTIONS.target_info_dict) + + blockimgdiff_version = 1 + if OPTIONS.info_dict: + blockimgdiff_version = max( + int(i) for i in + OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(",")) + system_diff = common.BlockDifference("system", system_tgt, system_src, - check_first_block=True) + check_first_block=True, + version=blockimgdiff_version) if HasVendorPartition(target_zip): if not HasVendorPartition(source_zip): @@ -749,7 +757,8 @@ def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip): vendor_src = GetImage("vendor", OPTIONS.source_tmp, OPTIONS.source_info_dict) vendor_tgt = GetImage("vendor", OPTIONS.target_tmp, OPTIONS.target_info_dict) vendor_diff = common.BlockDifference("vendor", vendor_tgt, vendor_src, - check_first_block=True) + check_first_block=True, + version=blockimgdiff_version) else: vendor_diff = None @@ -810,11 +819,22 @@ else if get_stage("%(bcb_dev)s") != "3/3" then device_specific.IncrementalOTA_VerifyBegin() if oem_props is None: - script.AssertSomeFingerprint(source_fp, target_fp) + # When blockimgdiff version is less than 3 (non-resumable block-based OTA), + # patching on a device that's already on the target build will damage the + # system. Because operations like move don't check the block state, they + # always apply the changes unconditionally. + if blockimgdiff_version <= 2: + script.AssertSomeFingerprint(source_fp) + else: + script.AssertSomeFingerprint(source_fp, target_fp) else: - script.AssertSomeThumbprint( - GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict), - GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) + if blockimgdiff_version <= 2: + script.AssertSomeThumbprint( + GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) + else: + script.AssertSomeThumbprint( + GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict), + GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) if updating_boot: boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict) -- 2.11.0