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

Commit e8dfaf75 authored by Ryan Mitchell's avatar Ryan Mitchell Committed by Android (Google) Code Review
Browse files

Merge "Enforce a default policy on packages without <overlayable>"

parents ed3a2ff5 48945224
Loading
Loading
Loading
Loading
+18 −3
Original line number Diff line number Diff line
@@ -287,11 +287,20 @@ std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream,
bool CheckOverlayable(const LoadedPackage& target_package,
                      const utils::OverlayManifestInfo& overlay_info,
                      const PolicyBitmask& fulfilled_policies, const ResourceId& resid) {
  static constexpr const PolicyBitmask sDefaultPolicies =
      PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION |
      PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::POLICY_SIGNATURE;

  // If the resource does not have an overlayable definition, allow the resource to be overlaid if
  // the overlay is preinstalled or signed with the same signature as the target.
  if (!target_package.DefinesOverlayable()) {
    return (sDefaultPolicies & fulfilled_policies) != 0;
  }

  const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(resid);
  if (overlayable_info == nullptr) {
    // If the resource does not have an overlayable definition, allow the resource to be overlaid.
    // Once overlayable enforcement is turned on, this check will return false.
    return !target_package.DefinesOverlayable();
    // Do not allow non-overlayable resources to be overlaid.
    return false;
  }

  if (overlay_info.target_name != overlayable_info->name) {
@@ -427,6 +436,12 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(
    matching_resources.Add(target_resid, overlay_resid);
  }

  if (matching_resources.Map().empty()) {
    out_error << "overlay \"" << overlay_apk_path << "\" does not successfully overlay any resource"
              << std::endl;
    return nullptr;
  }

  // encode idmap data
  std::unique_ptr<IdmapData> data(new IdmapData());
  const auto types_end = matching_resources.Map().cend();
+118 −156
Original line number Diff line number Diff line
@@ -173,20 +173,27 @@ TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) {
  ASSERT_THAT(idmap, IsNull());
}

TEST(IdmapTests, CreateIdmapFromApkAssets) {
  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
void CreateIdmap(const StringPiece& target_apk_path, const StringPiece& overlay_apk_path,
                 const PolicyBitmask& fulfilled_policies, bool enforce_overlayable,
                 std::unique_ptr<const Idmap>* out_idmap) {
  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path.to_string());
  ASSERT_THAT(target_apk, NotNull());

  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path.to_string());
  ASSERT_THAT(overlay_apk, NotNull());

  std::stringstream error;
  std::unique_ptr<const Idmap> idmap =
      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
  ASSERT_THAT(idmap, NotNull());
  *out_idmap =
      Idmap::FromApkAssets(target_apk_path.to_string(), *target_apk, overlay_apk_path.to_string(),
                           *overlay_apk, fulfilled_policies, enforce_overlayable, error);
}

TEST(IdmapTests, CreateIdmapFromApkAssets) {
  std::unique_ptr<const Idmap> idmap;
  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
              /* enforce_overlayable */ true, &idmap);

  ASSERT_THAT(idmap->GetHeader(), NotNull());
  ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
@@ -226,19 +233,12 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) {

// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
  ASSERT_THAT(target_apk, NotNull());

  const std::string overlay_apk_path(GetTestDataPath() + "/system-overlay/system-overlay.apk");
  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
  ASSERT_THAT(overlay_apk, NotNull());

  std::stringstream error;
  std::unique_ptr<const Idmap> idmap =
      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
  std::unique_ptr<const Idmap> idmap;
  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
  std::string overlay_apk_path = GetTestDataPath() + "/system-overlay/system-overlay.apk";
  CreateIdmap(target_apk_path, overlay_apk_path,
              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
                           /* enforce_overlayable */ true, error);
              /* enforce_overlayable */ true, &idmap);
  ASSERT_THAT(idmap, NotNull());

  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -263,21 +263,12 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
}

TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
  ASSERT_THAT(target_apk, NotNull());

  const std::string overlay_apk_path(GetTestDataPath() +
                                     "/signature-overlay/signature-overlay.apk");
  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
  ASSERT_THAT(overlay_apk, NotNull());

  uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE;

  std::stringstream error;
  std::unique_ptr<const Idmap> idmap =
      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
                           policy_flags, /* enforce_overlayable */ true, error);
  std::unique_ptr<const Idmap> idmap;
  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
  std::string overlay_apk_path = GetTestDataPath() + "/signature-overlay/signature-overlay.apk";
  CreateIdmap(target_apk_path, overlay_apk_path,
              PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE,
              /* enforce_overlayable */ true, &idmap);
  ASSERT_THAT(idmap, NotNull());

  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -298,52 +289,15 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/policy_signature
}

TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignatureNotFulfilled) {
  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
  ASSERT_THAT(target_apk, NotNull());

  const std::string overlay_apk_path(GetTestDataPath() +
                                     "/signature-overlay/signature-overlay.apk");
  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
  ASSERT_THAT(overlay_apk, NotNull());

  uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC;

  std::stringstream error;
  std::unique_ptr<const Idmap> idmap =
      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
                           policy_flags, /* enforce_overlayable */ true, error);
  ASSERT_THAT(idmap, NotNull());

  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
  ASSERT_EQ(dataBlocks.size(), 1U);

  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];

  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 0U);

  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
  ASSERT_EQ(types.size(), 0U);  // can't overlay, so contains nothing
}

// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
  ASSERT_THAT(target_apk, NotNull());

  const std::string overlay_apk_path(GetTestDataPath() +
                                     "/system-overlay-invalid/system-overlay-invalid.apk");
  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
  ASSERT_THAT(overlay_apk, NotNull());

  std::stringstream error;
  std::unique_ptr<const Idmap> idmap =
      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
  std::unique_ptr<const Idmap> idmap;
  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
  std::string overlay_apk_path =
      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
  CreateIdmap(target_apk_path, overlay_apk_path,
              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
                           /* enforce_overlayable */ true, error);
              /* enforce_overlayable */ true, &idmap);
  ASSERT_THAT(idmap, NotNull());

  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -369,20 +323,13 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {

// Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
  ASSERT_THAT(target_apk, NotNull());

  const std::string overlay_apk_path(GetTestDataPath() +
                                     "/system-overlay-invalid/system-overlay-invalid.apk");
  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
  ASSERT_THAT(overlay_apk, NotNull());

  std::stringstream error;
  std::unique_ptr<const Idmap> idmap =
      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
  std::unique_ptr<const Idmap> idmap;
  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
  std::string overlay_apk_path =
      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
  CreateIdmap(target_apk_path, overlay_apk_path,
              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
                           /* enforce_overlayable */ false, error);
              /* enforce_overlayable */ false, &idmap);
  ASSERT_THAT(idmap, NotNull());

  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -409,24 +356,62 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgn
  ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_system_vendor
}

// The resources of APKs that do not include an overlayable declaration should not restrict what
// resources can be overlaid.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayable) {
  const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
  ASSERT_THAT(target_apk, NotNull());
// Overlays that do not specify a target <overlayable> can overlay resources defined as overlayable.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
  std::unique_ptr<const Idmap> idmap;
  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
              /* enforce_overlayable */ false, &idmap);
  ASSERT_THAT(idmap, NotNull());

  const std::string overlay_apk_path(GetTestDataPath() +
                                     "/system-overlay-invalid/system-overlay-invalid.apk");
  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
  ASSERT_THAT(overlay_apk, NotNull());
  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
  ASSERT_EQ(dataBlocks.size(), 1U);

  std::stringstream error;
  std::unique_ptr<const Idmap> idmap =
      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
  ASSERT_THAT(idmap, NotNull());
  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];

  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);

  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
  ASSERT_EQ(types.size(), 2U);

  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/int1

  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
  ASSERT_EQ(types[1]->GetEntryCount(), 4U);
  ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);   // string/str1
  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);  // string/str2
  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);   // string/str3
  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);   // string/str4
}

// Overlays that are not pre-installed and are not signed with the same signature as the target
// cannot overlay packages that have not defined overlayable resources.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPoliciesPublicFail) {
  std::unique_ptr<const Idmap> idmap;
  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
              /* enforce_overlayable */ true, &idmap);
  ASSERT_THAT(idmap, IsNull());
}

// Overlays that are pre-installed or are signed with the same signature as the target can overlay
// packages that have not defined overlayable resources.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) {
  std::unique_ptr<const Idmap> idmap;
  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
  std::string overlay_apk_path =
      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";

  auto CheckEntries = [&]() -> void {
    const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
    ASSERT_EQ(dataBlocks.size(), 1U);

@@ -449,50 +434,27 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayable) {
    ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/string/policy_signature
    ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_system
    ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_system_vendor
}

// The resources of APKs that do not include an overlayable declaration should not restrict what
// resources can be overlaid.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
  const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
  ASSERT_THAT(target_apk, NotNull());

  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay-no-name.apk");
  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
  ASSERT_THAT(overlay_apk, NotNull());
  };

  std::stringstream error;
  std::unique_ptr<const Idmap> idmap =
      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SIGNATURE,
              /* enforce_overlayable */ true, &idmap);
  ASSERT_THAT(idmap, NotNull());
  CheckEntries();

  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
  ASSERT_EQ(dataBlocks.size(), 1U);

  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];

  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);

  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
  ASSERT_EQ(types.size(), 2U);
  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PRODUCT_PARTITION,
              /* enforce_overlayable */ true, &idmap);
  ASSERT_THAT(idmap, NotNull());
  CheckEntries();

  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SYSTEM_PARTITION,
              /* enforce_overlayable */ true, &idmap);
  ASSERT_THAT(idmap, NotNull());
  CheckEntries();

  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
  ASSERT_EQ(types[1]->GetEntryCount(), 4U);
  ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_VENDOR_PARTITION,
              /* enforce_overlayable */ true, &idmap);
  ASSERT_THAT(idmap, NotNull());
  CheckEntries();
}

TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
+1 −1
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

FRAMEWORK_RES_APK="${ANDROID_BUILD_TOP}/out/target/common/obj/APPS/framework-res_intermediates/package-export.apk"
FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar

aapt2 compile --dir res -o compiled.flata