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

Commit d3351562 authored by Daniel Norman's avatar Daniel Norman
Browse files

Checks for APK sharedUserIds that cross partition group boundaries.

This check is used when merging target files to ensure that a merged
build does not contain any APKs that share UID across builds.

Bug: 171431774
Test: test_common
Test: Use merge_target_files.py to merge two partial builds,
      observe no failures for inputs without colliding APKs.
Test: Use merge_target_files.py to merge two partial builds,
      observe failure for inputs that have an APK that shares a
      UID across input partition groups.
Change-Id: I9dc57216882741ae46a99cfd7847f34702c75582
parent b8d52a2f
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -1085,6 +1085,38 @@ def MergeDynamicPartitionInfoDicts(framework_dict, vendor_dict):
  return merged_dict


def SharedUidPartitionViolations(uid_dict, partition_groups):
  """Checks for APK sharedUserIds that cross partition group boundaries.

  This uses a single or merged build's shareduid_violation_modules.json
  output file, as generated by find_shareduid_violation.py or
  core/tasks/find-shareduid-violation.mk.

  An error is defined as a sharedUserId that is found in a set of partitions
  that span more than one partition group.

  Args:
    uid_dict: A dictionary created by using the standard json module to read a
      complete shareduid_violation_modules.json file.
    partition_groups: A list of groups, where each group is a list of
      partitions.

  Returns:
    A list of error messages.
  """
  errors = []
  for uid, partitions in uid_dict.items():
    found_in_groups = [
        group for group in partition_groups
        if set(partitions.keys()) & set(group)
    ]
    if len(found_in_groups) > 1:
      errors.append(
          "APK sharedUserId \"%s\" found across partition groups in partitions \"%s\""
          % (uid, ",".join(sorted(partitions.keys()))))
  return errors


def AppendAVBSigningArgs(cmd, partition):
  """Append signing arguments for avbtool."""
  # e.g., "--key path/to/signing_key --algorithm SHA256_RSA4096"
+21 −8
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ Usage: merge_target_files [args]
from __future__ import print_function

import fnmatch
import json
import logging
import os
import re
@@ -944,20 +945,32 @@ def merge_target_files(temp_dir, framework_target_files, framework_item_list,
  if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
    raise RuntimeError('Incompatible VINTF metadata')

  # Generate and check for cross-partition violations of sharedUserId
  # values in APKs. This requires the input target-files packages to contain
  # *.apk files.
  shareduid_violation_modules = os.path.join(
      output_target_files_temp_dir, 'META', 'shareduid_violation_modules.json')
  with open(shareduid_violation_modules, 'w') as f:
    partition_map = {
        'system': 'SYSTEM',
        'vendor': 'VENDOR',
        'product': 'PRODUCT',
        'system_ext': 'SYSTEM_EXT',
    }
    framework_partitions = item_list_to_partition_set(framework_item_list)
    vendor_partitions = item_list_to_partition_set(vendor_item_list)

    partition_map = {}
    for partition in (framework_partitions.union(vendor_partitions)):
      partition_map[partition.lower()] = partition.upper()
    violation = find_shareduid_violation.FindShareduidViolation(
        output_target_files_temp_dir, partition_map)

    # Write the output to a file to enable debugging.
    f.write(violation)
    # TODO(b/171431774): Add a check to common.py to check if the
    # shared UIDs cross the input build partition boundary.

    # Check for violations across the input builds' partition groups.
    shareduid_errors = common.SharedUidPartitionViolations(
        json.loads(violation), [framework_partitions, vendor_partitions])
    if shareduid_errors:
      for error in shareduid_errors:
        logger.error(error)
      raise ValueError('sharedUserId APK error. See %s' %
                       shareduid_violation_modules)

  generate_images(output_target_files_temp_dir, rebuild_recovery)

+29 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#

import copy
import json
import os
import subprocess
import tempfile
@@ -995,6 +996,34 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
        },
        sparse_image.file_map)

  def test_SharedUidPartitionViolations(self):
    uid_dict = {
        'android.uid.phone': {
            'system': ['system_phone.apk'],
            'system_ext': ['system_ext_phone.apk'],
        },
        'android.uid.wifi': {
            'vendor': ['vendor_wifi.apk'],
            'odm': ['odm_wifi.apk'],
        },
    }
    errors = common.SharedUidPartitionViolations(
        uid_dict, [('system', 'system_ext'), ('vendor', 'odm')])
    self.assertEqual(errors, [])

  def test_SharedUidPartitionViolations_Violation(self):
    uid_dict = {
        'android.uid.phone': {
            'system': ['system_phone.apk'],
            'vendor': ['vendor_phone.apk'],
        },
    }
    errors = common.SharedUidPartitionViolations(
        uid_dict, [('system', 'system_ext'), ('vendor', 'odm')])
    self.assertIn(
        ('APK sharedUserId "android.uid.phone" found across partition groups '
         'in partitions "system,vendor"'), errors)

  def test_GetSparseImage_missingImageFile(self):
    self.assertRaises(
        AssertionError, common.GetSparseImage, 'system2', self.testdata_dir,