diff options
-rw-r--r-- | cmds/idmap2/idmap2/Scan.cpp | 43 | ||||
-rw-r--r-- | cmds/idmap2/include/idmap2/Policies.h | 12 | ||||
-rw-r--r-- | cmds/idmap2/libidmap2/Idmap.cpp | 53 | ||||
-rw-r--r-- | cmds/idmap2/libidmap2/Policies.cpp | 36 |
4 files changed, 104 insertions, 40 deletions
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp index e5f6223ef2b4..e85f132c6072 100644 --- a/cmds/idmap2/idmap2/Scan.cpp +++ b/cmds/idmap2/idmap2/Scan.cpp @@ -38,7 +38,10 @@ using android::idmap2::CommandLineOptions; using android::idmap2::Idmap; -using android::idmap2::PoliciesToBitmask; +using android::idmap2::kPolicyProduct; +using android::idmap2::kPolicyPublic; +using android::idmap2::kPolicySystem; +using android::idmap2::kPolicyVendor; using android::idmap2::PolicyBitmask; using android::idmap2::PolicyFlags; using android::idmap2::Result; @@ -87,20 +90,22 @@ std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::st return std::make_unique<std::vector<std::string>>(paths.cbegin(), paths.cend()); } -PolicyBitmask PolicyForPath(const std::string& apk_path) { - static const std::vector<std::pair<std::string, PolicyBitmask>> values = { - {"/product/", PolicyFlags::POLICY_PRODUCT_PARTITION}, - {"/system/", PolicyFlags::POLICY_SYSTEM_PARTITION}, - {"/vendor/", PolicyFlags::POLICY_VENDOR_PARTITION}, +std::vector<std::string> PoliciesForPath(const std::string& apk_path) { + static const std::vector<std::pair<std::string, std::string>> values = { + {"/product/", kPolicyProduct}, + {"/system/", kPolicySystem}, + {"/vendor/", kPolicyVendor}, }; + std::vector<std::string> fulfilled_policies = {kPolicyPublic}; for (auto const& pair : values) { if (apk_path.compare(0, pair.first.size(), pair.first) == 0) { - return pair.second | PolicyFlags::POLICY_PUBLIC; + fulfilled_policies.emplace_back(pair.second); + break; } } - return PolicyFlags::POLICY_PUBLIC; + return fulfilled_policies; } } // namespace @@ -161,21 +166,17 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { continue; } - PolicyBitmask fulfilled_policies; + std::vector<std::string> fulfilled_policies; if (!override_policies.empty()) { - auto conv_result = PoliciesToBitmask(override_policies); - if (conv_result) { - fulfilled_policies = *conv_result; - } else { - out_error << "error: " << conv_result.GetErrorMessage() << std::endl; - return false; - } + fulfilled_policies = override_policies; } else { - fulfilled_policies = PolicyForPath(path); + fulfilled_policies = PoliciesForPath(path); } bool ignore_overlayable = false; - if ((fulfilled_policies & PolicyFlags::POLICY_VENDOR_PARTITION) != 0 && !VendorIsQOrLater()) { + if (std::find(fulfilled_policies.begin(), fulfilled_policies.end(), kPolicyVendor) != + fulfilled_policies.end() && + !VendorIsQOrLater()) { // If the overlay is on a pre-Q vendor partition, do not enforce overlayable // restrictions on this overlay because the pre-Q platform has no understanding of // overlayable. @@ -185,7 +186,7 @@ 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, overlay_info->priority, override_policies, + InputOverlay input{path, idmap_path, overlay_info->priority, fulfilled_policies, ignore_overlayable}; interesting_apks.insert( std::lower_bound(interesting_apks.begin(), interesting_apks.end(), input), input); @@ -211,8 +212,8 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { } for (const std::string& policy : overlay.policies) { - verify_args.emplace_back("--policy"); - verify_args.emplace_back(policy); + create_args.emplace_back("--policy"); + create_args.emplace_back(policy); } if (!Create(create_args, out_error)) { diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/include/idmap2/Policies.h index 911d3f2cd109..cd76b84ccc0a 100644 --- a/cmds/idmap2/include/idmap2/Policies.h +++ b/cmds/idmap2/include/idmap2/Policies.h @@ -27,13 +27,21 @@ namespace android::idmap2 { +constexpr const char* kPolicyPublic = "public"; +constexpr const char* kPolicyProduct = "product"; +constexpr const char* kPolicySystem = "system"; +constexpr const char* kPolicyVendor = "vendor"; +constexpr const char* kPolicySignature = "signature"; + using PolicyFlags = ResTable_overlayable_policy_header::PolicyFlags; using PolicyBitmask = uint32_t; -// Parses a the string representation of a set of policies into a bitmask. The format of the string -// is the same as for the <policy> element. +// Parses the string representations of policies into a bitmask. Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies); +// Retrieves the string representations of policies in the bitmask. +std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask); + } // namespace android::idmap2 #endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_ diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index f4c3e9ca180f..a927a69b2585 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -284,9 +284,23 @@ std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream, return std::move(idmap); } -bool CheckOverlayable(const LoadedPackage& target_package, - const utils::OverlayManifestInfo& overlay_info, - const PolicyBitmask& fulfilled_policies, const ResourceId& resid) { +std::string ConcatPolicies(const std::vector<std::string>& policies) { + std::string message; + for (const std::string& policy : policies) { + if (message.empty()) { + message.append(policy); + } else { + message.append(policy); + message.append("|"); + } + } + + return message; +} + +Result<Unit> 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; @@ -294,23 +308,34 @@ bool CheckOverlayable(const LoadedPackage& target_package, // 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; + return (sDefaultPolicies & fulfilled_policies) != 0 + ? Result<Unit>({}) + : Error( + "overlay must be preinstalled or signed with the same signature as the " + "target"); } const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(resid); if (overlayable_info == nullptr) { // Do not allow non-overlayable resources to be overlaid. - return false; + return Error("resource has no overlayable declaration"); } 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; + return Error("<overlay> android:targetName '%s' does not match overlayable name '%s'", + overlay_info.target_name.c_str(), overlayable_info->name.c_str()); } // Enforce policy restrictions if the resource is declared as overlayable. - return (overlayable_info->policy_flags & fulfilled_policies) != 0; + if ((overlayable_info->policy_flags & fulfilled_policies) == 0) { + return Error("overlay with policies '%s' does not fulfill any overlayable policies '%s'", + ConcatPolicies(BitmaskToPolicies(fulfilled_policies)).c_str(), + ConcatPolicies(BitmaskToPolicies(overlayable_info->policy_flags)).c_str()); + } + + return Result<Unit>({}); } std::unique_ptr<const Idmap> Idmap::FromApkAssets( @@ -426,11 +451,15 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( continue; } - 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; + if (!enforce_overlayable) { + Result<Unit> success = + CheckOverlayable(*target_pkg, *overlay_info, fulfilled_policies, target_resid); + if (!success) { + LOG(WARNING) << "overlay \"" << overlay_apk_path + << "\" is not allowed to overlay resource \"" << full_name + << "\": " << success.GetErrorMessage(); + continue; + } } matching_resources.Add(target_resid, overlay_resid); diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp index c6ba87dfc2fb..7c4555633fd2 100644 --- a/cmds/idmap2/libidmap2/Policies.cpp +++ b/cmds/idmap2/libidmap2/Policies.cpp @@ -30,12 +30,13 @@ namespace android::idmap2 { namespace { const std::map<android::StringPiece, PolicyFlags> kStringToFlag = { - {"public", PolicyFlags::POLICY_PUBLIC}, - {"product", PolicyFlags::POLICY_PRODUCT_PARTITION}, - {"system", PolicyFlags::POLICY_SYSTEM_PARTITION}, - {"vendor", PolicyFlags::POLICY_VENDOR_PARTITION}, - {"signature", PolicyFlags::POLICY_SIGNATURE}, + {kPolicyPublic, PolicyFlags::POLICY_PUBLIC}, + {kPolicyProduct, PolicyFlags::POLICY_PRODUCT_PARTITION}, + {kPolicySystem, PolicyFlags::POLICY_SYSTEM_PARTITION}, + {kPolicyVendor, PolicyFlags::POLICY_VENDOR_PARTITION}, + {kPolicySignature, PolicyFlags::POLICY_SIGNATURE}, }; + } // namespace Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies) { @@ -52,4 +53,29 @@ Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies return Result<PolicyBitmask>(bitmask); } +std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask) { + std::vector<std::string> policies; + if ((bitmask & PolicyFlags::POLICY_PUBLIC) != 0) { + policies.emplace_back(kPolicyPublic); + } + + if ((bitmask & PolicyFlags::POLICY_PRODUCT_PARTITION) != 0) { + policies.emplace_back(kPolicyProduct); + } + + if ((bitmask & PolicyFlags::POLICY_SYSTEM_PARTITION) != 0) { + policies.emplace_back(kPolicySystem); + } + + if ((bitmask & PolicyFlags::POLICY_VENDOR_PARTITION) != 0) { + policies.emplace_back(kPolicyVendor); + } + + if ((bitmask & PolicyFlags::POLICY_SIGNATURE) != 0) { + policies.emplace_back(kPolicySignature); + } + + return policies; +} + } // namespace android::idmap2 |