diff options
author | Xin Li <delphij@google.com> | 2020-09-10 17:22:01 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-09-10 17:22:01 +0000 |
commit | 8ac6741e47c76bde065f868ea64d2f04541487b9 (patch) | |
tree | 1a679458fdbd8d370692d56791e2bf83acee35b5 /cmds/idmap2/idmap2d/Idmap2Service.cpp | |
parent | 3de940cc40b1e3fdf8224e18a8308a16768cbfa8 (diff) | |
parent | c64112eb974e9aa7638aead998f07a868acfb5a7 (diff) |
Merge "Merge Android R"
Diffstat (limited to 'cmds/idmap2/idmap2d/Idmap2Service.cpp')
-rw-r--r-- | cmds/idmap2/idmap2d/Idmap2Service.cpp | 81 |
1 files changed, 70 insertions, 11 deletions
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index d7237763a2e5..15e22a3410cf 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -33,22 +33,29 @@ #include "idmap2/BinaryStreamVisitor.h" #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" -#include "idmap2/Policies.h" +#include "idmap2/Result.h" #include "idmap2/SysTrace.h" +#include "idmap2/ZipFile.h" #include "utils/String8.h" using android::IPCThreadState; +using android::base::StringPrintf; using android::binder::Status; using android::idmap2::BinaryStreamVisitor; +using android::idmap2::GetPackageCrc; using android::idmap2::Idmap; using android::idmap2::IdmapHeader; -using android::idmap2::PolicyBitmask; +using android::idmap2::ZipFile; using android::idmap2::utils::kIdmapCacheDir; using android::idmap2::utils::kIdmapFilePermissionMask; using android::idmap2::utils::UidHasWriteAccessToPath; +using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; + namespace { +constexpr const char* kFrameworkPath = "/system/framework/framework-res.apk"; + Status ok() { return Status::ok(); } @@ -62,6 +69,21 @@ PolicyBitmask ConvertAidlArgToPolicyBitmask(int32_t arg) { return static_cast<PolicyBitmask>(arg); } +Status GetCrc(const std::string& apk_path, uint32_t* out_crc) { + const auto zip = ZipFile::Open(apk_path); + if (!zip) { + return error(StringPrintf("failed to open apk %s", apk_path.c_str())); + } + + const auto crc = GetPackageCrc(*zip); + if (!crc) { + return error(crc.GetErrorMessage()); + } + + *out_crc = *crc; + return ok(); +} + } // namespace namespace android::os { @@ -93,21 +115,52 @@ Status Idmap2Service::removeIdmap(const std::string& overlay_apk_path, return ok(); } -Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path, - int32_t fulfilled_policies ATTRIBUTE_UNUSED, - bool enforce_overlayable ATTRIBUTE_UNUSED, - int32_t user_id ATTRIBUTE_UNUSED, bool* _aidl_return) { +Status Idmap2Service::verifyIdmap(const std::string& target_apk_path, + const std::string& overlay_apk_path, int32_t fulfilled_policies, + bool enforce_overlayable, int32_t user_id ATTRIBUTE_UNUSED, + bool* _aidl_return) { SYSTRACE << "Idmap2Service::verifyIdmap " << overlay_apk_path; assert(_aidl_return); + const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path); std::ifstream fin(idmap_path); const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin); fin.close(); - *_aidl_return = header && header->IsUpToDate(); + if (!header) { + *_aidl_return = false; + return error("failed to parse idmap header"); + } - // TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed + uint32_t target_crc; + if (target_apk_path == kFrameworkPath && android_crc_) { + target_crc = *android_crc_; + } else { + auto target_crc_status = GetCrc(target_apk_path, &target_crc); + if (!target_crc_status.isOk()) { + *_aidl_return = false; + return target_crc_status; + } + + // Loading the framework zip can take several milliseconds. Cache the crc of the framework + // resource APK to reduce repeated work during boot. + if (target_apk_path == kFrameworkPath) { + android_crc_ = target_crc; + } + } - return ok(); + uint32_t overlay_crc; + auto overlay_crc_status = GetCrc(overlay_apk_path, &overlay_crc); + if (!overlay_crc_status.isOk()) { + *_aidl_return = false; + return overlay_crc_status; + } + + auto up_to_date = + header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), target_crc, overlay_crc, + ConvertAidlArgToPolicyBitmask(fulfilled_policies), enforce_overlayable); + + *_aidl_return = static_cast<bool>(up_to_date); + return *_aidl_return ? ok() : error(up_to_date.GetErrorMessage()); } Status Idmap2Service::createIdmap(const std::string& target_apk_path, @@ -137,21 +190,27 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path, return error("failed to load apk " + overlay_apk_path); } - const auto idmap = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, - *overlay_apk, policy_bitmask, enforce_overlayable); + const auto idmap = + Idmap::FromApkAssets(*target_apk, *overlay_apk, policy_bitmask, enforce_overlayable); if (!idmap) { return error(idmap.GetErrorMessage()); } + // idmap files are mapped with mmap in libandroidfw. Deleting and recreating the idmap guarantees + // that existing memory maps will continue to be valid and unaffected. + unlink(idmap_path.c_str()); + umask(kIdmapFilePermissionMask); std::ofstream fout(idmap_path); if (fout.fail()) { return error("failed to open idmap path " + idmap_path); } + BinaryStreamVisitor visitor(fout); (*idmap)->accept(&visitor); fout.close(); if (fout.fail()) { + unlink(idmap_path.c_str()); return error("failed to write to idmap path " + idmap_path); } |