Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a768495 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Detect downgrade by checking build time for all partitions" into main...

Merge "Detect downgrade by checking build time for all partitions" into main am: fb5630b3 am: fb962534 am: 6a832779

Original change: https://android-review.googlesource.com/c/platform/build/+/2878035



Change-Id: Iba7d4b196d92f779c9aaeafb182aa7a9c8ec8203
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents a8791412 6a832779
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -1038,7 +1038,11 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None):
  partition_timestamps_flags = []
  # Enforce a max timestamp this payload can be applied on top of.
  if OPTIONS.downgrade:
    max_timestamp = source_info.GetBuildProp("ro.build.date.utc")
    # When generating ota between merged target-files, partition build date can
    # decrease in target, at the same time as ro.build.date.utc increases,
    # so always pick largest value.
    max_timestamp = max(source_info.GetBuildProp("ro.build.date.utc"),
        str(metadata.postcondition.timestamp))
    partition_timestamps_flags = GeneratePartitionTimestampFlagsDowngrade(
        metadata.precondition.partition_state,
        metadata.postcondition.partition_state
+47 −7
Original line number Diff line number Diff line
@@ -364,26 +364,66 @@ def HandleDowngradeMetadata(metadata_proto, target_info, source_info):
  # Only incremental OTAs are allowed to reach here.
  assert OPTIONS.incremental_source is not None

  # used for logging upon errors
  log_downgrades = []
  log_upgrades = []

  post_timestamp = target_info.GetBuildProp("ro.build.date.utc")
  pre_timestamp = source_info.GetBuildProp("ro.build.date.utc")
  is_downgrade = int(post_timestamp) < int(pre_timestamp)
  if int(post_timestamp) < int(pre_timestamp):
    logger.info(f"ro.build.date.utc pre timestamp: {pre_timestamp}, "
                f"post timestamp: {post_timestamp}. Downgrade detected.")
    log_downgrades.append(f"ro.build.date.utc pre: {pre_timestamp} post: {post_timestamp}")
  else:
    logger.info(f"ro.build.date.utc pre timestamp: {pre_timestamp}, "
                f"post timestamp: {post_timestamp}.")
    log_upgrades.append(f"ro.build.date.utc pre: {pre_timestamp} post: {post_timestamp}")

  # When merging system and vendor target files, it is not enough
  # to check ro.build.date.utc, the timestamp for each partition must
  # be checked.
  if source_info.is_ab:
    ab_partitions = set(source_info.get("ab_partitions"))
    for partition in sorted(set(PARTITIONS_WITH_BUILD_PROP) & ab_partitions):

      partition_prop = source_info.get('{}.build.prop'.format(partition))
      # Skip if the partition is missing, or it doesn't have a build.prop
      if not partition_prop or not partition_prop.build_props:
        continue
      partition_prop = target_info.get('{}.build.prop'.format(partition))
      # Skip if the partition is missing, or it doesn't have a build.prop
      if not partition_prop or not partition_prop.build_props:
        continue

      post_timestamp = target_info.GetPartitionBuildProp(
        'ro.build.date.utc', partition)
      pre_timestamp = source_info.GetPartitionBuildProp(
        'ro.build.date.utc', partition)
      if int(post_timestamp) < int(pre_timestamp):
        logger.info(f"Partition {partition} pre timestamp: {pre_timestamp}, "
                    f"post time: {post_timestamp}. Downgrade detected.")
        log_downgrades.append(f"{partition} pre: {pre_timestamp} post: {post_timestamp}")
      else:
        logger.info(f"Partition {partition} pre timestamp: {pre_timestamp}, "
                    f"post timestamp: {post_timestamp}.")
        log_upgrades.append(f"{partition} pre: {pre_timestamp} post: {post_timestamp}")

  if OPTIONS.spl_downgrade:
    metadata_proto.spl_downgrade = True

  if OPTIONS.downgrade:
    if not is_downgrade:
    if len(log_downgrades) == 0:
      raise RuntimeError(
          "--downgrade or --override_timestamp specified but no downgrade "
          "detected: pre: %s, post: %s" % (pre_timestamp, post_timestamp))
          "detected. Current values for ro.build.date.utc: " + ', '.join(log_upgrades))
    metadata_proto.downgrade = True
  else:
    if is_downgrade:
    if len(log_downgrades) != 0:
      raise RuntimeError(
          "Downgrade detected based on timestamp check: pre: %s, post: %s. "
          "Downgrade detected based on timestamp check in ro.build.date.utc. "
          "Need to specify --override_timestamp OR --downgrade to allow "
          "building the incremental." % (pre_timestamp, post_timestamp))

          "building the incremental. Downgrades detected for: "
          + ', '.join(log_downgrades))

def ComputeRuntimeBuildInfos(default_build_info, boot_variable_values):
  """Returns a set of build info objects that may exist during runtime."""
