diff options
author | Ryan Mitchell <rtmitchell@google.com> | 2020-12-14 20:42:03 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-12-14 20:42:03 +0000 |
commit | 314863c132479b108f0ce61a5a753123cd3a15ca (patch) | |
tree | 8c2c62e7f5964b3ed503f1f2c753d0850ac70dec /cmds | |
parent | 2991744d472491889d9ba465c8f96c1022af5df0 (diff) | |
parent | a45506e6f6619f59ce1ae94b20ad377b86966be0 (diff) |
Merge changes from topic "inc-hard-am"
* changes:
Revert^2 "Cache resolved theme values"
Set resource id correctly when resolve fails
Revert^2 "libandroidfw hardening for IncFs"
idmap2: remove call to obsolete 'idmap2 verify' from valgrind.sh
idmap2: remove the 'scan' command
Diffstat (limited to 'cmds')
-rw-r--r-- | cmds/idmap2/Android.bp | 1 | ||||
-rw-r--r-- | cmds/idmap2/idmap2/Commands.h | 1 | ||||
-rw-r--r-- | cmds/idmap2/idmap2/Lookup.cpp | 71 | ||||
-rw-r--r-- | cmds/idmap2/idmap2/Main.cpp | 6 | ||||
-rw-r--r-- | cmds/idmap2/idmap2/Scan.cpp | 257 | ||||
-rw-r--r-- | cmds/idmap2/include/idmap2/FileUtils.h | 14 | ||||
-rw-r--r-- | cmds/idmap2/include/idmap2/ResourceMapping.h | 3 | ||||
-rw-r--r-- | cmds/idmap2/libidmap2/FileUtils.cpp | 60 | ||||
-rw-r--r-- | cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp | 5 | ||||
-rw-r--r-- | cmds/idmap2/libidmap2/ResourceMapping.cpp | 54 | ||||
-rw-r--r-- | cmds/idmap2/libidmap2/ResourceUtils.cpp | 16 | ||||
-rw-r--r-- | cmds/idmap2/libidmap2/XmlParser.cpp | 11 | ||||
-rw-r--r-- | cmds/idmap2/tests/FileUtilsTests.cpp | 57 | ||||
-rw-r--r-- | cmds/idmap2/tests/Idmap2BinaryTests.cpp | 125 | ||||
-rwxr-xr-x | cmds/idmap2/valgrind.sh | 2 |
15 files changed, 73 insertions, 610 deletions
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp index 878cef94b674..e21a6b288fb3 100644 --- a/cmds/idmap2/Android.bp +++ b/cmds/idmap2/Android.bp @@ -181,7 +181,6 @@ cc_binary { "idmap2/Dump.cpp", "idmap2/Lookup.cpp", "idmap2/Main.cpp", - "idmap2/Scan.cpp", ], target: { android: { diff --git a/cmds/idmap2/idmap2/Commands.h b/cmds/idmap2/idmap2/Commands.h index 69eea8d262d2..4099671066a2 100644 --- a/cmds/idmap2/idmap2/Commands.h +++ b/cmds/idmap2/idmap2/Commands.h @@ -26,6 +26,5 @@ android::idmap2::Result<android::idmap2::Unit> Create(const std::vector<std::str android::idmap2::Result<android::idmap2::Unit> CreateMultiple(const std::vector<std::string>& args); android::idmap2::Result<android::idmap2::Unit> Dump(const std::vector<std::string>& args); android::idmap2::Result<android::idmap2::Unit> Lookup(const std::vector<std::string>& args); -android::idmap2::Result<android::idmap2::Unit> Scan(const std::vector<std::string>& args); #endif // IDMAP2_IDMAP2_COMMANDS_H_ diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp index c44170928992..8323d0ba2415 100644 --- a/cmds/idmap2/idmap2/Lookup.cpp +++ b/cmds/idmap2/idmap2/Lookup.cpp @@ -45,11 +45,8 @@ using android::ApkAssets; using android::ApkAssetsCookie; using android::AssetManager2; using android::ConfigDescription; -using android::is_valid_resid; -using android::kInvalidCookie; using android::Res_value; using android::ResStringPool; -using android::ResTable_config; using android::StringPiece16; using android::base::StringPrintf; using android::idmap2::CommandLineOptions; @@ -59,7 +56,6 @@ using android::idmap2::ResourceId; using android::idmap2::Result; using android::idmap2::Unit; using android::idmap2::utils::ExtractOverlayManifestInfo; -using android::util::Utf16ToUtf8; namespace { @@ -69,25 +65,23 @@ Result<ResourceId> WARN_UNUSED ParseResReference(const AssetManager2& am, const // first, try to parse as a hex number char* endptr = nullptr; - ResourceId resid; - resid = strtol(res.c_str(), &endptr, kBaseHex); + const ResourceId parsed_resid = strtol(res.c_str(), &endptr, kBaseHex); if (*endptr == '\0') { - return resid; + return parsed_resid; } // next, try to parse as a package:type/name string - resid = am.GetResourceId(res, "", fallback_package); - if (is_valid_resid(resid)) { - return resid; + if (auto resid = am.GetResourceId(res, "", fallback_package)) { + return *resid; } // end of the road: res could not be parsed return Error("failed to obtain resource id for %s", res.c_str()); } -void PrintValue(AssetManager2* const am, const Res_value& value, const ApkAssetsCookie& cookie, +void PrintValue(AssetManager2* const am, const AssetManager2::SelectedValue& value, std::string* const out) { - switch (value.dataType) { + switch (value.type) { case Res_value::TYPE_INT_DEC: out->append(StringPrintf("%d", value.data)); break; @@ -98,30 +92,21 @@ void PrintValue(AssetManager2* const am, const Res_value& value, const ApkAssets out->append(value.data != 0 ? "true" : "false"); break; case Res_value::TYPE_STRING: { - const ResStringPool* pool = am->GetStringPoolForCookie(cookie); + const ResStringPool* pool = am->GetStringPoolForCookie(value.cookie); out->append("\""); - size_t len; - if (pool->isUTF8()) { - const char* str = pool->string8At(value.data, &len); - out->append(str, len); - } else { - const char16_t* str16 = pool->stringAt(value.data, &len); - out->append(Utf16ToUtf8(StringPiece16(str16, len))); + if (auto str = pool->string8ObjectAt(value.data)) { + out->append(*str); } - out->append("\""); } break; default: - out->append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data)); + out->append(StringPrintf("dataType=0x%02x data=0x%08x", value.type, value.data)); break; } } Result<std::string> WARN_UNUSED GetValue(AssetManager2* const am, ResourceId resid) { - Res_value value; - ResTable_config config; - uint32_t flags; - ApkAssetsCookie cookie = am->GetResource(resid, true, 0, &value, &config, &flags); - if (cookie == kInvalidCookie) { + auto value = am->GetResource(resid); + if (!value.has_value()) { return Error("no resource 0x%08x in asset manager", resid); } @@ -129,41 +114,35 @@ Result<std::string> WARN_UNUSED GetValue(AssetManager2* const am, ResourceId res // TODO(martenkongstad): use optional parameter GetResource(..., std::string* // stacktrace = NULL) instead - out.append(StringPrintf("cookie=%d ", cookie)); + out.append(StringPrintf("cookie=%d ", value->cookie)); out.append("config='"); - out.append(config.toString().c_str()); + out.append(value->config.toString().c_str()); out.append("' value="); - if (value.dataType == Res_value::TYPE_REFERENCE) { - const android::ResolvedBag* bag = am->GetBag(static_cast<uint32_t>(value.data)); - if (bag == nullptr) { - out.append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data)); + if (value->type == Res_value::TYPE_REFERENCE) { + auto bag_result = am->GetBag(static_cast<uint32_t>(value->data)); + if (!bag_result.has_value()) { + out.append(StringPrintf("dataType=0x%02x data=0x%08x", value->type, value->data)); return out; } + out.append("["); - Res_value bag_val; - ResTable_config selected_config; - uint32_t flags; - uint32_t ref; - ApkAssetsCookie bag_cookie; + const android::ResolvedBag* bag = bag_result.value(); for (size_t i = 0; i < bag->entry_count; ++i) { - const android::ResolvedBag::Entry& entry = bag->entries[i]; - bag_val = entry.value; - bag_cookie = am->ResolveReference(entry.cookie, &bag_val, &selected_config, &flags, &ref); - if (bag_cookie == kInvalidCookie) { - out.append( - StringPrintf("Error: dataType=0x%02x data=0x%08x", bag_val.dataType, bag_val.data)); + AssetManager2::SelectedValue entry(bag, bag->entries[i]); + if (am->ResolveReference(entry).has_value()) { + out.append(StringPrintf("Error: dataType=0x%02x data=0x%08x", entry.type, entry.data)); continue; } - PrintValue(am, bag_val, bag_cookie, &out); + PrintValue(am, entry, &out); if (i != bag->entry_count - 1) { out.append(", "); } } out.append("]"); } else { - PrintValue(am, value, cookie, &out); + PrintValue(am, *value, &out); } return out; diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp index fb093f0f22a4..aa6d0e76698f 100644 --- a/cmds/idmap2/idmap2/Main.cpp +++ b/cmds/idmap2/idmap2/Main.cpp @@ -53,8 +53,10 @@ void PrintUsage(const NameToFunctionMap& commands, std::ostream& out) { int main(int argc, char** argv) { SYSTRACE << "main"; const NameToFunctionMap commands = { - {"create", Create}, {"create-multiple", CreateMultiple}, {"dump", Dump}, {"lookup", Lookup}, - {"scan", Scan}, + {"create", Create}, + {"create-multiple", CreateMultiple}, + {"dump", Dump}, + {"lookup", Lookup}, }; if (argc <= 1) { PrintUsage(commands, std::cerr); diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp deleted file mode 100644 index 36250450cc74..000000000000 --- a/cmds/idmap2/idmap2/Scan.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <dirent.h> - -#include <fstream> -#include <memory> -#include <ostream> -#include <set> -#include <string> -#include <utility> -#include <vector> - -#include "Commands.h" -#include "android-base/properties.h" -#include "idmap2/CommandLineOptions.h" -#include "idmap2/CommandUtils.h" -#include "idmap2/FileUtils.h" -#include "idmap2/Idmap.h" -#include "idmap2/Policies.h" -#include "idmap2/PolicyUtils.h" -#include "idmap2/ResourceUtils.h" -#include "idmap2/Result.h" -#include "idmap2/SysTrace.h" -#include "idmap2/XmlParser.h" - -using android::idmap2::CommandLineOptions; -using android::idmap2::Error; -using android::idmap2::Idmap; -using android::idmap2::Result; -using android::idmap2::Unit; -using android::idmap2::policy::kPolicyOdm; -using android::idmap2::policy::kPolicyOem; -using android::idmap2::policy::kPolicyProduct; -using android::idmap2::policy::kPolicyPublic; -using android::idmap2::policy::kPolicySystem; -using android::idmap2::policy::kPolicyVendor; -using android::idmap2::utils::ExtractOverlayManifestInfo; -using android::idmap2::utils::FindFiles; -using android::idmap2::utils::OverlayManifestInfo; -using android::idmap2::utils::PoliciesToBitmaskResult; - -using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; - -namespace { - -struct InputOverlay { - bool operator<(InputOverlay const& rhs) const { - return priority < rhs.priority || (priority == rhs.priority && apk_path < rhs.apk_path); - } - - std::string apk_path; // NOLINT(misc-non-private-member-variables-in-classes) - std::string idmap_path; // NOLINT(misc-non-private-member-variables-in-classes) - int priority; // NOLINT(misc-non-private-member-variables-in-classes) - std::vector<std::string> policies; // NOLINT(misc-non-private-member-variables-in-classes) - bool ignore_overlayable; // NOLINT(misc-non-private-member-variables-in-classes) -}; - -bool VendorIsQOrLater() { - constexpr int kQSdkVersion = 29; - constexpr int kBase = 10; - std::string version_prop = android::base::GetProperty("ro.vndk.version", "29"); - int version = strtol(version_prop.data(), nullptr, kBase); - - // If the string cannot be parsed, it is a development sdk codename. - return version >= kQSdkVersion || version == 0; -} - -Result<std::unique_ptr<std::vector<std::string>>> FindApkFiles(const std::vector<std::string>& dirs, - bool recursive) { - SYSTRACE << "FindApkFiles " << dirs << " " << recursive; - const auto predicate = [](unsigned char type, const std::string& path) -> bool { - static constexpr size_t kExtLen = 4; // strlen(".apk") - return type == DT_REG && path.size() > kExtLen && - path.compare(path.size() - kExtLen, kExtLen, ".apk") == 0; - }; - // pass apk paths through a set to filter out duplicates - std::set<std::string> paths; - for (const auto& dir : dirs) { - const auto apk_paths = FindFiles(dir, recursive, predicate); - if (!apk_paths) { - return Error("failed to open directory %s", dir.c_str()); - } - paths.insert(apk_paths->cbegin(), apk_paths->cend()); - } - return std::make_unique<std::vector<std::string>>(paths.cbegin(), paths.cend()); -} - -std::vector<std::string> PoliciesForPath(const std::string& apk_path) { - // clang-format off - static const std::vector<std::pair<std::string, std::string>> values = { - {"/odm/", kPolicyOdm}, - {"/oem/", kPolicyOem}, - {"/product/", kPolicyProduct}, - {"/system/", kPolicySystem}, - {"/system_ext/", kPolicySystem}, - {"/vendor/", kPolicyVendor}, - }; - // clang-format on - - std::vector<std::string> fulfilled_policies = {kPolicyPublic}; - for (auto const& pair : values) { - if (apk_path.compare(0, pair.first.size(), pair.first) == 0) { - fulfilled_policies.emplace_back(pair.second); - break; - } - } - - return fulfilled_policies; -} - -} // namespace - -Result<Unit> Scan(const std::vector<std::string>& args) { - SYSTRACE << "Scan " << args; - std::vector<std::string> input_directories; - std::string target_package_name; - std::string target_apk_path; - std::string output_directory; - std::vector<std::string> override_policies; - bool recursive = false; - - const CommandLineOptions opts = - CommandLineOptions("idmap2 scan") - .MandatoryOption("--input-directory", "directory containing overlay apks to scan", - &input_directories) - .OptionalFlag("--recursive", "also scan subfolders of overlay-directory", &recursive) - .MandatoryOption("--target-package-name", "package name of target package", - &target_package_name) - .MandatoryOption("--target-apk-path", "path to target apk", &target_apk_path) - .MandatoryOption("--output-directory", - "directory in which to write artifacts (idmap files and overlays.list)", - &output_directory) - .OptionalOption( - "--override-policy", - "input: an overlayable policy this overlay fulfills " - "(if none or supplied, the overlays will not have their policies overriden", - &override_policies); - const auto opts_ok = opts.Parse(args); - if (!opts_ok) { - return opts_ok.GetError(); - } - - const auto apk_paths = FindApkFiles(input_directories, recursive); - if (!apk_paths) { - return Error(apk_paths.GetError(), "failed to find apk files"); - } - - std::vector<InputOverlay> interesting_apks; - for (const std::string& path : **apk_paths) { - Result<OverlayManifestInfo> overlay_info = - ExtractOverlayManifestInfo(path, /* assert_overlay */ false); - if (!overlay_info) { - return overlay_info.GetError(); - } - - if (!overlay_info->is_static) { - continue; - } - - if (overlay_info->target_package.empty() || - overlay_info->target_package != target_package_name) { - continue; - } - - if (overlay_info->priority < 0) { - continue; - } - - // Note that conditional property enablement/exclusion only applies if - // the attribute is present. In its absence, all overlays are presumed enabled. - if (!overlay_info->requiredSystemPropertyName.empty() && - !overlay_info->requiredSystemPropertyValue.empty()) { - // if property set & equal to value, then include overlay - otherwise skip - if (android::base::GetProperty(overlay_info->requiredSystemPropertyName, "") != - overlay_info->requiredSystemPropertyValue) { - continue; - } - } - - std::vector<std::string> fulfilled_policies; - if (!override_policies.empty()) { - fulfilled_policies = override_policies; - } else { - fulfilled_policies = PoliciesForPath(path); - } - - bool ignore_overlayable = false; - 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. - ignore_overlayable = true; - } - - 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, fulfilled_policies, - ignore_overlayable}; - interesting_apks.insert( - std::lower_bound(interesting_apks.begin(), interesting_apks.end(), input), input); - } - - std::stringstream stream; - for (const auto& overlay : interesting_apks) { - const auto policy_bitmask = PoliciesToBitmaskResult(overlay.policies); - if (!policy_bitmask) { - LOG(WARNING) << "failed to create idmap for overlay apk path \"" << overlay.apk_path - << "\": " << policy_bitmask.GetErrorMessage(); - continue; - } - - if (!Verify(overlay.idmap_path, target_apk_path, overlay.apk_path, *policy_bitmask, - !overlay.ignore_overlayable)) { - std::vector<std::string> create_args = {"--target-apk-path", target_apk_path, - "--overlay-apk-path", overlay.apk_path, - "--idmap-path", overlay.idmap_path}; - if (overlay.ignore_overlayable) { - create_args.emplace_back("--ignore-overlayable"); - } - - for (const std::string& policy : overlay.policies) { - create_args.emplace_back("--policy"); - create_args.emplace_back(policy); - } - - const auto create_ok = Create(create_args); - if (!create_ok) { - LOG(WARNING) << "failed to create idmap for overlay apk path \"" << overlay.apk_path - << "\": " << create_ok.GetError().GetMessage(); - continue; - } - } - - stream << overlay.idmap_path << std::endl; - } - - std::cout << stream.str(); - - return Unit{}; -} diff --git a/cmds/idmap2/include/idmap2/FileUtils.h b/cmds/idmap2/include/idmap2/FileUtils.h index 3f03236d5e1a..c4e0e1fd8ef0 100644 --- a/cmds/idmap2/include/idmap2/FileUtils.h +++ b/cmds/idmap2/include/idmap2/FileUtils.h @@ -17,27 +17,13 @@ #ifndef IDMAP2_INCLUDE_IDMAP2_FILEUTILS_H_ #define IDMAP2_INCLUDE_IDMAP2_FILEUTILS_H_ -#include <sys/types.h> - -#include <functional> -#include <memory> #include <string> -#include <vector> namespace android::idmap2::utils { constexpr const char* kIdmapCacheDir = "/data/resource-cache"; constexpr const mode_t kIdmapFilePermissionMask = 0133; // u=rw,g=r,o=r -typedef std::function<bool(unsigned char type /* DT_* from dirent.h */, const std::string& path)> - FindFilesPredicate; -std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse, - const FindFilesPredicate& predicate); - -std::unique_ptr<std::string> ReadFile(int fd); - -std::unique_ptr<std::string> ReadFile(const std::string& path); - bool UidHasWriteAccessToPath(uid_t uid, const std::string& path); } // namespace android::idmap2::utils diff --git a/cmds/idmap2/include/idmap2/ResourceMapping.h b/cmds/idmap2/include/idmap2/ResourceMapping.h index 0a58ec43d8ff..f66916ccb78c 100644 --- a/cmds/idmap2/include/idmap2/ResourceMapping.h +++ b/cmds/idmap2/include/idmap2/ResourceMapping.h @@ -117,7 +117,8 @@ class ResourceMapping { static Result<ResourceMapping> CreateResourceMappingLegacy(const AssetManager2* target_am, const AssetManager2* overlay_am, const LoadedPackage* target_package, - const LoadedPackage* overlay_package); + const LoadedPackage* overlay_package, + LogInfo& log_info); // Removes resources that do not pass policy or overlayable checks of the target package. void FilterOverlayableResources(const AssetManager2* target_am, diff --git a/cmds/idmap2/libidmap2/FileUtils.cpp b/cmds/idmap2/libidmap2/FileUtils.cpp index 3e8e32989a09..3af1f70ebe39 100644 --- a/cmds/idmap2/libidmap2/FileUtils.cpp +++ b/cmds/idmap2/libidmap2/FileUtils.cpp @@ -16,19 +16,7 @@ #include "idmap2/FileUtils.h" -#include <dirent.h> -#include <sys/types.h> -#include <unistd.h> - -#include <cerrno> -#include <climits> -#include <cstdlib> -#include <cstring> -#include <fstream> -#include <memory> #include <string> -#include <utility> -#include <vector> #include "android-base/file.h" #include "android-base/macros.h" @@ -37,54 +25,6 @@ namespace android::idmap2::utils { -std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse, - const FindFilesPredicate& predicate) { - DIR* dir = opendir(root.c_str()); - if (dir == nullptr) { - return nullptr; - } - std::unique_ptr<std::vector<std::string>> vector(new std::vector<std::string>()); - struct dirent* dirent; - while ((dirent = readdir(dir)) != nullptr) { - const std::string path = root + "/" + dirent->d_name; - if (predicate(dirent->d_type, path)) { - vector->push_back(path); - } - if (recurse && dirent->d_type == DT_DIR && strcmp(dirent->d_name, ".") != 0 && - strcmp(dirent->d_name, "..") != 0) { - auto sub_vector = FindFiles(path, recurse, predicate); - if (!sub_vector) { - closedir(dir); - return nullptr; - } - vector->insert(vector->end(), sub_vector->begin(), sub_vector->end()); - } - } - closedir(dir); - - return vector; -} - -std::unique_ptr<std::string> ReadFile(const std::string& path) { - std::unique_ptr<std::string> str(new std::string()); - std::ifstream fin(path); - str->append({std::istreambuf_iterator<char>(fin), std::istreambuf_iterator<char>()}); - fin.close(); - return str; -} - -std::unique_ptr<std::string> ReadFile(int fd) { - static constexpr const size_t kBufSize = 1024; - - std::unique_ptr<std::string> str(new std::string()); - char buf[kBufSize]; - ssize_t r; - while ((r = read(fd, buf, sizeof(buf))) > 0) { - str->append(buf, r); - } - return r == 0 ? std::move(str) : nullptr; -} - #ifdef __ANDROID__ bool UidHasWriteAccessToPath(uid_t uid, const std::string& path) { // resolve symlinks and relative paths; the directories must exist diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp index a93202a64d31..3037a791328e 100644 --- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp +++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp @@ -100,10 +100,9 @@ void PrettyPrintVisitor::visit(const IdmapData& data) { stream_ << TAB << base::StringPrintf("0x%08x -> ", target_entry.target_id) << utils::DataTypeToString(target_entry.value.data_type); - size_t unused; if (target_entry.value.data_type == Res_value::TYPE_STRING) { - auto str = string_pool.stringAt(target_entry.value.data_value - string_pool_offset, &unused); - stream_ << " \"" << StringPiece16(str) << "\""; + auto str = string_pool.stringAt(target_entry.value.data_value - string_pool_offset); + stream_ << " \"" << str.value_or(StringPiece16(u"")) << "\""; } else { stream_ << " " << base::StringPrintf("0x%08x", target_entry.value.data_value); } diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index 31f1c16ba5a6..d777cbfa9a14 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -71,9 +71,10 @@ Result<Unit> CheckOverlayable(const LoadedPackage& target_package, if (!target_package.DefinesOverlayable()) { return (sDefaultPolicies & fulfilled_policies) != 0 ? Result<Unit>({}) - : Error("overlay must be preinstalled, signed with the same signature as the target," - " or signed with the same signature as the package referenced through" - " <overlay-config-signature>."); + : Error( + "overlay must be preinstalled, signed with the same signature as the target," + " or signed with the same signature as the package referenced through" + " <overlay-config-signature>."); } const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(target_resource); @@ -119,32 +120,25 @@ const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) { Result<std::unique_ptr<Asset>> OpenNonAssetFromResource(const ResourceId& resource_id, const AssetManager2& asset_manager) { - Res_value value{}; - ResTable_config selected_config{}; - uint32_t flags; - auto cookie = - asset_manager.GetResource(resource_id, /* may_be_bag */ false, - /* density_override */ 0U, &value, &selected_config, &flags); - if (cookie == kInvalidCookie) { + auto value = asset_manager.GetResource(resource_id); + if (!value.has_value()) { return Error("failed to find resource for id 0x%08x", resource_id); } - if (value.dataType != Res_value::TYPE_STRING) { + if (value->type != Res_value::TYPE_STRING) { return Error("resource for is 0x%08x is not a file", resource_id); } - auto string_pool = asset_manager.GetStringPoolForCookie(cookie); - size_t len; - auto file_path16 = string_pool->stringAt(value.data, &len); - if (file_path16 == nullptr) { - return Error("failed to find string for index %d", value.data); + auto string_pool = asset_manager.GetStringPoolForCookie(value->cookie); + auto file = string_pool->string8ObjectAt(value->data); + if (!file.has_value()) { + return Error("failed to find string for index %d", value->data); } // Load the overlay resource mappings from the file specified using android:resourcesMap. - auto file_path = String8(String16(file_path16)); - auto asset = asset_manager.OpenNonAsset(file_path.c_str(), Asset::AccessMode::ACCESS_BUFFER); + auto asset = asset_manager.OpenNonAsset(file->c_str(), Asset::AccessMode::ACCESS_BUFFER); if (asset == nullptr) { - return Error("file \"%s\" not found", file_path.c_str()); + return Error("file \"%s\" not found", file->c_str()); } return asset; @@ -190,16 +184,16 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage return Error(R"(<item> tag missing expected attribute "value")"); } - ResourceId target_id = + auto target_id_result = target_am->GetResourceId(*target_resource, "", target_package->GetPackageName()); - if (target_id == 0U) { + if (!target_id_result.has_value()) { log_info.Warning(LogMessage() << "failed to find resource \"" << *target_resource << "\" in target resources"); continue; } // Retrieve the compile-time resource id of the target resource. - target_id = REWRITE_PACKAGE(target_id, target_package_id); + uint32_t target_id = REWRITE_PACKAGE(*target_id_result, target_package_id); if (overlay_resource->dataType == Res_value::TYPE_STRING) { overlay_resource->data += string_pool_offset; @@ -220,7 +214,7 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage Result<ResourceMapping> ResourceMapping::CreateResourceMappingLegacy( const AssetManager2* target_am, const AssetManager2* overlay_am, - const LoadedPackage* target_package, const LoadedPackage* overlay_package) { + const LoadedPackage* target_package, const LoadedPackage* overlay_package, LogInfo& log_info) { ResourceMapping resource_mapping; const uint8_t target_package_id = target_package->GetPackageId(); const auto end = overlay_package->end(); @@ -234,13 +228,15 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMappingLegacy( // Find the resource with the same type and entry name within the target package. const std::string full_name = base::StringPrintf("%s:%s", target_package->GetPackageName().c_str(), name->c_str()); - ResourceId target_resource = target_am->GetResourceId(full_name); - if (target_resource == 0U) { + auto target_resource_result = target_am->GetResourceId(full_name); + if (!target_resource_result.has_value()) { + log_info.Warning(LogMessage() << "failed to find resource \"" << full_name + << "\" in target resources"); continue; } // Retrieve the compile-time resource id of the target resource. - target_resource = REWRITE_PACKAGE(target_resource, target_package_id); + ResourceId target_resource = REWRITE_PACKAGE(*target_resource_result, target_package_id); resource_mapping.AddMapping(target_resource, overlay_resid, false /* rewrite_overlay_reference */); } @@ -347,7 +343,9 @@ Result<ResourceMapping> ResourceMapping::FromApkAssets(const ApkAssets& target_a auto& string_pool = (*parser)->get_strings(); string_pool_data_length = string_pool.bytes(); string_pool_data.reset(new uint8_t[string_pool_data_length]); - memcpy(string_pool_data.get(), string_pool.data(), string_pool_data_length); + + // Overlays should not be incrementally installed, so calling unsafe_ptr is fine here. + memcpy(string_pool_data.get(), string_pool.data().unsafe_ptr(), string_pool_data_length); // Offset string indices by the size of the overlay resource table string pool. string_pool_offset = overlay_arsc->GetStringPool()->size(); @@ -358,7 +356,7 @@ Result<ResourceMapping> ResourceMapping::FromApkAssets(const ApkAssets& target_a // If no file is specified using android:resourcesMap, it is assumed that the overlay only // defines resources intended to override target resources of the same type and name. resource_mapping = CreateResourceMappingLegacy(&target_asset_manager, &overlay_asset_manager, - target_pkg, overlay_pkg); + target_pkg, overlay_pkg, log_info); } if (!resource_mapping) { diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp index 98d026bc70dc..e817140238ae 100644 --- a/cmds/idmap2/libidmap2/ResourceUtils.cpp +++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp @@ -72,21 +72,21 @@ StringPiece DataTypeToString(uint8_t data_type) { } Result<std::string> ResToTypeEntryName(const AssetManager2& am, uint32_t resid) { - AssetManager2::ResourceName name; - if (!am.GetResourceName(resid, &name)) { + const auto name = am.GetResourceName(resid); + if (!name.has_value()) { return Error("no resource 0x%08x in asset manager", resid); } std::string out; - if (name.type != nullptr) { - out.append(name.type, name.type_len); + if (name->type != nullptr) { + out.append(name->type, name->type_len); } else { - out += Utf16ToUtf8(StringPiece16(name.type16, name.type_len)); + out += Utf16ToUtf8(StringPiece16(name->type16, name->type_len)); } out.append("/"); - if (name.entry != nullptr) { - out.append(name.entry, name.entry_len); + if (name->entry != nullptr) { + out.append(name->entry, name->entry_len); } else { - out += Utf16ToUtf8(StringPiece16(name.entry16, name.entry_len)); + out += Utf16ToUtf8(StringPiece16(name->entry16, name->entry_len)); } return out; } diff --git a/cmds/idmap2/libidmap2/XmlParser.cpp b/cmds/idmap2/libidmap2/XmlParser.cpp index 526a560907aa..7c55b64566f2 100644 --- a/cmds/idmap2/libidmap2/XmlParser.cpp +++ b/cmds/idmap2/libidmap2/XmlParser.cpp @@ -98,18 +98,19 @@ Result<std::string> XmlParser::Node::GetAttributeStringValue(const std::string& switch ((*value).dataType) { case Res_value::TYPE_STRING: { - size_t len; - const String16 value16(parser_.getStrings().stringAt((*value).data, &len)); - return std::string(String8(value16).c_str()); + if (auto str = parser_.getStrings().string8ObjectAt((*value).data)) { + return std::string(str->string()); + } + break; } case Res_value::TYPE_INT_DEC: case Res_value::TYPE_INT_HEX: case Res_value::TYPE_INT_BOOLEAN: { return std::to_string((*value).data); } - default: - return Error(R"(Failed to convert attribute "%s" value to a string)", name.c_str()); } + + return Error(R"(Failed to convert attribute "%s" value to a string)", name.c_str()); } Result<Res_value> XmlParser::Node::GetAttributeValue(const std::string& name) const { diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp index 8af4037be954..5750ca1f49c5 100644 --- a/cmds/idmap2/tests/FileUtilsTests.cpp +++ b/cmds/idmap2/tests/FileUtilsTests.cpp @@ -14,73 +14,16 @@ * limitations under the License. */ -#include <dirent.h> -#include <fcntl.h> - -#include <set> #include <string> #include "TestHelpers.h" -#include "android-base/macros.h" #include "android-base/stringprintf.h" -#include "gmock/gmock.h" #include "gtest/gtest.h" #include "idmap2/FileUtils.h" #include "private/android_filesystem_config.h" -using ::testing::NotNull; - namespace android::idmap2::utils { -TEST(FileUtilsTests, FindFilesFindEverythingNonRecursive) { - const auto& root = GetTestDataPath(); - auto v = utils::FindFiles(root, false, - [](unsigned char type ATTRIBUTE_UNUSED, - const std::string& path ATTRIBUTE_UNUSED) -> bool { return true; }); - ASSERT_THAT(v, NotNull()); - ASSERT_EQ(v->size(), 7U); - ASSERT_EQ(std::set<std::string>(v->begin(), v->end()), std::set<std::string>({ - root + "/.", - root + "/..", - root + "/overlay", - root + "/target", - root + "/signature-overlay", - root + "/system-overlay", - root + "/system-overlay-invalid", - })); -} - -TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) { - const auto& root = GetTestDataPath(); - auto v = utils::FindFiles(root, true, [](unsigned char type, const std::string& path) -> bool { - return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0; - }); - ASSERT_THAT(v, NotNull()); - ASSERT_EQ(v->size(), 11U); - 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-shared.apk", - root + "/overlay/overlay-static-1.apk", root + "/overlay/overlay-static-2.apk", - root + "/signature-overlay/signature-overlay.apk", - root + "/system-overlay/system-overlay.apk", - root + "/system-overlay-invalid/system-overlay-invalid.apk"})); -} - -TEST(FileUtilsTests, ReadFile) { - int pipefd[2]; - ASSERT_EQ(pipe2(pipefd, O_CLOEXEC), 0); - - ASSERT_EQ(write(pipefd[1], "foobar", 6), 6); - close(pipefd[1]); - - auto data = ReadFile(pipefd[0]); - ASSERT_THAT(data, NotNull()); - ASSERT_EQ(*data, "foobar"); - close(pipefd[0]); -} - #ifdef __ANDROID__ TEST(FileUtilsTests, UidHasWriteAccessToPath) { constexpr const char* tmp_path = "/data/local/tmp/test@idmap"; diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp index eba102da0763..e7e9e4cf5091 100644 --- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp +++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp @@ -159,131 +159,6 @@ TEST_F(Idmap2BinaryTests, Dump) { unlink(GetIdmapPath().c_str()); } -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 = - Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_2_apk_path); - - // single input directory, recursive - // clang-format off - auto result = ExecuteBinary({"idmap2", - "scan", - "--input-directory", GetTestDataPath(), - "--recursive", - "--target-package-name", "test.target", - "--target-apk-path", GetTargetApkPath(), - "--output-directory", GetTempDirPath(), - "--override-policy", "public"}); - // clang-format on - 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()); - - 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); - ASSERT_TRUE(idmap_static_no_name); - 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); - ASSERT_TRUE(idmap_static_1); - ASSERT_IDMAP(**idmap_static_1, GetTargetApkPath(), overlay_static_1_apk_path); - - auto idmap_static_2_raw_string = utils::ReadFile(idmap_static_2_path); - auto idmap_static_2_raw_stream = std::istringstream(*idmap_static_2_raw_string); - auto idmap_static_2 = Idmap::FromBinaryStream(idmap_static_2_raw_stream); - ASSERT_TRUE(idmap_static_2); - 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()); - - // multiple input directories, non-recursive - // clang-format off - result = ExecuteBinary({"idmap2", - "scan", - "--input-directory", GetTestDataPath() + "/target", - "--input-directory", GetTestDataPath() + "/overlay", - "--target-package-name", "test.target", - "--target-apk-path", GetTargetApkPath(), - "--output-directory", GetTempDirPath(), - "--override-policy", "public"}); - // clang-format on - 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()); - - // the same input directory given twice, but no duplicate entries - // clang-format off - result = ExecuteBinary({"idmap2", - "scan", - "--input-directory", GetTestDataPath(), - "--input-directory", GetTestDataPath(), - "--recursive", - "--target-package-name", "test.target", - "--target-apk-path", GetTargetApkPath(), - "--output-directory", GetTempDirPath(), - "--override-policy", "public"}); - // clang-format on - 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()); - - // no APKs in input-directory: ok, but no output - // clang-format off - result = ExecuteBinary({"idmap2", - "scan", - "--input-directory", GetTempDirPath(), - "--target-package-name", "test.target", - "--target-apk-path", GetTargetApkPath(), - "--output-directory", GetTempDirPath(), - "--override-policy", "public"}); - // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; - ASSERT_EQ(result->stdout, ""); - - // the signature idmap failing to generate should not cause scanning to fail - // clang-format off - result = ExecuteBinary({"idmap2", - "scan", - "--input-directory", GetTestDataPath(), - "--recursive", - "--target-package-name", "test.target", - "--target-apk-path", GetTargetApkPath(), - "--output-directory", GetTempDirPath(), - "--override-policy", "public"}); - // clang-format on - 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()); -} - TEST_F(Idmap2BinaryTests, Lookup) { SKIP_TEST_IF_CANT_EXEC_IDMAP2; diff --git a/cmds/idmap2/valgrind.sh b/cmds/idmap2/valgrind.sh index b4ebab0c7ffe..84daeecdb21e 100755 --- a/cmds/idmap2/valgrind.sh +++ b/cmds/idmap2/valgrind.sh @@ -53,7 +53,5 @@ valgrind="valgrind --error-exitcode=1 -q --track-origins=yes --leak-check=full" _eval "idmap2 create" "$valgrind idmap2 create --policy public --target-apk-path $target_path --overlay-apk-path $overlay_path --idmap-path $idmap_path" _eval "idmap2 dump" "$valgrind idmap2 dump --idmap-path $idmap_path" _eval "idmap2 lookup" "$valgrind idmap2 lookup --idmap-path $idmap_path --config '' --resid test.target:string/str1" -_eval "idmap2 scan" "$valgrind idmap2 scan --input-directory ${prefix}/tests/data/overlay --recursive --target-package-name test.target --target-apk-path $target_path --output-directory /tmp --override-policy public" -_eval "idmap2 verify" "$valgrind idmap2 verify --idmap-path $idmap_path" _eval "idmap2_tests" "$valgrind $ANDROID_HOST_OUT/nativetest64/idmap2_tests/idmap2_tests" exit $errors |