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

Commit 2793fd2e authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Creates a combined split-sepolicy file in merge_target_files.py."

parents c66465a4 48603ff1
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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 \
+1 −0
Original line number Original line Diff line number Diff line
@@ -451,6 +451,7 @@ python_binary_host {
    required: [
    required: [
        "checkvintf",
        "checkvintf",
        "host_init_verifier",
        "host_init_verifier",
        "secilc",
    ],
    ],
    target: {
    target: {
        darwin: {
        darwin: {
+88 −2
Original line number Original line Diff line number Diff line
@@ -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
@@ -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,
@@ -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)
+45 −6
Original line number Original line Diff line number Diff line
@@ -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):
@@ -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))