+88 −0
Original line number Diff line number Diff line
@@ -163,6 +163,20 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
      'oem_fingerprint_properties': 'ro.product.device ro.product.brand',
  }

  TEST_TARGET_VENDOR_INFO_DICT = common.PartitionBuildProps.FromDictionary(
    'vendor', {
      'ro.vendor.build.date.utc' : '87654321',
      'ro.product.vendor.device':'vendor-device',
      'ro.vendor.build.fingerprint': 'build-fingerprint-vendor'}
  )

  TEST_SOURCE_VENDOR_INFO_DICT = common.PartitionBuildProps.FromDictionary(
    'vendor', {
      'ro.vendor.build.date.utc' : '12345678',
      'ro.product.vendor.device':'vendor-device',
      'ro.vendor.build.fingerprint': 'build-fingerprint-vendor'}
  )

  def setUp(self):
    self.testdata_dir = test_utils.get_testdata_dir()
    self.assertTrue(os.path.exists(self.testdata_dir))
@@ -351,6 +365,13 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
         source_info['build.prop'].build_props['ro.build.date.utc'],
         target_info['build.prop'].build_props['ro.build.date.utc'])

  @staticmethod
  def _test_GetPackageMetadata_swapVendorBuildTimestamps(target_info, source_info):
    (target_info['vendor.build.prop'].build_props['ro.vendor.build.date.utc'],
     source_info['vendor.build.prop'].build_props['ro.vendor.build.date.utc']) = (
         source_info['vendor.build.prop'].build_props['ro.vendor.build.date.utc'],
         target_info['vendor.build.prop'].build_props['ro.vendor.build.date.utc'])

  def test_GetPackageMetadata_unintentionalDowngradeDetected(self):
    target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
    source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
@@ -363,6 +384,24 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
    self.assertRaises(RuntimeError, self.GetLegacyOtaMetadata, target_info,
                      source_info)

  def test_GetPackageMetadata_unintentionalVendorDowngradeDetected(self):
    target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
    target_info_dict['ab_update'] = 'true'
    target_info_dict['ab_partitions'] = ['vendor']
    target_info_dict["vendor.build.prop"] = copy.deepcopy(self.TEST_TARGET_VENDOR_INFO_DICT)
    source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
    source_info_dict['ab_update'] = 'true'
    source_info_dict['ab_partitions'] = ['vendor']
    source_info_dict["vendor.build.prop"] = copy.deepcopy(self.TEST_SOURCE_VENDOR_INFO_DICT)
    self._test_GetPackageMetadata_swapVendorBuildTimestamps(
        target_info_dict, source_info_dict)

    target_info = common.BuildInfo(target_info_dict, None)
    source_info = common.BuildInfo(source_info_dict, None)
    common.OPTIONS.incremental_source = ''
    self.assertRaises(RuntimeError, self.GetLegacyOtaMetadata, target_info,
                      source_info)

  def test_GetPackageMetadata_downgrade(self):
    target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
    source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
@@ -397,6 +436,55 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
        },
        metadata)

  def test_GetPackageMetadata_vendorDowngrade(self):
    target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
    target_info_dict['ab_update'] = 'true'
    target_info_dict['ab_partitions'] = ['vendor']
    target_info_dict["vendor.build.prop"] = copy.deepcopy(self.TEST_TARGET_VENDOR_INFO_DICT)
    source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
    source_info_dict['ab_update'] = 'true'
    source_info_dict['ab_partitions'] = ['vendor']
    source_info_dict["vendor.build.prop"] = copy.deepcopy(self.TEST_SOURCE_VENDOR_INFO_DICT)
    self._test_GetPackageMetadata_swapVendorBuildTimestamps(
        target_info_dict, source_info_dict)

    target_info = common.BuildInfo(target_info_dict, None)
    source_info = common.BuildInfo(source_info_dict, None)
    common.OPTIONS.incremental_source = ''
    common.OPTIONS.downgrade = True
    common.OPTIONS.wipe_user_data = True
    common.OPTIONS.spl_downgrade = True
    metadata = self.GetLegacyOtaMetadata(target_info, source_info)
    # Reset spl_downgrade so other tests are unaffected
    common.OPTIONS.spl_downgrade = False

    self.assertDictEqual(
        {
            'ota-downgrade': 'yes',
            'ota-type': 'AB',
            'ota-required-cache': '0',
            'ota-wipe': 'yes',
            'post-build': 'build-fingerprint-target',
            'post-build-incremental': 'build-version-incremental-target',
            'post-sdk-level': '27',
            'post-security-patch-level': '2017-12-01',
            'post-timestamp': '1500000000',
            'pre-device': 'product-device',
            'pre-build': 'build-fingerprint-source',
            'pre-build-incremental': 'build-version-incremental-source',
            'spl-downgrade': 'yes',
        },
        metadata)

    post_build = GetPackageMetadata(target_info, source_info).postcondition
    self.assertEqual('vendor', post_build.partition_state[0].partition_name)
    self.assertEqual('12345678', post_build.partition_state[0].version)

    pre_build = GetPackageMetadata(target_info, source_info).precondition
    self.assertEqual('vendor', pre_build.partition_state[0].partition_name)
    self.assertEqual('87654321', pre_build.partition_state[0].version)


  @test_utils.SkipIfExternalToolsUnavailable()
  def test_GetTargetFilesZipForSecondaryImages(self):
    input_file = construct_target_files(secondary=True)