diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index 5e70af1e7d..0683678b50 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -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" diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py index 0d135d625e..ba9e740674 100755 --- a/tools/releasetools/merge_target_files.py +++ b/tools/releasetools/merge_target_files.py @@ -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) diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py index ee28571878..0b368f9b61 100644 --- a/tools/releasetools/test_common.py +++ b/tools/releasetools/test_common.py @@ -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,