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

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

Merge "Enforce overlayable API when defined"

parents a7c7b75e 19823450
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -16,11 +16,11 @@ cc_defaults {
    name: "idmap2_defaults",
    tidy: true,
    tidy_checks: [
        "modernize-*",
        "-modernize-avoid-c-arrays",
        "android-*",
        "misc-*",
        "modernize-*",
        "readability-*",
        "-modernize-avoid-c-arrays",
    ],
    tidy_flags: [
        "-system-headers",
+2 −2
Original line number Diff line number Diff line
@@ -281,10 +281,10 @@ bool CheckOverlayable(const LoadedPackage& target_package,
  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 true;
    return !target_package.DefinesOverlayable();
  }

  if (!overlay_info.target_name.empty() && overlay_info.target_name != overlayable_info->name) {
  if (overlay_info.target_name != overlayable_info->name) {
    // If the overlay supplies a target overlayable name, the resource must belong to the
    // overlayable defined with the specified name to be overlaid.
    return false;
+17 −10
Original line number Diff line number Diff line
@@ -40,9 +40,14 @@ TEST(FileUtilsTests, FindFilesFindEverythingNonRecursive) {
                               const std::string& path ATTRIBUTE_UNUSED) -> bool { return true; });
  ASSERT_THAT(v, NotNull());
  ASSERT_EQ(v->size(), 6U);
  ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
            std::set<std::string>({root + "/.", root + "/..", root + "/overlay", root + "/target",
                                   root + "/system-overlay", root + "/system-overlay-invalid"}));
  ASSERT_EQ(std::set<std::string>(v->begin(), v->end()), std::set<std::string>({
                                                             root + "/.",
                                                             root + "/..",
                                                             root + "/overlay",
                                                             root + "/target",
                                                             root + "/system-overlay",
                                                             root + "/system-overlay-invalid",
                                                         }));
}

TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
@@ -51,12 +56,14 @@ TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
    return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0;
  });
  ASSERT_THAT(v, NotNull());
  ASSERT_EQ(v->size(), 6U);
  ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
            std::set<std::string>({root + "/target/target.apk", root + "/overlay/overlay.apk",
                                   root + "/overlay/overlay-static-1.apk",
                                   root + "/overlay/overlay-static-2.apk",
                                   root + "/system-overlay/system-overlay.apk",
  ASSERT_EQ(v->size(), 9U);
  ASSERT_EQ(
      std::set<std::string>(v->begin(), v->end()),
      std::set<std::string>(
          {root + "/target/target.apk", root + "/target/target-no-overlayable.apk",
           root + "/overlay/overlay.apk", root + "/overlay/overlay-no-name.apk",
           root + "/overlay/overlay-no-name-static.apk", root + "/overlay/overlay-static-1.apk",
           root + "/overlay/overlay-static-2.apk", root + "/system-overlay/system-overlay.apk",
           root + "/system-overlay-invalid/system-overlay-invalid.apk"}));
}

+14 −0
Original line number Diff line number Diff line
@@ -163,8 +163,12 @@ TEST_F(Idmap2BinaryTests, Dump) {
TEST_F(Idmap2BinaryTests, Scan) {
  SKIP_TEST_IF_CANT_EXEC_IDMAP2;

  const std::string overlay_static_no_name_apk_path =
      GetTestDataPath() + "/overlay/overlay-no-name-static.apk";
  const std::string overlay_static_1_apk_path = GetTestDataPath() + "/overlay/overlay-static-1.apk";
  const std::string overlay_static_2_apk_path = GetTestDataPath() + "/overlay/overlay-static-2.apk";
  const std::string idmap_static_no_name_path =
      Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_no_name_apk_path);
  const std::string idmap_static_1_path =
      Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_1_apk_path);
  const std::string idmap_static_2_path =
@@ -184,11 +188,18 @@ TEST_F(Idmap2BinaryTests, Scan) {
  ASSERT_THAT(result, NotNull());
  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
  std::stringstream expected;
  expected << idmap_static_no_name_path << std::endl;
  expected << idmap_static_1_path << std::endl;
  expected << idmap_static_2_path << std::endl;
  ASSERT_EQ(result->stdout, expected.str());

  std::stringstream error;
  auto idmap_static_no_name_raw_string = utils::ReadFile(idmap_static_no_name_path);
  auto idmap_static_no_name_raw_stream = std::istringstream(*idmap_static_no_name_raw_string);
  auto idmap_static_no_name = Idmap::FromBinaryStream(idmap_static_no_name_raw_stream, error);
  ASSERT_THAT(idmap_static_no_name, NotNull());
  ASSERT_IDMAP(*idmap_static_no_name, GetTargetApkPath(), overlay_static_no_name_apk_path);

  auto idmap_static_1_raw_string = utils::ReadFile(idmap_static_1_path);
  auto idmap_static_1_raw_stream = std::istringstream(*idmap_static_1_raw_string);
  auto idmap_static_1 = Idmap::FromBinaryStream(idmap_static_1_raw_stream, error);
@@ -201,6 +212,7 @@ TEST_F(Idmap2BinaryTests, Scan) {
  ASSERT_THAT(idmap_static_2, NotNull());
  ASSERT_IDMAP(*idmap_static_2, GetTargetApkPath(), overlay_static_2_apk_path);

  unlink(idmap_static_no_name_path.c_str());
  unlink(idmap_static_2_path.c_str());
  unlink(idmap_static_1_path.c_str());

@@ -218,6 +230,7 @@ TEST_F(Idmap2BinaryTests, Scan) {
  ASSERT_THAT(result, NotNull());
  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
  ASSERT_EQ(result->stdout, expected.str());
  unlink(idmap_static_no_name_path.c_str());
  unlink(idmap_static_2_path.c_str());
  unlink(idmap_static_1_path.c_str());

@@ -236,6 +249,7 @@ TEST_F(Idmap2BinaryTests, Scan) {
  ASSERT_THAT(result, NotNull());
  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
  ASSERT_EQ(result->stdout, expected.str());
  unlink(idmap_static_no_name_path.c_str());
  unlink(idmap_static_2_path.c_str());
  unlink(idmap_static_1_path.c_str());

+96 −11
Original line number Diff line number Diff line
@@ -224,7 +224,8 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) {
  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
}

TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
// 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());
@@ -260,7 +261,8 @@ TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
  ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_system_vendor
}

TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
// 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());
@@ -288,20 +290,60 @@ TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
  ASSERT_EQ(types.size(), 1U);

  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
  ASSERT_EQ(types[0]->GetEntryCount(), 3U);
  ASSERT_EQ(types[0]->GetEntryOffset(), 6U);
  ASSERT_EQ(types[0]->GetEntry(0), 0x0003U);  // string/policy_public
  ASSERT_EQ(types[0]->GetEntry(1), 0x0004U);  // string/policy_system
  ASSERT_EQ(types[0]->GetEntry(2), 0x0005U);  // string/policy_system_vendor
}

// 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,
                           PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
                           /* enforce_overlayable */ false, 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(), 1U);

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

  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
  ASSERT_EQ(types[0]->GetEntryCount(), 6U);
  ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/not_overlayable
  ASSERT_EQ(types[0]->GetEntry(1), kNoEntry);  // string/other
  ASSERT_EQ(types[0]->GetEntry(2), kNoEntry);  // string/policy_product
  ASSERT_EQ(types[0]->GetEntry(1), 0x0001U);  // string/other
  ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_product
  ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);  // string/policy_public
  ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/policy_system
  ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_system_vendor
}

TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
// 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());

@@ -313,8 +355,7 @@ TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlaya
  std::stringstream error;
  std::unique_ptr<const Idmap> idmap =
      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
                           PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
                           /* enforce_overlayable */ false, error);
                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
  ASSERT_THAT(idmap, NotNull());

  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -340,6 +381,50 @@ TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlaya
  ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // 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);
  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(), 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);

  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
  ASSERT_EQ(types[1]->GetEntryCount(), 4U);
  ASSERT_EQ(types[1]->GetEntryOffset(), 9U);
  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);
}

TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
  std::string target_apk_path(GetTestDataPath());
  for (int i = 0; i < 32; i++) {
Loading