Loading core/Makefile +1 −0 Original line number Original line Diff line number Diff line Loading @@ -4136,6 +4136,7 @@ INTERNAL_OTATOOLS_MODULES := \ mkuserimg_mke2fs \ mkuserimg_mke2fs \ ota_from_target_files \ ota_from_target_files \ repack_bootimg \ repack_bootimg \ secilc \ sefcontext_compile \ sefcontext_compile \ sgdisk \ sgdisk \ shflags \ shflags \ Loading tools/releasetools/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -451,6 +451,7 @@ python_binary_host { required: [ required: [ "checkvintf", "checkvintf", "host_init_verifier", "host_init_verifier", "secilc", ], ], target: { target: { darwin: { darwin: { Loading tools/releasetools/merge_target_files.py +88 −2 Original line number Original line Diff line number Diff line Loading @@ -93,6 +93,7 @@ import shutil import subprocess import subprocess import sys import sys import zipfile import zipfile from xml.etree import ElementTree import add_img_to_target_files import add_img_to_target_files import build_super_image import build_super_image Loading Loading @@ -658,6 +659,80 @@ def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir, os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin')) os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin')) def compile_split_sepolicy(product_out, partition_map, output_policy): """Uses secilc to compile a split sepolicy file. Depends on various */etc/selinux/* and */etc/vintf/* files within partitions. Args: product_out: PRODUCT_OUT directory, containing partition directories. partition_map: A map of partition name -> relative path within product_out. output_policy: The name of the output policy created by secilc. Returns: A command list that can be executed to create the compiled sepolicy. """ def get_file(partition, path): if partition not in partition_map: logger.warning('Cannot load SEPolicy files for missing partition %s', partition) return None return os.path.join(product_out, partition_map[partition], path) # Load the kernel sepolicy version from the FCM. This is normally provided # directly to selinux.cpp as a build flag, but is also available in this file. fcm_file = get_file('system', 'etc/vintf/compatibility_matrix.device.xml') if not fcm_file or not os.path.exists(fcm_file): raise ExternalError('Missing required file for loading sepolicy: %s', fcm) kernel_sepolicy_version = ElementTree.parse(fcm_file).getroot().find( 'sepolicy/kernel-sepolicy-version').text # Load the vendor's plat sepolicy version. This is the version used for # locating sepolicy mapping files. vendor_plat_version_file = get_file('vendor', 'etc/selinux/plat_sepolicy_vers.txt') if not vendor_plat_version_file or not os.path.exists( vendor_plat_version_file): raise ExternalError('Missing required sepolicy file %s', vendor_plat_version_file) with open(vendor_plat_version_file) as f: vendor_plat_version = f.read().strip() # Use the same flags and arguments as selinux.cpp OpenSplitPolicy(). cmd = ['secilc', '-m', '-M', 'true', '-G', '-N'] cmd.extend(['-c', kernel_sepolicy_version]) cmd.extend(['-o', output_policy]) cmd.extend(['-f', '/dev/null']) required_policy_files = ( ('system', 'etc/selinux/plat_sepolicy.cil'), ('system', 'etc/selinux/mapping/%s.cil' % vendor_plat_version), ('vendor', 'etc/selinux/vendor_sepolicy.cil'), ('vendor', 'etc/selinux/plat_pub_versioned.cil'), ) for policy in (map(lambda partition_and_path: get_file(*partition_and_path), required_policy_files)): if not policy or not os.path.exists(policy): raise ExternalError('Missing required sepolicy file %s', policy) cmd.append(policy) optional_policy_files = ( ('system', 'etc/selinux/mapping/%s.compat.cil' % vendor_plat_version), ('system_ext', 'etc/selinux/system_ext_sepolicy.cil'), ('system_ext', 'etc/selinux/mapping/%s.cil' % vendor_plat_version), ('product', 'etc/selinux/product_sepolicy.cil'), ('product', 'etc/selinux/mapping/%s.cil' % vendor_plat_version), ('odm', 'etc/selinux/odm_sepolicy.cil'), ) for policy in (map(lambda partition_and_path: get_file(*partition_and_path), optional_policy_files)): if policy and os.path.exists(policy): cmd.append(policy) return cmd def process_special_cases(framework_target_files_temp_dir, def process_special_cases(framework_target_files_temp_dir, vendor_target_files_temp_dir, vendor_target_files_temp_dir, output_target_files_temp_dir, output_target_files_temp_dir, Loading Loading @@ -977,17 +1052,28 @@ def merge_target_files(temp_dir, framework_target_files, framework_item_list, raise ValueError('sharedUserId APK error. See %s' % raise ValueError('sharedUserId APK error. See %s' % shareduid_violation_modules) shareduid_violation_modules) # Run host_init_verifier on the combined init rc files. # host_init_verifier and secilc check only the following partitions: filtered_partitions = { filtered_partitions = { partition: path partition: path for partition, path in partition_map.items() for partition, path in partition_map.items() # host_init_verifier checks only the following partitions: if partition in ['system', 'system_ext', 'product', 'vendor', 'odm'] if partition in ['system', 'system_ext', 'product', 'vendor', 'odm'] } } # Run host_init_verifier on the combined init rc files. common.RunHostInitVerifier( common.RunHostInitVerifier( product_out=output_target_files_temp_dir, product_out=output_target_files_temp_dir, partition_map=filtered_partitions) partition_map=filtered_partitions) # Check that the split sepolicy from the multiple builds can compile. split_sepolicy_cmd = compile_split_sepolicy( product_out=output_target_files_temp_dir, partition_map=filtered_partitions, output_policy=os.path.join(output_target_files_temp_dir, 'META/combined.policy')) logger.info('Compiling split sepolicy: %s', ' '.join(split_sepolicy_cmd)) common.RunAndCheckOutput(split_sepolicy_cmd) # TODO(b/178864050): Run tests on the combined.policy file. generate_images(output_target_files_temp_dir, rebuild_recovery) generate_images(output_target_files_temp_dir, rebuild_recovery) generate_super_empty_image(output_target_files_temp_dir, output_super_empty) generate_super_empty_image(output_target_files_temp_dir, output_super_empty) Loading tools/releasetools/test_merge_target_files.py +45 −6 Original line number Original line Diff line number Diff line Loading @@ -18,12 +18,11 @@ import os.path import common import common import test_utils import test_utils from merge_target_files import (validate_config_lists, from merge_target_files import ( DEFAULT_FRAMEWORK_ITEM_LIST, validate_config_lists, DEFAULT_FRAMEWORK_ITEM_LIST, DEFAULT_VENDOR_ITEM_LIST, DEFAULT_VENDOR_ITEM_LIST, DEFAULT_FRAMEWORK_MISC_INFO_KEYS, copy_items, DEFAULT_FRAMEWORK_MISC_INFO_KEYS, copy_items, item_list_to_partition_set, process_apex_keys_apk_certs_common, item_list_to_partition_set, compile_split_sepolicy) process_apex_keys_apk_certs_common) class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase): class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase): Loading Loading @@ -235,3 +234,43 @@ class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase): ] ] partition_set = item_list_to_partition_set(item_list) partition_set = item_list_to_partition_set(item_list) self.assertEqual(set(['product', 'system', 'system_ext']), partition_set) self.assertEqual(set(['product', 'system', 'system_ext']), partition_set) def test_compile_split_sepolicy(self): product_out_dir = common.MakeTempDir() def write_temp_file(path, data=''): full_path = os.path.join(product_out_dir, path) if not os.path.exists(os.path.dirname(full_path)): os.makedirs(os.path.dirname(full_path)) with open(full_path, 'w') as f: f.write(data) write_temp_file( 'system/etc/vintf/compatibility_matrix.device.xml', """ <compatibility-matrix> <sepolicy> <kernel-sepolicy-version>30</kernel-sepolicy-version> </sepolicy> </compatibility-matrix>""") write_temp_file('vendor/etc/selinux/plat_sepolicy_vers.txt', '30.0') write_temp_file('system/etc/selinux/plat_sepolicy.cil') write_temp_file('system/etc/selinux/mapping/30.0.cil') write_temp_file('product/etc/selinux/mapping/30.0.cil') write_temp_file('vendor/etc/selinux/vendor_sepolicy.cil') write_temp_file('vendor/etc/selinux/plat_pub_versioned.cil') cmd = compile_split_sepolicy(product_out_dir, { 'system': 'system', 'product': 'product', 'vendor': 'vendor', }, os.path.join(product_out_dir, 'policy')) self.assertEqual(' '.join(cmd), ('secilc -m -M true -G -N -c 30 ' '-o {OTP}/policy -f /dev/null ' '{OTP}/system/etc/selinux/plat_sepolicy.cil ' '{OTP}/system/etc/selinux/mapping/30.0.cil ' '{OTP}/vendor/etc/selinux/vendor_sepolicy.cil ' '{OTP}/vendor/etc/selinux/plat_pub_versioned.cil ' '{OTP}/product/etc/selinux/mapping/30.0.cil').format( OTP=product_out_dir)) Loading
core/Makefile +1 −0 Original line number Original line Diff line number Diff line Loading @@ -4136,6 +4136,7 @@ INTERNAL_OTATOOLS_MODULES := \ mkuserimg_mke2fs \ mkuserimg_mke2fs \ ota_from_target_files \ ota_from_target_files \ repack_bootimg \ repack_bootimg \ secilc \ sefcontext_compile \ sefcontext_compile \ sgdisk \ sgdisk \ shflags \ shflags \ Loading
tools/releasetools/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -451,6 +451,7 @@ python_binary_host { required: [ required: [ "checkvintf", "checkvintf", "host_init_verifier", "host_init_verifier", "secilc", ], ], target: { target: { darwin: { darwin: { Loading
tools/releasetools/merge_target_files.py +88 −2 Original line number Original line Diff line number Diff line Loading @@ -93,6 +93,7 @@ import shutil import subprocess import subprocess import sys import sys import zipfile import zipfile from xml.etree import ElementTree import add_img_to_target_files import add_img_to_target_files import build_super_image import build_super_image Loading Loading @@ -658,6 +659,80 @@ def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir, os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin')) os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin')) def compile_split_sepolicy(product_out, partition_map, output_policy): """Uses secilc to compile a split sepolicy file. Depends on various */etc/selinux/* and */etc/vintf/* files within partitions. Args: product_out: PRODUCT_OUT directory, containing partition directories. partition_map: A map of partition name -> relative path within product_out. output_policy: The name of the output policy created by secilc. Returns: A command list that can be executed to create the compiled sepolicy. """ def get_file(partition, path): if partition not in partition_map: logger.warning('Cannot load SEPolicy files for missing partition %s', partition) return None return os.path.join(product_out, partition_map[partition], path) # Load the kernel sepolicy version from the FCM. This is normally provided # directly to selinux.cpp as a build flag, but is also available in this file. fcm_file = get_file('system', 'etc/vintf/compatibility_matrix.device.xml') if not fcm_file or not os.path.exists(fcm_file): raise ExternalError('Missing required file for loading sepolicy: %s', fcm) kernel_sepolicy_version = ElementTree.parse(fcm_file).getroot().find( 'sepolicy/kernel-sepolicy-version').text # Load the vendor's plat sepolicy version. This is the version used for # locating sepolicy mapping files. vendor_plat_version_file = get_file('vendor', 'etc/selinux/plat_sepolicy_vers.txt') if not vendor_plat_version_file or not os.path.exists( vendor_plat_version_file): raise ExternalError('Missing required sepolicy file %s', vendor_plat_version_file) with open(vendor_plat_version_file) as f: vendor_plat_version = f.read().strip() # Use the same flags and arguments as selinux.cpp OpenSplitPolicy(). cmd = ['secilc', '-m', '-M', 'true', '-G', '-N'] cmd.extend(['-c', kernel_sepolicy_version]) cmd.extend(['-o', output_policy]) cmd.extend(['-f', '/dev/null']) required_policy_files = ( ('system', 'etc/selinux/plat_sepolicy.cil'), ('system', 'etc/selinux/mapping/%s.cil' % vendor_plat_version), ('vendor', 'etc/selinux/vendor_sepolicy.cil'), ('vendor', 'etc/selinux/plat_pub_versioned.cil'), ) for policy in (map(lambda partition_and_path: get_file(*partition_and_path), required_policy_files)): if not policy or not os.path.exists(policy): raise ExternalError('Missing required sepolicy file %s', policy) cmd.append(policy) optional_policy_files = ( ('system', 'etc/selinux/mapping/%s.compat.cil' % vendor_plat_version), ('system_ext', 'etc/selinux/system_ext_sepolicy.cil'), ('system_ext', 'etc/selinux/mapping/%s.cil' % vendor_plat_version), ('product', 'etc/selinux/product_sepolicy.cil'), ('product', 'etc/selinux/mapping/%s.cil' % vendor_plat_version), ('odm', 'etc/selinux/odm_sepolicy.cil'), ) for policy in (map(lambda partition_and_path: get_file(*partition_and_path), optional_policy_files)): if policy and os.path.exists(policy): cmd.append(policy) return cmd def process_special_cases(framework_target_files_temp_dir, def process_special_cases(framework_target_files_temp_dir, vendor_target_files_temp_dir, vendor_target_files_temp_dir, output_target_files_temp_dir, output_target_files_temp_dir, Loading Loading @@ -977,17 +1052,28 @@ def merge_target_files(temp_dir, framework_target_files, framework_item_list, raise ValueError('sharedUserId APK error. See %s' % raise ValueError('sharedUserId APK error. See %s' % shareduid_violation_modules) shareduid_violation_modules) # Run host_init_verifier on the combined init rc files. # host_init_verifier and secilc check only the following partitions: filtered_partitions = { filtered_partitions = { partition: path partition: path for partition, path in partition_map.items() for partition, path in partition_map.items() # host_init_verifier checks only the following partitions: if partition in ['system', 'system_ext', 'product', 'vendor', 'odm'] if partition in ['system', 'system_ext', 'product', 'vendor', 'odm'] } } # Run host_init_verifier on the combined init rc files. common.RunHostInitVerifier( common.RunHostInitVerifier( product_out=output_target_files_temp_dir, product_out=output_target_files_temp_dir, partition_map=filtered_partitions) partition_map=filtered_partitions) # Check that the split sepolicy from the multiple builds can compile. split_sepolicy_cmd = compile_split_sepolicy( product_out=output_target_files_temp_dir, partition_map=filtered_partitions, output_policy=os.path.join(output_target_files_temp_dir, 'META/combined.policy')) logger.info('Compiling split sepolicy: %s', ' '.join(split_sepolicy_cmd)) common.RunAndCheckOutput(split_sepolicy_cmd) # TODO(b/178864050): Run tests on the combined.policy file. generate_images(output_target_files_temp_dir, rebuild_recovery) generate_images(output_target_files_temp_dir, rebuild_recovery) generate_super_empty_image(output_target_files_temp_dir, output_super_empty) generate_super_empty_image(output_target_files_temp_dir, output_super_empty) Loading
tools/releasetools/test_merge_target_files.py +45 −6 Original line number Original line Diff line number Diff line Loading @@ -18,12 +18,11 @@ import os.path import common import common import test_utils import test_utils from merge_target_files import (validate_config_lists, from merge_target_files import ( DEFAULT_FRAMEWORK_ITEM_LIST, validate_config_lists, DEFAULT_FRAMEWORK_ITEM_LIST, DEFAULT_VENDOR_ITEM_LIST, DEFAULT_VENDOR_ITEM_LIST, DEFAULT_FRAMEWORK_MISC_INFO_KEYS, copy_items, DEFAULT_FRAMEWORK_MISC_INFO_KEYS, copy_items, item_list_to_partition_set, process_apex_keys_apk_certs_common, item_list_to_partition_set, compile_split_sepolicy) process_apex_keys_apk_certs_common) class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase): class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase): Loading Loading @@ -235,3 +234,43 @@ class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase): ] ] partition_set = item_list_to_partition_set(item_list) partition_set = item_list_to_partition_set(item_list) self.assertEqual(set(['product', 'system', 'system_ext']), partition_set) self.assertEqual(set(['product', 'system', 'system_ext']), partition_set) def test_compile_split_sepolicy(self): product_out_dir = common.MakeTempDir() def write_temp_file(path, data=''): full_path = os.path.join(product_out_dir, path) if not os.path.exists(os.path.dirname(full_path)): os.makedirs(os.path.dirname(full_path)) with open(full_path, 'w') as f: f.write(data) write_temp_file( 'system/etc/vintf/compatibility_matrix.device.xml', """ <compatibility-matrix> <sepolicy> <kernel-sepolicy-version>30</kernel-sepolicy-version> </sepolicy> </compatibility-matrix>""") write_temp_file('vendor/etc/selinux/plat_sepolicy_vers.txt', '30.0') write_temp_file('system/etc/selinux/plat_sepolicy.cil') write_temp_file('system/etc/selinux/mapping/30.0.cil') write_temp_file('product/etc/selinux/mapping/30.0.cil') write_temp_file('vendor/etc/selinux/vendor_sepolicy.cil') write_temp_file('vendor/etc/selinux/plat_pub_versioned.cil') cmd = compile_split_sepolicy(product_out_dir, { 'system': 'system', 'product': 'product', 'vendor': 'vendor', }, os.path.join(product_out_dir, 'policy')) self.assertEqual(' '.join(cmd), ('secilc -m -M true -G -N -c 30 ' '-o {OTP}/policy -f /dev/null ' '{OTP}/system/etc/selinux/plat_sepolicy.cil ' '{OTP}/system/etc/selinux/mapping/30.0.cil ' '{OTP}/vendor/etc/selinux/vendor_sepolicy.cil ' '{OTP}/vendor/etc/selinux/plat_pub_versioned.cil ' '{OTP}/product/etc/selinux/mapping/30.0.cil').format( OTP=product_out_dir))