Loading cmds/idmap2/idmap2/Scan.cpp +13 −35 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include "idmap2/CommandLineOptions.h" #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" #include "idmap2/ResourceUtils.h" #include "idmap2/Xml.h" #include "idmap2/ZipFile.h" Loading @@ -36,14 +37,13 @@ using android::idmap2::CommandLineOptions; using android::idmap2::Idmap; using android::idmap2::MemoryChunk; using android::idmap2::PoliciesToBitmask; using android::idmap2::PolicyBitmask; using android::idmap2::PolicyFlags; using android::idmap2::Result; using android::idmap2::Xml; using android::idmap2::ZipFile; using android::idmap2::utils::ExtractOverlayManifestInfo; using android::idmap2::utils::FindFiles; using android::idmap2::utils::OverlayManifestInfo; namespace { Loading Loading @@ -138,46 +138,23 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { std::vector<InputOverlay> interesting_apks; for (const std::string& path : *apk_paths) { std::unique_ptr<const ZipFile> zip = ZipFile::Open(path); if (!zip) { out_error << "error: failed to open " << path << " as a zip file" << std::endl; Result<OverlayManifestInfo> overlay_info = ExtractOverlayManifestInfo(path, out_error, /* assert_overlay */ false); if (!overlay_info) { return false; } std::unique_ptr<const MemoryChunk> entry = zip->Uncompress("AndroidManifest.xml"); if (!entry) { out_error << "error: failed to uncompress AndroidManifest.xml from " << path << std::endl; return false; } std::unique_ptr<const Xml> xml = Xml::Create(entry->buf, entry->size); if (!xml) { out_error << "error: failed to parse AndroidManifest.xml from " << path << std::endl; continue; } const auto tag = xml->FindTag("overlay"); if (!tag) { continue; } auto iter = tag->find("isStatic"); if (iter == tag->end() || std::stoul(iter->second) == 0U) { continue; } iter = tag->find("targetPackage"); if (iter == tag->end() || iter->second != target_package_name) { if (!overlay_info->is_static) { continue; } iter = tag->find("priority"); if (iter == tag->end()) { if (overlay_info->target_package.empty() || overlay_info->target_package != target_package_name) { continue; } const int priority = std::stoi(iter->second); if (priority < 0) { if (overlay_info->priority < 0) { continue; } Loading @@ -203,7 +180,8 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, path); // Sort the static overlays in ascending priority order InputOverlay input{path, idmap_path, priority, override_policies, ignore_overlayable}; InputOverlay input{path, idmap_path, overlay_info->priority, override_policies, ignore_overlayable}; interesting_apks.insert( std::lower_bound(interesting_apks.begin(), interesting_apks.end(), input), input); } Loading cmds/idmap2/include/idmap2/ResourceUtils.h +14 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_ #define IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_ #include <optional> #include <ostream> #include <string> #include "android-base/macros.h" Loading @@ -24,9 +26,21 @@ #include "idmap2/Idmap.h" #include "idmap2/Result.h" #include "idmap2/ZipFile.h" namespace android::idmap2::utils { struct OverlayManifestInfo { std::string target_package; // NOLINT(misc-non-private-member-variables-in-classes) std::string target_name; // NOLINT(misc-non-private-member-variables-in-classes) bool is_static; // NOLINT(misc-non-private-member-variables-in-classes) int priority = -1; // NOLINT(misc-non-private-member-variables-in-classes) }; Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path, std::ostream& out_error, bool assert_overlay = true); Result<std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, ResourceId resid); } // namespace android::idmap2::utils Loading cmds/idmap2/libidmap2/Idmap.cpp +20 −8 Original line number Diff line number Diff line Loading @@ -274,17 +274,24 @@ std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream, return std::move(idmap); } bool CheckOverlayable(const LoadedPackage& target_package, PolicyBitmask fulfilled_polices, ResourceId resid) { const OverlayableInfo* info = target_package.GetOverlayableInfo(resid); if (info == nullptr) { bool CheckOverlayable(const LoadedPackage& target_package, const utils::OverlayManifestInfo& overlay_info, const PolicyBitmask& fulfilled_polices, const ResourceId& resid) { 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 true; } if (!overlay_info.target_name.empty() && 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; } // Enforce policy restrictions if the resource is declared as overlayable. return (info->policy_flags & fulfilled_polices) != 0; return (overlayable_info->policy_flags & fulfilled_polices) != 0; } std::unique_ptr<const Idmap> Idmap::FromApkAssets( Loading Loading @@ -339,6 +346,12 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( return nullptr; } Result<utils::OverlayManifestInfo> overlay_info = utils::ExtractOverlayManifestInfo(overlay_apk_path, out_error); if (!overlay_info) { return nullptr; } std::unique_ptr<IdmapHeader> header(new IdmapHeader()); header->magic_ = kIdmapMagic; header->version_ = kIdmapCurrentVersion; Loading Loading @@ -393,9 +406,8 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( continue; } if (enforce_overlayable && !CheckOverlayable(*target_pkg, fulfilled_policies, target_resid)) { // The resources must be defined as overlayable and the overlay must fulfill at least one // policy enforced on the overlayable resource if (enforce_overlayable && !CheckOverlayable(*target_pkg, *overlay_info, fulfilled_policies, target_resid)) { LOG(WARNING) << "overlay \"" << overlay_apk_path << "\" is not allowed to overlay resource \"" << full_name << "\"" << std::endl; continue; Loading cmds/idmap2/libidmap2/ResourceUtils.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #include <memory> #include <string> #include "androidfw/StringPiece.h" Loading @@ -21,8 +22,13 @@ #include "idmap2/ResourceUtils.h" #include "idmap2/Result.h" #include "idmap2/Xml.h" #include "idmap2/ZipFile.h" using android::StringPiece16; using android::idmap2::Result; using android::idmap2::Xml; using android::idmap2::ZipFile; using android::util::Utf16ToUtf8; namespace android::idmap2::utils { Loading @@ -47,4 +53,63 @@ Result<std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, Reso return {out}; } Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path, std::ostream& out_error, bool assert_overlay) { std::unique_ptr<const ZipFile> zip = ZipFile::Open(path); if (!zip) { out_error << "error: failed to open " << path << " as a zip file" << std::endl; return kResultError; } std::unique_ptr<const MemoryChunk> entry = zip->Uncompress("AndroidManifest.xml"); if (!entry) { out_error << "error: failed to uncompress AndroidManifest.xml from " << path << std::endl; return kResultError; } std::unique_ptr<const Xml> xml = Xml::Create(entry->buf, entry->size); if (!xml) { out_error << "error: failed to parse AndroidManifest.xml from " << path << std::endl; return kResultError; } OverlayManifestInfo info{}; const auto tag = xml->FindTag("overlay"); if (!tag) { if (assert_overlay) { out_error << "error: <overlay> missing from AndroidManifest.xml of " << path << std::endl; return kResultError; } return info; } auto iter = tag->find("targetPackage"); if (iter == tag->end()) { if (assert_overlay) { out_error << "error: android:targetPackage missing from <overlay> of " << path << std::endl; return kResultError; } } else { info.target_package = iter->second; } iter = tag->find("targetName"); if (iter != tag->end()) { info.target_name = iter->second; } iter = tag->find("isStatic"); if (iter != tag->end()) { info.is_static = std::stoul(iter->second) != 0U; } iter = tag->find("priority"); if (iter != tag->end()) { info.priority = std::stoi(iter->second); } return info; } } // namespace android::idmap2::utils cmds/idmap2/tests/BinaryStreamVisitorTests.cpp +15 −12 Original line number Diff line number Diff line Loading @@ -111,43 +111,46 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) { success = LoadedIdmap::Lookup(header, 0x0002, &entry); // string/c ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0003, &entry); // string/not_overlayable success = LoadedIdmap::Lookup(header, 0x0003, &entry); // string/other ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0004, &entry); // string/policy_product success = LoadedIdmap::Lookup(header, 0x0004, &entry); // string/not_overlayable ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0005, &entry); // string/policy_public success = LoadedIdmap::Lookup(header, 0x0005, &entry); // string/policy_product ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0006, &entry); // string/policy_system success = LoadedIdmap::Lookup(header, 0x0006, &entry); // string/policy_public ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0007, &entry); // string/policy_system_vendor success = LoadedIdmap::Lookup(header, 0x0007, &entry); // string/policy_system ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0008, &entry); // string/str1 success = LoadedIdmap::Lookup(header, 0x0008, &entry); // string/policy_system_vendor ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/str1 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0000); success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/str2 success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/str2 ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/str3 success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/str3 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0001); success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/str4 success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/str4 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0002); success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/x success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/x ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/y success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/y ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/z success = LoadedIdmap::Lookup(header, 0x000f, &entry); // string/z ASSERT_FALSE(success); } Loading Loading
cmds/idmap2/idmap2/Scan.cpp +13 −35 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include "idmap2/CommandLineOptions.h" #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" #include "idmap2/ResourceUtils.h" #include "idmap2/Xml.h" #include "idmap2/ZipFile.h" Loading @@ -36,14 +37,13 @@ using android::idmap2::CommandLineOptions; using android::idmap2::Idmap; using android::idmap2::MemoryChunk; using android::idmap2::PoliciesToBitmask; using android::idmap2::PolicyBitmask; using android::idmap2::PolicyFlags; using android::idmap2::Result; using android::idmap2::Xml; using android::idmap2::ZipFile; using android::idmap2::utils::ExtractOverlayManifestInfo; using android::idmap2::utils::FindFiles; using android::idmap2::utils::OverlayManifestInfo; namespace { Loading Loading @@ -138,46 +138,23 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { std::vector<InputOverlay> interesting_apks; for (const std::string& path : *apk_paths) { std::unique_ptr<const ZipFile> zip = ZipFile::Open(path); if (!zip) { out_error << "error: failed to open " << path << " as a zip file" << std::endl; Result<OverlayManifestInfo> overlay_info = ExtractOverlayManifestInfo(path, out_error, /* assert_overlay */ false); if (!overlay_info) { return false; } std::unique_ptr<const MemoryChunk> entry = zip->Uncompress("AndroidManifest.xml"); if (!entry) { out_error << "error: failed to uncompress AndroidManifest.xml from " << path << std::endl; return false; } std::unique_ptr<const Xml> xml = Xml::Create(entry->buf, entry->size); if (!xml) { out_error << "error: failed to parse AndroidManifest.xml from " << path << std::endl; continue; } const auto tag = xml->FindTag("overlay"); if (!tag) { continue; } auto iter = tag->find("isStatic"); if (iter == tag->end() || std::stoul(iter->second) == 0U) { continue; } iter = tag->find("targetPackage"); if (iter == tag->end() || iter->second != target_package_name) { if (!overlay_info->is_static) { continue; } iter = tag->find("priority"); if (iter == tag->end()) { if (overlay_info->target_package.empty() || overlay_info->target_package != target_package_name) { continue; } const int priority = std::stoi(iter->second); if (priority < 0) { if (overlay_info->priority < 0) { continue; } Loading @@ -203,7 +180,8 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, path); // Sort the static overlays in ascending priority order InputOverlay input{path, idmap_path, priority, override_policies, ignore_overlayable}; InputOverlay input{path, idmap_path, overlay_info->priority, override_policies, ignore_overlayable}; interesting_apks.insert( std::lower_bound(interesting_apks.begin(), interesting_apks.end(), input), input); } Loading
cmds/idmap2/include/idmap2/ResourceUtils.h +14 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_ #define IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_ #include <optional> #include <ostream> #include <string> #include "android-base/macros.h" Loading @@ -24,9 +26,21 @@ #include "idmap2/Idmap.h" #include "idmap2/Result.h" #include "idmap2/ZipFile.h" namespace android::idmap2::utils { struct OverlayManifestInfo { std::string target_package; // NOLINT(misc-non-private-member-variables-in-classes) std::string target_name; // NOLINT(misc-non-private-member-variables-in-classes) bool is_static; // NOLINT(misc-non-private-member-variables-in-classes) int priority = -1; // NOLINT(misc-non-private-member-variables-in-classes) }; Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path, std::ostream& out_error, bool assert_overlay = true); Result<std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, ResourceId resid); } // namespace android::idmap2::utils Loading
cmds/idmap2/libidmap2/Idmap.cpp +20 −8 Original line number Diff line number Diff line Loading @@ -274,17 +274,24 @@ std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream, return std::move(idmap); } bool CheckOverlayable(const LoadedPackage& target_package, PolicyBitmask fulfilled_polices, ResourceId resid) { const OverlayableInfo* info = target_package.GetOverlayableInfo(resid); if (info == nullptr) { bool CheckOverlayable(const LoadedPackage& target_package, const utils::OverlayManifestInfo& overlay_info, const PolicyBitmask& fulfilled_polices, const ResourceId& resid) { 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 true; } if (!overlay_info.target_name.empty() && 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; } // Enforce policy restrictions if the resource is declared as overlayable. return (info->policy_flags & fulfilled_polices) != 0; return (overlayable_info->policy_flags & fulfilled_polices) != 0; } std::unique_ptr<const Idmap> Idmap::FromApkAssets( Loading Loading @@ -339,6 +346,12 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( return nullptr; } Result<utils::OverlayManifestInfo> overlay_info = utils::ExtractOverlayManifestInfo(overlay_apk_path, out_error); if (!overlay_info) { return nullptr; } std::unique_ptr<IdmapHeader> header(new IdmapHeader()); header->magic_ = kIdmapMagic; header->version_ = kIdmapCurrentVersion; Loading Loading @@ -393,9 +406,8 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( continue; } if (enforce_overlayable && !CheckOverlayable(*target_pkg, fulfilled_policies, target_resid)) { // The resources must be defined as overlayable and the overlay must fulfill at least one // policy enforced on the overlayable resource if (enforce_overlayable && !CheckOverlayable(*target_pkg, *overlay_info, fulfilled_policies, target_resid)) { LOG(WARNING) << "overlay \"" << overlay_apk_path << "\" is not allowed to overlay resource \"" << full_name << "\"" << std::endl; continue; Loading
cmds/idmap2/libidmap2/ResourceUtils.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #include <memory> #include <string> #include "androidfw/StringPiece.h" Loading @@ -21,8 +22,13 @@ #include "idmap2/ResourceUtils.h" #include "idmap2/Result.h" #include "idmap2/Xml.h" #include "idmap2/ZipFile.h" using android::StringPiece16; using android::idmap2::Result; using android::idmap2::Xml; using android::idmap2::ZipFile; using android::util::Utf16ToUtf8; namespace android::idmap2::utils { Loading @@ -47,4 +53,63 @@ Result<std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, Reso return {out}; } Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path, std::ostream& out_error, bool assert_overlay) { std::unique_ptr<const ZipFile> zip = ZipFile::Open(path); if (!zip) { out_error << "error: failed to open " << path << " as a zip file" << std::endl; return kResultError; } std::unique_ptr<const MemoryChunk> entry = zip->Uncompress("AndroidManifest.xml"); if (!entry) { out_error << "error: failed to uncompress AndroidManifest.xml from " << path << std::endl; return kResultError; } std::unique_ptr<const Xml> xml = Xml::Create(entry->buf, entry->size); if (!xml) { out_error << "error: failed to parse AndroidManifest.xml from " << path << std::endl; return kResultError; } OverlayManifestInfo info{}; const auto tag = xml->FindTag("overlay"); if (!tag) { if (assert_overlay) { out_error << "error: <overlay> missing from AndroidManifest.xml of " << path << std::endl; return kResultError; } return info; } auto iter = tag->find("targetPackage"); if (iter == tag->end()) { if (assert_overlay) { out_error << "error: android:targetPackage missing from <overlay> of " << path << std::endl; return kResultError; } } else { info.target_package = iter->second; } iter = tag->find("targetName"); if (iter != tag->end()) { info.target_name = iter->second; } iter = tag->find("isStatic"); if (iter != tag->end()) { info.is_static = std::stoul(iter->second) != 0U; } iter = tag->find("priority"); if (iter != tag->end()) { info.priority = std::stoi(iter->second); } return info; } } // namespace android::idmap2::utils
cmds/idmap2/tests/BinaryStreamVisitorTests.cpp +15 −12 Original line number Diff line number Diff line Loading @@ -111,43 +111,46 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) { success = LoadedIdmap::Lookup(header, 0x0002, &entry); // string/c ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0003, &entry); // string/not_overlayable success = LoadedIdmap::Lookup(header, 0x0003, &entry); // string/other ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0004, &entry); // string/policy_product success = LoadedIdmap::Lookup(header, 0x0004, &entry); // string/not_overlayable ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0005, &entry); // string/policy_public success = LoadedIdmap::Lookup(header, 0x0005, &entry); // string/policy_product ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0006, &entry); // string/policy_system success = LoadedIdmap::Lookup(header, 0x0006, &entry); // string/policy_public ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0007, &entry); // string/policy_system_vendor success = LoadedIdmap::Lookup(header, 0x0007, &entry); // string/policy_system ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0008, &entry); // string/str1 success = LoadedIdmap::Lookup(header, 0x0008, &entry); // string/policy_system_vendor ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/str1 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0000); success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/str2 success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/str2 ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/str3 success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/str3 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0001); success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/str4 success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/str4 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0002); success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/x success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/x ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/y success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/y ASSERT_FALSE(success); success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/z success = LoadedIdmap::Lookup(header, 0x000f, &entry); // string/z ASSERT_FALSE(success); } Loading