Adds image-specific selinux_fc props to allow different file_contexts.
This enables mixed builds to use the file_contexts.bin from the system
build when regenerating images that come from system target files, and
similarly for file_contexts.bin from the other build when regenerating
images from other target files.
In monolithic (non-mixed) builds all image-specific selinux_fc props
point to the same file_contexts.
Bug: 132108151
Test: Built and booted mixed build devices.
Change-Id: Id51ed6d96ea6337879f1ab21d47c93c67bc25312
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 4136ed4..ba04651 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -519,7 +519,6 @@
common_props = (
"extfs_sparse_flag",
"squashfs_sparse_flag",
- "selinux_fc",
"skip_fsck",
"ext_mkuserimg",
"verity",
@@ -564,6 +563,7 @@
if not copy_prop("system_extfs_rsv_pct", "extfs_rsv_pct"):
d["extfs_rsv_pct"] = "0"
copy_prop("system_reserved_size", "partition_reserved_size")
+ copy_prop("system_selinux_fc", "selinux_fc")
elif mount_point == "system_other":
# We inherit the selinux policies of /system since we contain some of its
# files.
@@ -587,6 +587,7 @@
if not copy_prop("system_extfs_rsv_pct", "extfs_rsv_pct"):
d["extfs_rsv_pct"] = "0"
copy_prop("system_reserved_size", "partition_reserved_size")
+ copy_prop("system_selinux_fc", "selinux_fc")
elif mount_point == "data":
# Copy the generic fs type first, override with specific one if available.
copy_prop("fs_type", "fs_type")
@@ -594,9 +595,11 @@
copy_prop("userdata_size", "partition_size")
copy_prop("flash_logical_block_size", "flash_logical_block_size")
copy_prop("flash_erase_block_size", "flash_erase_block_size")
+ copy_prop("userdata_selinux_fc", "selinux_fc")
elif mount_point == "cache":
copy_prop("cache_fs_type", "fs_type")
copy_prop("cache_size", "partition_size")
+ copy_prop("cache_selinux_fc", "selinux_fc")
elif mount_point == "vendor":
copy_prop("avb_vendor_hashtree_enable", "avb_hashtree_enable")
copy_prop("avb_vendor_add_hashtree_footer_args",
@@ -618,6 +621,7 @@
if not copy_prop("vendor_extfs_rsv_pct", "extfs_rsv_pct"):
d["extfs_rsv_pct"] = "0"
copy_prop("vendor_reserved_size", "partition_reserved_size")
+ copy_prop("vendor_selinux_fc", "selinux_fc")
elif mount_point == "product":
copy_prop("avb_product_hashtree_enable", "avb_hashtree_enable")
copy_prop("avb_product_add_hashtree_footer_args",
@@ -639,6 +643,7 @@
if not copy_prop("product_extfs_rsv_pct", "extfs_rsv_pct"):
d["extfs_rsv_pct"] = "0"
copy_prop("product_reserved_size", "partition_reserved_size")
+ copy_prop("product_selinux_fc", "selinux_fc")
elif mount_point == "product_services":
copy_prop("avb_product_services_hashtree_enable", "avb_hashtree_enable")
copy_prop("avb_product_services_add_hashtree_footer_args",
@@ -662,6 +667,7 @@
if not copy_prop("product_services_extfs_rsv_pct", "extfs_rsv_pct"):
d["extfs_rsv_pct"] = "0"
copy_prop("product_services_reserved_size", "partition_reserved_size")
+ copy_prop("product_services_selinux_fc", "selinux_fc")
elif mount_point == "odm":
copy_prop("avb_odm_hashtree_enable", "avb_hashtree_enable")
copy_prop("avb_odm_add_hashtree_footer_args",
@@ -683,6 +689,7 @@
if not copy_prop("odm_extfs_rsv_pct", "extfs_rsv_pct"):
d["extfs_rsv_pct"] = "0"
copy_prop("odm_reserved_size", "partition_reserved_size")
+ copy_prop("odm_selinux_fc", "selinux_fc")
elif mount_point == "oem":
copy_prop("fs_type", "fs_type")
copy_prop("oem_size", "partition_size")
@@ -692,6 +699,7 @@
copy_prop("ext4_share_dup_blocks", "ext4_share_dup_blocks")
if not copy_prop("oem_extfs_rsv_pct", "extfs_rsv_pct"):
d["extfs_rsv_pct"] = "0"
+ copy_prop("oem_selinux_fc", "selinux_fc")
d["partition_name"] = mount_point
return d
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index e642297..5bdb2a7 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -332,13 +332,15 @@
raise ValueError("Failed to find 'fstab_version'")
if repacking:
- # "selinux_fc" should point to the file_contexts file (file_contexts.bin)
- # under META/.
- fc_basename = os.path.basename(d.get("selinux_fc", "file_contexts"))
- fc_config = os.path.join(input_file, "META", fc_basename)
- assert os.path.exists(fc_config)
+ # "selinux_fc" properties should point to the file_contexts files
+ # (file_contexts.bin) under META/.
+ for key in d:
+ if key.endswith("selinux_fc"):
+ fc_basename = os.path.basename(d[key])
+ fc_config = os.path.join(input_file, "META", fc_basename)
+ assert os.path.exists(fc_config)
- d["selinux_fc"] = fc_config
+ d[key] = fc_config
# Similarly we need to redirect "root_dir", and "root_fs_config".
d["root_dir"] = os.path.join(input_file, "ROOT")
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index 2a722c5..e8c3cf7 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -160,7 +160,6 @@
default_other_item_list = [
'META/boot_filesystem_config.txt',
- 'META/file_contexts.bin',
'META/otakeys.txt',
'META/releasetools.py',
'META/vendor_filesystem_config.txt',
@@ -501,6 +500,18 @@
list_suffix='_partition_list')
merged_info_dict.update(merged_dynamic_partitions_dict)
+ # Replace <image>_selinux_fc values with system or other file_contexts.bin
+ # depending on which dictionary the key came from.
+ # Only the file basename is required because all selinux_fc properties are
+ # replaced with the full path to the file under META/ when misc_info.txt is
+ # loaded from target files for repacking. See common.py LoadInfoDict().
+ for key in merged_info_dict:
+ if key.endswith('_selinux_fc'):
+ merged_info_dict[key] = 'other_file_contexts.bin'
+ for key in system_info_dict:
+ if key.endswith('_selinux_fc'):
+ merged_info_dict[key] = 'system_file_contexts.bin'
+
output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
'misc_info.txt')
write_sorted_data(data=merged_info_dict, path=output_misc_info_txt)
@@ -605,6 +616,28 @@
write_sorted_data(data=other_dict.values(), path=output_file)
+def copy_file_contexts(system_target_files_dir, other_target_files_dir,
+ output_target_files_dir):
+ """Creates named copies of each build's file_contexts.bin in output META/."""
+ system_fc_path = os.path.join(system_target_files_dir, 'META', 'system_file_contexts.bin')
+ if not os.path.exists(system_fc_path):
+ system_fc_path = os.path.join(system_target_files_dir, 'META', 'file_contexts.bin')
+ if not os.path.exists(system_fc_path):
+ raise ValueError('Missing system file_contexts.bin.')
+ shutil.copyfile(
+ system_fc_path,
+ os.path.join(output_target_files_dir, 'META', 'system_file_contexts.bin'))
+
+ other_fc_path = os.path.join(other_target_files_dir, 'META', 'other_file_contexts.bin')
+ if not os.path.exists(other_fc_path):
+ other_fc_path = os.path.join(other_target_files_dir, 'META', 'file_contexts.bin')
+ if not os.path.exists(other_fc_path):
+ raise ValueError('Missing other file_contexts.bin.')
+ shutil.copyfile(
+ other_fc_path,
+ os.path.join(output_target_files_dir, 'META', 'other_file_contexts.bin'))
+
+
def process_special_cases(system_target_files_temp_dir,
other_target_files_temp_dir,
output_target_files_temp_dir, system_misc_info_keys,
@@ -638,6 +671,11 @@
append_recovery_to_filesystem_config(
output_target_files_temp_dir=output_target_files_temp_dir)
+ copy_file_contexts(
+ system_target_files_dir=system_target_files_temp_dir,
+ other_target_files_dir=other_target_files_temp_dir,
+ output_target_files_dir=output_target_files_temp_dir)
+
process_misc_info_txt(
system_target_files_temp_dir=system_target_files_temp_dir,
other_target_files_temp_dir=other_target_files_temp_dir,