Add policies and enforce overlayable to header
If the fulfilled policies change without the contents of the target and overlay APKs changing, the idmap for the overlay should be regenerated. This change adds fulfilled policies and enforce overlayable to the idmap header so that idmap2d can determine if the polices or enforce overlayable changed from what was used to generate the idmap. Bug: 119328308 Test: idmap2_tests Test: atest RegenerateIdmapTest Change-Id: I96f970e82b5243be01b205ac2cb6ab249c6100bc
This commit is contained in:
@@ -168,13 +168,13 @@ cc_binary {
|
||||
],
|
||||
host_supported: true,
|
||||
srcs: [
|
||||
"idmap2/CommandUtils.cpp",
|
||||
"idmap2/Create.cpp",
|
||||
"idmap2/CreateMultiple.cpp",
|
||||
"idmap2/Dump.cpp",
|
||||
"idmap2/Lookup.cpp",
|
||||
"idmap2/Main.cpp",
|
||||
"idmap2/Scan.cpp",
|
||||
"idmap2/Verify.cpp",
|
||||
],
|
||||
target: {
|
||||
android: {
|
||||
|
||||
@@ -19,30 +19,19 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "idmap2/CommandLineOptions.h"
|
||||
#include "idmap2/Idmap.h"
|
||||
#include "idmap2/Result.h"
|
||||
#include "idmap2/SysTrace.h"
|
||||
|
||||
using android::idmap2::CommandLineOptions;
|
||||
using android::idmap2::Error;
|
||||
using android::idmap2::IdmapHeader;
|
||||
using android::idmap2::Result;
|
||||
using android::idmap2::Unit;
|
||||
|
||||
Result<Unit> Verify(const std::vector<std::string>& args) {
|
||||
SYSTRACE << "Verify " << args;
|
||||
std::string idmap_path;
|
||||
|
||||
const CommandLineOptions opts =
|
||||
CommandLineOptions("idmap2 verify")
|
||||
.MandatoryOption("--idmap-path", "input: path to idmap file to verify", &idmap_path);
|
||||
|
||||
const auto opts_ok = opts.Parse(args);
|
||||
if (!opts_ok) {
|
||||
return opts_ok.GetError();
|
||||
}
|
||||
|
||||
Result<Unit> Verify(const std::string& idmap_path, const std::string& target_path,
|
||||
const std::string& overlay_path, uint32_t fulfilled_policies,
|
||||
bool enforce_overlayable) {
|
||||
SYSTRACE << "Verify " << idmap_path;
|
||||
std::ifstream fin(idmap_path);
|
||||
const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin);
|
||||
fin.close();
|
||||
@@ -50,7 +39,8 @@ Result<Unit> Verify(const std::vector<std::string>& args) {
|
||||
return Error("failed to parse idmap header");
|
||||
}
|
||||
|
||||
const auto header_ok = header->IsUpToDate();
|
||||
const auto header_ok = header->IsUpToDate(target_path.c_str(), overlay_path.c_str(),
|
||||
fulfilled_policies, enforce_overlayable);
|
||||
if (!header_ok) {
|
||||
return Error(header_ok.GetError(), "idmap not up to date");
|
||||
}
|
||||
28
cmds/idmap2/idmap2/CommandUtils.h
Normal file
28
cmds/idmap2/idmap2/CommandUtils.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef IDMAP2_IDMAP2_COMMAND_UTILS_H_
|
||||
#define IDMAP2_IDMAP2_COMMAND_UTILS_H_
|
||||
|
||||
#include "idmap2/Result.h"
|
||||
|
||||
android::idmap2::Result<android::idmap2::Unit> Verify(const std::string& idmap_path,
|
||||
const std::string& target_path,
|
||||
const std::string& overlay_path,
|
||||
uint32_t fulfilled_policies,
|
||||
bool enforce_overlayable);
|
||||
|
||||
#endif // IDMAP2_IDMAP2_COMMAND_UTILS_H_
|
||||
@@ -27,6 +27,5 @@ android::idmap2::Result<android::idmap2::Unit> CreateMultiple(const std::vector<
|
||||
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);
|
||||
android::idmap2::Result<android::idmap2::Unit> Verify(const std::vector<std::string>& args);
|
||||
|
||||
#endif // IDMAP2_IDMAP2_COMMANDS_H_
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "android-base/stringprintf.h"
|
||||
#include "idmap2/BinaryStreamVisitor.h"
|
||||
#include "idmap2/CommandLineOptions.h"
|
||||
#include "idmap2/CommandUtils.h"
|
||||
#include "idmap2/FileUtils.h"
|
||||
#include "idmap2/Idmap.h"
|
||||
#include "idmap2/Policies.h"
|
||||
@@ -103,7 +104,8 @@ Result<Unit> CreateMultiple(const std::vector<std::string>& args) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Verify(std::vector<std::string>({"--idmap-path", idmap_path}))) {
|
||||
if (!Verify(idmap_path, target_apk_path, overlay_apk_path, fulfilled_policies,
|
||||
!ignore_overlayable)) {
|
||||
const std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
|
||||
if (!overlay_apk) {
|
||||
LOG(WARNING) << "failed to load apk " << overlay_apk_path.c_str();
|
||||
|
||||
@@ -53,9 +53,8 @@ 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}, {"verify", Verify},
|
||||
{"create", Create}, {"create-multiple", CreateMultiple}, {"dump", Dump}, {"lookup", Lookup},
|
||||
{"scan", Scan},
|
||||
};
|
||||
if (argc <= 1) {
|
||||
PrintUsage(commands, std::cerr);
|
||||
|
||||
@@ -27,8 +27,11 @@
|
||||
#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"
|
||||
@@ -48,6 +51,7 @@ 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;
|
||||
|
||||
@@ -215,7 +219,15 @@ Result<Unit> Scan(const std::vector<std::string>& args) {
|
||||
|
||||
std::stringstream stream;
|
||||
for (const auto& overlay : interesting_apks) {
|
||||
if (!Verify(std::vector<std::string>({"--idmap-path", overlay.idmap_path}))) {
|
||||
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};
|
||||
|
||||
@@ -33,16 +33,19 @@
|
||||
#include "idmap2/BinaryStreamVisitor.h"
|
||||
#include "idmap2/FileUtils.h"
|
||||
#include "idmap2/Idmap.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::ZipFile;
|
||||
using android::idmap2::utils::kIdmapCacheDir;
|
||||
using android::idmap2::utils::kIdmapFilePermissionMask;
|
||||
using android::idmap2::utils::UidHasWriteAccessToPath;
|
||||
@@ -66,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 overlay_zip = ZipFile::Open(apk_path);
|
||||
if (!overlay_zip) {
|
||||
return error(StringPrintf("failed to open apk %s", apk_path.c_str()));
|
||||
}
|
||||
|
||||
const auto crc = GetPackageCrc(*overlay_zip);
|
||||
if (!crc) {
|
||||
return error(crc.GetErrorMessage());
|
||||
}
|
||||
|
||||
*out_crc = *crc;
|
||||
return ok();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace android::os {
|
||||
@@ -98,10 +116,9 @@ Status Idmap2Service::removeIdmap(const std::string& overlay_apk_path,
|
||||
}
|
||||
|
||||
Status Idmap2Service::verifyIdmap(const std::string& target_apk_path,
|
||||
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) {
|
||||
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);
|
||||
@@ -113,34 +130,38 @@ Status Idmap2Service::verifyIdmap(const std::string& target_apk_path,
|
||||
return error("failed to parse idmap header");
|
||||
}
|
||||
|
||||
if (strcmp(header->GetTargetPath().data(), target_apk_path.data()) != 0) {
|
||||
*_aidl_return = false;
|
||||
return ok();
|
||||
}
|
||||
|
||||
if (target_apk_path != kFrameworkPath) {
|
||||
*_aidl_return = (bool) header->IsUpToDate();
|
||||
uint32_t target_crc;
|
||||
if (target_apk_path == kFrameworkPath && android_crc_) {
|
||||
target_crc = *android_crc_;
|
||||
} else {
|
||||
if (!android_crc_) {
|
||||
// Loading the framework zip can take several milliseconds. Cache the crc of the framework
|
||||
// resource APK to reduce repeated work during boot.
|
||||
const auto target_zip = idmap2::ZipFile::Open(target_apk_path);
|
||||
if (!target_zip) {
|
||||
return error(base::StringPrintf("failed to open target %s", target_apk_path.c_str()));
|
||||
}
|
||||
|
||||
const auto target_crc = GetPackageCrc(*target_zip);
|
||||
if (!target_crc) {
|
||||
return error(target_crc.GetErrorMessage());
|
||||
}
|
||||
|
||||
android_crc_ = *target_crc;
|
||||
auto target_crc_status = GetCrc(target_apk_path, &target_crc);
|
||||
if (!target_crc_status.isOk()) {
|
||||
*_aidl_return = false;
|
||||
return target_crc_status;
|
||||
}
|
||||
|
||||
*_aidl_return = (bool) header->IsUpToDate(android_crc_.value());
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
fulfilled_policies, enforce_overlayable);
|
||||
if (!up_to_date) {
|
||||
*_aidl_return = false;
|
||||
return error(up_to_date.GetErrorMessage());
|
||||
}
|
||||
|
||||
// TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed
|
||||
return ok();
|
||||
}
|
||||
|
||||
|
||||
@@ -117,6 +117,14 @@ class IdmapHeader {
|
||||
return overlay_crc_;
|
||||
}
|
||||
|
||||
inline uint32_t GetFulfilledPolicies() const {
|
||||
return fulfilled_policies_;
|
||||
}
|
||||
|
||||
bool GetEnforceOverlayable() const {
|
||||
return enforce_overlayable_;
|
||||
}
|
||||
|
||||
inline StringPiece GetTargetPath() const {
|
||||
return StringPiece(target_path_);
|
||||
}
|
||||
@@ -132,8 +140,11 @@ class IdmapHeader {
|
||||
// Invariant: anytime the idmap data encoding is changed, the idmap version
|
||||
// field *must* be incremented. Because of this, we know that if the idmap
|
||||
// header is up-to-date the entire file is up-to-date.
|
||||
Result<Unit> IsUpToDate() const;
|
||||
Result<Unit> IsUpToDate(uint32_t target_crc_) const;
|
||||
Result<Unit> IsUpToDate(const char* target_path, const char* overlay_path,
|
||||
uint32_t fulfilled_policies, bool enforce_overlayable) const;
|
||||
Result<Unit> IsUpToDate(const char* target_path, const char* overlay_path, uint32_t target_crc,
|
||||
uint32_t overlay_crc, uint32_t fulfilled_policies,
|
||||
bool enforce_overlayable) const;
|
||||
|
||||
void accept(Visitor* v) const;
|
||||
|
||||
@@ -145,6 +156,8 @@ class IdmapHeader {
|
||||
uint32_t version_;
|
||||
uint32_t target_crc_;
|
||||
uint32_t overlay_crc_;
|
||||
uint32_t fulfilled_policies_;
|
||||
bool enforce_overlayable_;
|
||||
char target_path_[kIdmapStringLength];
|
||||
char overlay_path_[kIdmapStringLength];
|
||||
std::string debug_info_;
|
||||
|
||||
@@ -66,6 +66,8 @@ void BinaryStreamVisitor::visit(const IdmapHeader& header) {
|
||||
Write32(header.GetVersion());
|
||||
Write32(header.GetTargetCrc());
|
||||
Write32(header.GetOverlayCrc());
|
||||
Write32(header.GetFulfilledPolicies());
|
||||
Write8(static_cast<uint8_t>(header.GetEnforceOverlayable()));
|
||||
WriteString256(header.GetTargetPath());
|
||||
WriteString256(header.GetOverlayPath());
|
||||
WriteString(header.GetDebugInfo());
|
||||
|
||||
@@ -112,14 +112,18 @@ Result<uint32_t> GetPackageCrc(const ZipFile& zip) {
|
||||
|
||||
std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) {
|
||||
std::unique_ptr<IdmapHeader> idmap_header(new IdmapHeader());
|
||||
|
||||
uint8_t enforce_overlayable;
|
||||
if (!Read32(stream, &idmap_header->magic_) || !Read32(stream, &idmap_header->version_) ||
|
||||
!Read32(stream, &idmap_header->target_crc_) || !Read32(stream, &idmap_header->overlay_crc_) ||
|
||||
!Read32(stream, &idmap_header->fulfilled_policies_) ||
|
||||
!Read8(stream, &enforce_overlayable) ||
|
||||
!ReadString256(stream, idmap_header->target_path_) ||
|
||||
!ReadString256(stream, idmap_header->overlay_path_)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
idmap_header->enforce_overlayable_ = static_cast<bool>(enforce_overlayable);
|
||||
|
||||
auto debug_str = ReadString(stream);
|
||||
if (!debug_str) {
|
||||
return nullptr;
|
||||
@@ -129,21 +133,35 @@ std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& s
|
||||
return std::move(idmap_header);
|
||||
}
|
||||
|
||||
Result<Unit> IdmapHeader::IsUpToDate() const {
|
||||
const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_path_);
|
||||
Result<Unit> IdmapHeader::IsUpToDate(const char* target_path, const char* overlay_path,
|
||||
uint32_t fulfilled_policies, bool enforce_overlayable) const {
|
||||
const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_path);
|
||||
if (!target_zip) {
|
||||
return Error("failed to open target %s", GetTargetPath().to_string().c_str());
|
||||
return Error("failed to open target %s", target_path);
|
||||
}
|
||||
|
||||
Result<uint32_t> target_crc = GetPackageCrc(*target_zip);
|
||||
const Result<uint32_t> target_crc = GetPackageCrc(*target_zip);
|
||||
if (!target_crc) {
|
||||
return Error("failed to get target crc");
|
||||
}
|
||||
|
||||
return IsUpToDate(*target_crc);
|
||||
const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_path);
|
||||
if (!overlay_zip) {
|
||||
return Error("failed to overlay target %s", overlay_path);
|
||||
}
|
||||
|
||||
const Result<uint32_t> overlay_crc = GetPackageCrc(*overlay_zip);
|
||||
if (!overlay_crc) {
|
||||
return Error("failed to get overlay crc");
|
||||
}
|
||||
|
||||
return IsUpToDate(target_path, overlay_path, *target_crc, *overlay_crc, fulfilled_policies,
|
||||
enforce_overlayable);
|
||||
}
|
||||
|
||||
Result<Unit> IdmapHeader::IsUpToDate(uint32_t target_crc) const {
|
||||
Result<Unit> IdmapHeader::IsUpToDate(const char* target_path, const char* overlay_path,
|
||||
uint32_t target_crc, uint32_t overlay_crc,
|
||||
uint32_t fulfilled_policies, bool enforce_overlayable) const {
|
||||
if (magic_ != kIdmapMagic) {
|
||||
return Error("bad magic: actual 0x%08x, expected 0x%08x", magic_, kIdmapMagic);
|
||||
}
|
||||
@@ -157,19 +175,30 @@ Result<Unit> IdmapHeader::IsUpToDate(uint32_t target_crc) const {
|
||||
target_crc);
|
||||
}
|
||||
|
||||
const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_path_);
|
||||
if (!overlay_zip) {
|
||||
return Error("failed to open overlay %s", GetOverlayPath().to_string().c_str());
|
||||
}
|
||||
|
||||
Result<uint32_t> overlay_crc = GetPackageCrc(*overlay_zip);
|
||||
if (!overlay_crc) {
|
||||
return Error("failed to get overlay crc");
|
||||
}
|
||||
|
||||
if (overlay_crc_ != *overlay_crc) {
|
||||
if (overlay_crc_ != overlay_crc) {
|
||||
return Error("bad overlay crc: idmap version 0x%08x, file system version 0x%08x", overlay_crc_,
|
||||
*overlay_crc);
|
||||
overlay_crc);
|
||||
}
|
||||
|
||||
if (fulfilled_policies_ != fulfilled_policies) {
|
||||
return Error("bad fulfilled policies: idmap version 0x%08x, file system version 0x%08x",
|
||||
fulfilled_policies, fulfilled_policies_);
|
||||
}
|
||||
|
||||
if (enforce_overlayable != enforce_overlayable_) {
|
||||
return Error("bad enforce overlayable: idmap version %s, file system version %s",
|
||||
enforce_overlayable ? "true" : "false",
|
||||
enforce_overlayable_ ? "true" : "false");
|
||||
}
|
||||
|
||||
if (strcmp(target_path, target_path_) != 0) {
|
||||
return Error("bad target path: idmap version %s, file system version %s", target_path,
|
||||
target_path_);
|
||||
}
|
||||
|
||||
if (strcmp(overlay_path, overlay_path_) != 0) {
|
||||
return Error("bad overlay path: idmap version %s, file system version %s", overlay_path,
|
||||
overlay_path_);
|
||||
}
|
||||
|
||||
return Unit{};
|
||||
@@ -320,6 +349,9 @@ Result<std::unique_ptr<const Idmap>> Idmap::FromApkAssets(const ApkAssets& targe
|
||||
}
|
||||
header->overlay_crc_ = *crc;
|
||||
|
||||
header->fulfilled_policies_ = fulfilled_policies;
|
||||
header->enforce_overlayable_ = enforce_overlayable;
|
||||
|
||||
if (target_apk_path.size() > sizeof(header->target_path_)) {
|
||||
return Error("target apk path \"%s\" longer than maximum size %zu", target_apk_path.c_str(),
|
||||
sizeof(header->target_path_));
|
||||
|
||||
@@ -23,10 +23,12 @@
|
||||
#include "android-base/macros.h"
|
||||
#include "android-base/stringprintf.h"
|
||||
#include "androidfw/ApkAssets.h"
|
||||
#include "idmap2/PolicyUtils.h"
|
||||
#include "idmap2/ResourceUtils.h"
|
||||
#include "idmap2/Result.h"
|
||||
|
||||
using android::ApkAssets;
|
||||
using android::idmap2::policy::PoliciesToDebugString;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -39,9 +41,6 @@ size_t StringSizeWhenEncoded(const std::string& s) {
|
||||
|
||||
namespace android::idmap2 {
|
||||
|
||||
// verbatim copy fomr PrettyPrintVisitor.cpp, move to common utils
|
||||
#define RESID(pkg, type, entry) (((pkg) << 24) | ((type) << 16) | (entry))
|
||||
|
||||
void RawPrintVisitor::visit(const Idmap& idmap ATTRIBUTE_UNUSED) {
|
||||
}
|
||||
|
||||
@@ -50,6 +49,9 @@ void RawPrintVisitor::visit(const IdmapHeader& header) {
|
||||
print(header.GetVersion(), "version");
|
||||
print(header.GetTargetCrc(), "target crc");
|
||||
print(header.GetOverlayCrc(), "overlay crc");
|
||||
print(header.GetFulfilledPolicies(), "fulfilled policies: %s",
|
||||
PoliciesToDebugString(header.GetFulfilledPolicies()).c_str());
|
||||
print(static_cast<uint8_t>(header.GetEnforceOverlayable()), "enforce overlayable");
|
||||
print(header.GetTargetPath().to_string(), kIdmapStringLength, "target path");
|
||||
print(header.GetOverlayPath().to_string(), kIdmapStringLength, "overlay path");
|
||||
print("...", StringSizeWhenEncoded(header.GetDebugInfo()), "debug info");
|
||||
|
||||
@@ -291,13 +291,6 @@ Result<ResourceMapping> ResourceMapping::FromApkAssets(const ApkAssets& target_a
|
||||
const PolicyBitmask& fulfilled_policies,
|
||||
bool enforce_overlayable,
|
||||
LogInfo& log_info) {
|
||||
if (enforce_overlayable) {
|
||||
log_info.Info(LogMessage() << "fulfilled_policies="
|
||||
<< ConcatPolicies(BitmaskToPolicies(fulfilled_policies))
|
||||
<< " enforce_overlayable="
|
||||
<< (enforce_overlayable ? "true" : "false"));
|
||||
}
|
||||
|
||||
AssetManager2 target_asset_manager;
|
||||
if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true /* invalidate_caches */,
|
||||
false /* filter_incompatible_configs*/)) {
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "android-base/stringprintf.h"
|
||||
#include "androidfw/ResourceTypes.h"
|
||||
#include "androidfw/StringPiece.h"
|
||||
|
||||
using android::base::StringPrintf;
|
||||
|
||||
using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
|
||||
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
|
||||
|
||||
@@ -48,6 +51,29 @@ inline static const std::array<std::pair<StringPiece, PolicyFlags>, 8> kPolicySt
|
||||
{kPolicySystem, PolicyFlags::SYSTEM_PARTITION},
|
||||
{kPolicyVendor, PolicyFlags::VENDOR_PARTITION},
|
||||
};
|
||||
|
||||
inline static std::string PoliciesToDebugString(PolicyBitmask policies) {
|
||||
std::string str;
|
||||
uint32_t remaining = policies;
|
||||
for (auto const& policy : kPolicyStringToFlag) {
|
||||
if ((policies & policy.second) != policy.second) {
|
||||
continue;
|
||||
}
|
||||
if (!str.empty()) {
|
||||
str.append("|");
|
||||
}
|
||||
str.append(policy.first.data());
|
||||
remaining &= ~policy.second;
|
||||
}
|
||||
if (remaining != 0) {
|
||||
if (!str.empty()) {
|
||||
str.append("|");
|
||||
}
|
||||
str.append(StringPrintf("0x%08x", remaining));
|
||||
}
|
||||
return !str.empty() ? str : "none";
|
||||
}
|
||||
|
||||
} // namespace android::idmap2::policy
|
||||
|
||||
#endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
|
||||
|
||||
@@ -48,6 +48,11 @@ TEST(BinaryStreamVisitorTests, CreateBinaryStreamViaBinaryStreamVisitor) {
|
||||
ASSERT_TRUE(result2);
|
||||
const auto idmap2 = std::move(*result2);
|
||||
|
||||
ASSERT_EQ(idmap1->GetHeader()->GetFulfilledPolicies(),
|
||||
idmap2->GetHeader()->GetFulfilledPolicies());
|
||||
ASSERT_EQ(idmap1->GetHeader()->GetEnforceOverlayable(),
|
||||
idmap2->GetHeader()->GetEnforceOverlayable());
|
||||
ASSERT_EQ(idmap1->GetHeader()->GetTargetPath(), idmap2->GetHeader()->GetTargetPath());
|
||||
ASSERT_EQ(idmap1->GetHeader()->GetTargetCrc(), idmap2->GetHeader()->GetTargetCrc());
|
||||
ASSERT_EQ(idmap1->GetHeader()->GetTargetPath(), idmap2->GetHeader()->GetTargetPath());
|
||||
ASSERT_EQ(idmap1->GetData().size(), 1U);
|
||||
|
||||
@@ -62,9 +62,11 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
|
||||
std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
|
||||
ASSERT_THAT(header, NotNull());
|
||||
ASSERT_EQ(header->GetMagic(), 0x504d4449U);
|
||||
ASSERT_EQ(header->GetVersion(), 0x03U);
|
||||
ASSERT_EQ(header->GetVersion(), 0x04U);
|
||||
ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
|
||||
ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
|
||||
ASSERT_EQ(header->GetFulfilledPolicies(), 0x11);
|
||||
ASSERT_EQ(header->GetEnforceOverlayable(), true);
|
||||
ASSERT_EQ(header->GetTargetPath().to_string(), "targetX.apk");
|
||||
ASSERT_EQ(header->GetOverlayPath().to_string(), "overlayX.apk");
|
||||
ASSERT_EQ(header->GetDebugInfo(), "debug");
|
||||
@@ -73,7 +75,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
|
||||
TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
|
||||
std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
|
||||
// overwrite the target path string, including the terminating null, with '.'
|
||||
for (size_t i = 0x10; i < 0x110; i++) {
|
||||
for (size_t i = 0x15; i < 0x115; i++) {
|
||||
raw[i] = '.';
|
||||
}
|
||||
std::istringstream stream(raw);
|
||||
@@ -82,7 +84,7 @@ TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
|
||||
}
|
||||
|
||||
TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
|
||||
const size_t offset = 0x21c;
|
||||
const size_t offset = 0x221;
|
||||
std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
|
||||
idmap_raw_data_len - offset);
|
||||
std::istringstream stream(raw);
|
||||
@@ -94,7 +96,7 @@ TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
|
||||
}
|
||||
|
||||
TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
|
||||
const size_t offset = 0x21c;
|
||||
const size_t offset = 0x221;
|
||||
std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
|
||||
idmap_raw_data_len - offset);
|
||||
std::istringstream stream(raw);
|
||||
@@ -128,9 +130,11 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) {
|
||||
|
||||
ASSERT_THAT(idmap->GetHeader(), NotNull());
|
||||
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x03U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x04U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), 0x11);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetEnforceOverlayable(), true);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "targetX.apk");
|
||||
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlayX.apk");
|
||||
|
||||
@@ -180,9 +184,11 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) {
|
||||
|
||||
ASSERT_THAT(idmap->GetHeader(), NotNull());
|
||||
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x03U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x04U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), PolicyFlags::PUBLIC);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetEnforceOverlayable(), true);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
|
||||
}
|
||||
@@ -389,7 +395,8 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
|
||||
|
||||
std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
|
||||
ASSERT_THAT(header, NotNull());
|
||||
ASSERT_TRUE(header->IsUpToDate());
|
||||
ASSERT_TRUE(header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
|
||||
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
|
||||
|
||||
// magic: bytes (0x0, 0x03)
|
||||
std::string bad_magic_string(stream.str());
|
||||
@@ -402,7 +409,8 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
|
||||
IdmapHeader::FromBinaryStream(bad_magic_stream);
|
||||
ASSERT_THAT(bad_magic_header, NotNull());
|
||||
ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic());
|
||||
ASSERT_FALSE(bad_magic_header->IsUpToDate());
|
||||
ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
|
||||
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
|
||||
|
||||
// version: bytes (0x4, 0x07)
|
||||
std::string bad_version_string(stream.str());
|
||||
@@ -415,7 +423,8 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
|
||||
IdmapHeader::FromBinaryStream(bad_version_stream);
|
||||
ASSERT_THAT(bad_version_header, NotNull());
|
||||
ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion());
|
||||
ASSERT_FALSE(bad_version_header->IsUpToDate());
|
||||
ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
|
||||
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
|
||||
|
||||
// target crc: bytes (0x8, 0xb)
|
||||
std::string bad_target_crc_string(stream.str());
|
||||
@@ -428,7 +437,8 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
|
||||
IdmapHeader::FromBinaryStream(bad_target_crc_stream);
|
||||
ASSERT_THAT(bad_target_crc_header, NotNull());
|
||||
ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc());
|
||||
ASSERT_FALSE(bad_target_crc_header->IsUpToDate());
|
||||
ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
|
||||
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
|
||||
|
||||
// overlay crc: bytes (0xc, 0xf)
|
||||
std::string bad_overlay_crc_string(stream.str());
|
||||
@@ -441,27 +451,55 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
|
||||
IdmapHeader::FromBinaryStream(bad_overlay_crc_stream);
|
||||
ASSERT_THAT(bad_overlay_crc_header, NotNull());
|
||||
ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc());
|
||||
ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate());
|
||||
ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
|
||||
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
|
||||
|
||||
// target path: bytes (0x10, 0x10f)
|
||||
// fulfilled policy: bytes (0x10, 0x13)
|
||||
std::string bad_policy_string(stream.str());
|
||||
bad_policy_string[0x10] = '.';
|
||||
bad_policy_string[0x11] = '.';
|
||||
bad_policy_string[0x12] = '.';
|
||||
bad_policy_string[0x13] = '.';
|
||||
std::stringstream bad_policy_stream(bad_policy_string);
|
||||
std::unique_ptr<const IdmapHeader> bad_policy_header =
|
||||
IdmapHeader::FromBinaryStream(bad_policy_stream);
|
||||
ASSERT_THAT(bad_policy_header, NotNull());
|
||||
ASSERT_NE(header->GetFulfilledPolicies(), bad_policy_header->GetFulfilledPolicies());
|
||||
ASSERT_FALSE(bad_policy_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
|
||||
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
|
||||
|
||||
// enforce overlayable: bytes (0x14)
|
||||
std::string bad_enforce_string(stream.str());
|
||||
bad_enforce_string[0x14] = '\0';
|
||||
std::stringstream bad_enforce_stream(bad_enforce_string);
|
||||
std::unique_ptr<const IdmapHeader> bad_enforce_header =
|
||||
IdmapHeader::FromBinaryStream(bad_enforce_stream);
|
||||
ASSERT_THAT(bad_enforce_header, NotNull());
|
||||
ASSERT_NE(header->GetEnforceOverlayable(), bad_enforce_header->GetEnforceOverlayable());
|
||||
ASSERT_FALSE(bad_enforce_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
|
||||
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
|
||||
|
||||
// target path: bytes (0x15, 0x114)
|
||||
std::string bad_target_path_string(stream.str());
|
||||
bad_target_path_string[0x10] = '\0';
|
||||
bad_target_path_string[0x15] = '\0';
|
||||
std::stringstream bad_target_path_stream(bad_target_path_string);
|
||||
std::unique_ptr<const IdmapHeader> bad_target_path_header =
|
||||
IdmapHeader::FromBinaryStream(bad_target_path_stream);
|
||||
ASSERT_THAT(bad_target_path_header, NotNull());
|
||||
ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath());
|
||||
ASSERT_FALSE(bad_target_path_header->IsUpToDate());
|
||||
ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
|
||||
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
|
||||
|
||||
// overlay path: bytes (0x110, 0x20f)
|
||||
// overlay path: bytes (0x115, 0x214)
|
||||
std::string bad_overlay_path_string(stream.str());
|
||||
bad_overlay_path_string[0x110] = '\0';
|
||||
bad_overlay_path_string[0x115] = '\0';
|
||||
std::stringstream bad_overlay_path_stream(bad_overlay_path_string);
|
||||
std::unique_ptr<const IdmapHeader> bad_overlay_path_header =
|
||||
IdmapHeader::FromBinaryStream(bad_overlay_path_stream);
|
||||
ASSERT_THAT(bad_overlay_path_header, NotNull());
|
||||
ASSERT_NE(header->GetOverlayPath(), bad_overlay_path_header->GetOverlayPath());
|
||||
ASSERT_FALSE(bad_overlay_path_header->IsUpToDate());
|
||||
ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
|
||||
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
|
||||
}
|
||||
|
||||
class TestVisitor : public Visitor {
|
||||
|
||||
@@ -43,6 +43,8 @@ namespace android::idmap2 {
|
||||
<< str << "--------"; \
|
||||
} while (0)
|
||||
|
||||
#define ADDRESS "[0-9a-f]{8}: "
|
||||
|
||||
TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
|
||||
fclose(stderr); // silence expected warnings
|
||||
|
||||
@@ -62,15 +64,16 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
|
||||
RawPrintVisitor visitor(stream);
|
||||
(*idmap)->accept(&visitor);
|
||||
|
||||
#define ADDRESS "[0-9a-f]{8}: "
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000003 version\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 version\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(
|
||||
StringPrintf(ADDRESS "%s target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING),
|
||||
stream.str());
|
||||
ASSERT_CONTAINS_REGEX(
|
||||
StringPrintf(ADDRESS "%s overlay crc\n", android::idmap2::TestConstants::OVERLAY_CRC_STRING),
|
||||
stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000001 fulfilled policies: public\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS " 01 enforce overlayable\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS " 7f target package id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 target entry count\n", stream.str());
|
||||
@@ -83,7 +86,6 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 value: integer/int1\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 overlay id: integer/int1\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1\n", stream.str());
|
||||
#undef ADDRESS
|
||||
}
|
||||
|
||||
TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
|
||||
@@ -99,22 +101,23 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
|
||||
RawPrintVisitor visitor(stream);
|
||||
(*idmap)->accept(&visitor);
|
||||
|
||||
ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("00000004: 00000003 version\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("00000008: 00001234 target crc\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("0000000c: 00005678 overlay crc\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("0000021c: 7f target package id\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("0000021d: 7f overlay package id\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("0000021e: 00000003 target entry count\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("00000222: 00000003 overlay entry count\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("00000226: 00000000 string pool index offset\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("0000022a: 00000000 string pool byte length\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("0000022e: 7f020000 target id\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("00000232: 01 type: reference\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("00000233: 7f020000 value\n"), std::string::npos);
|
||||
|
||||
ASSERT_NE(stream.str().find("00000249: 7f020000 overlay id\n"), std::string::npos);
|
||||
ASSERT_NE(stream.str().find("0000024d: 7f020000 target id\n"), std::string::npos);
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 version\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00001234 target crc\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00005678 overlay crc\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000011 fulfilled policies: public|signature\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS " 01 enforce overlayable\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS " 7f target package id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000003 target entry count\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000003 overlay entry count\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool index offset\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool byte length\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS " 01 type: reference\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 value\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str());
|
||||
}
|
||||
|
||||
} // namespace android::idmap2
|
||||
|
||||
@@ -30,7 +30,7 @@ const unsigned char idmap_raw_data[] = {
|
||||
0x49, 0x44, 0x4d, 0x50,
|
||||
|
||||
// 0x4: version
|
||||
0x03, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x8: target crc
|
||||
0x34, 0x12, 0x00, 0x00,
|
||||
@@ -38,7 +38,13 @@ const unsigned char idmap_raw_data[] = {
|
||||
// 0xc: overlay crc
|
||||
0x78, 0x56, 0x00, 0x00,
|
||||
|
||||
// 0x10: target path "targetX.apk"
|
||||
// 0x10: fulfilled policies
|
||||
0x11, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x14: enforce overlayable
|
||||
0x01,
|
||||
|
||||
// 0x15: target path "targetX.apk"
|
||||
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -56,7 +62,7 @@ const unsigned char idmap_raw_data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x110: overlay path "overlayX.apk"
|
||||
// 0x115: overlay path "overlayX.apk"
|
||||
0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -74,7 +80,7 @@ const unsigned char idmap_raw_data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x210: debug string
|
||||
// 0x215: debug string
|
||||
// string length, including terminating null
|
||||
0x08, 0x00, 0x00, 0x00,
|
||||
|
||||
@@ -82,63 +88,63 @@ const unsigned char idmap_raw_data[] = {
|
||||
0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00,
|
||||
|
||||
// DATA HEADER
|
||||
// 0x21c: target_package_id
|
||||
// 0x221: target_package_id
|
||||
0x7f,
|
||||
|
||||
// 0x21d: overlay_package_id
|
||||
// 0x222: overlay_package_id
|
||||
0x7f,
|
||||
|
||||
// 0x21e: target_entry_count
|
||||
// 0x223: target_entry_count
|
||||
0x03, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x222: overlay_entry_count
|
||||
// 0x227: overlay_entry_count
|
||||
0x03, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x226: string_pool_offset
|
||||
// 0x22b: string_pool_offset
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x22a: string_pool_byte_length
|
||||
// 0x22f: string_pool_byte_length
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// TARGET ENTRIES
|
||||
// 0x22e: 0x7f020000
|
||||
0x00, 0x00, 0x02, 0x7f,
|
||||
|
||||
// 0x232: TYPE_REFERENCE
|
||||
0x01,
|
||||
|
||||
// 0x233: 0x7f020000
|
||||
0x00, 0x00, 0x02, 0x7f,
|
||||
|
||||
// 0x237: 0x7f030000
|
||||
0x00, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0x23b: TYPE_REFERENCE
|
||||
// 0x237: TYPE_REFERENCE
|
||||
0x01,
|
||||
|
||||
// 0x238: 0x7f020000
|
||||
0x00, 0x00, 0x02, 0x7f,
|
||||
|
||||
// 0x23c: 0x7f030000
|
||||
0x00, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0x240: 0x7f030002
|
||||
0x02, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0x244: TYPE_REFERENCE
|
||||
// 0x240: TYPE_REFERENCE
|
||||
0x01,
|
||||
|
||||
// 0x245: 0x7f030001
|
||||
// 0x241: 0x7f030000
|
||||
0x00, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0x245: 0x7f030002
|
||||
0x02, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0x249: TYPE_REFERENCE
|
||||
0x01,
|
||||
|
||||
// 0x24a: 0x7f030001
|
||||
0x01, 0x00, 0x03, 0x7f,
|
||||
|
||||
// OVERLAY ENTRIES
|
||||
// 0x249: 0x7f020000 -> 0x7f020000
|
||||
// 0x24e: 0x7f020000 -> 0x7f020000
|
||||
0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f,
|
||||
|
||||
// 0x251: 0x7f030000 -> 0x7f030000
|
||||
// 0x256: 0x7f030000 -> 0x7f030000
|
||||
0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0x259: 0x7f030001 -> 0x7f030002
|
||||
// 0x25e: 0x7f030001 -> 0x7f030002
|
||||
0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f};
|
||||
|
||||
const unsigned int idmap_raw_data_len = 0x261;
|
||||
const unsigned int idmap_raw_data_len = 0x266;
|
||||
|
||||
std::string GetTestDataPath();
|
||||
|
||||
|
||||
@@ -28,5 +28,6 @@ java_test_host {
|
||||
":OverlayRemountedTest_Target",
|
||||
":OverlayRemountedTest_TargetUpgrade",
|
||||
":OverlayRemountedTest_Overlay",
|
||||
":OverlayRemountedTest_Overlay_SameCert",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(DeviceJUnit4ClassRunner.class)
|
||||
public class PackagedUpgradedTest extends OverlayRemountedTestBase {
|
||||
public class RegenerateIdmapTest extends OverlayRemountedTestBase {
|
||||
private static final String OVERLAY_SIGNATURE_APK =
|
||||
"OverlayRemountedTest_Overlay_SameCert.apk";
|
||||
private static final String TARGET_UPGRADE_APK = "OverlayRemountedTest_TargetUpgrade.apk";
|
||||
|
||||
@Test
|
||||
@@ -66,4 +68,32 @@ public class PackagedUpgradedTest extends OverlayRemountedTestBase {
|
||||
assertResource(targetReference, "@" + 0x7f0100ff + " -> true");
|
||||
assertResource(targetOverlaid, "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdmapPoliciesChanged() throws Exception {
|
||||
final String targetResource = resourceName(TARGET_PACKAGE, "bool",
|
||||
"signature_policy_overlaid");
|
||||
|
||||
mPreparer.pushResourceFile(TARGET_APK, "/product/app/OverlayTarget.apk")
|
||||
.pushResourceFile(OVERLAY_APK, "/product/overlay/TestOverlay.apk")
|
||||
.reboot()
|
||||
.setOverlayEnabled(OVERLAY_PACKAGE, false);
|
||||
|
||||
assertResource(targetResource, "false");
|
||||
|
||||
// The overlay is not signed with the same signature as the target.
|
||||
mPreparer.setOverlayEnabled(OVERLAY_PACKAGE, true);
|
||||
assertResource(targetResource, "false");
|
||||
|
||||
// Replace the overlay with a version of the overlay that is signed with the same signature
|
||||
// as the target.
|
||||
mPreparer.pushResourceFile(OVERLAY_SIGNATURE_APK, "/product/overlay/TestOverlay.apk")
|
||||
.reboot();
|
||||
|
||||
// The idmap should have been recreated with the signature policy fulfilled.
|
||||
assertResource(targetResource, "true");
|
||||
|
||||
mPreparer.setOverlayEnabled(OVERLAY_PACKAGE, false);
|
||||
assertResource(targetResource, "false");
|
||||
}
|
||||
}
|
||||
@@ -19,3 +19,9 @@ android_test_helper_app {
|
||||
"com.android.overlaytest.overlay",
|
||||
],
|
||||
}
|
||||
|
||||
android_test_helper_app {
|
||||
name: "OverlayRemountedTest_Overlay_SameCert",
|
||||
certificate: ":rro-remounted-test-a",
|
||||
sdk_version: "current",
|
||||
}
|
||||
@@ -17,4 +17,5 @@
|
||||
|
||||
<resources>
|
||||
<bool name="target_overlaid">true</bool>
|
||||
<bool name="signature_policy_overlaid">true</bool>
|
||||
</resources>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
android_test_helper_app {
|
||||
name: "OverlayRemountedTest_Target",
|
||||
sdk_version: "test_current",
|
||||
certificate: ":rro-remounted-test-a",
|
||||
apex_available: [
|
||||
"com.android.overlaytest.overlaid",
|
||||
],
|
||||
@@ -23,6 +24,7 @@ android_test_helper_app {
|
||||
|
||||
android_test_helper_app {
|
||||
name: "OverlayRemountedTest_TargetUpgrade",
|
||||
certificate: ":rro-remounted-test-a",
|
||||
resource_dirs: ["res_upgrade"],
|
||||
sdk_version: "test_current",
|
||||
}
|
||||
|
||||
@@ -20,5 +20,8 @@
|
||||
<policy type="public">
|
||||
<item type="bool" name="target_overlaid" />
|
||||
</policy>
|
||||
<policy type="signature">
|
||||
<item type="bool" name="signature_policy_overlaid" />
|
||||
</policy>
|
||||
</overlayable>
|
||||
</resources>
|
||||
|
||||
@@ -23,4 +23,6 @@
|
||||
<bool name="target_overlaid">false</bool>
|
||||
<public type="bool" name="target_overlaid" id="0x7f010000" />
|
||||
<bool name="target_reference">@bool/target_overlaid</bool>
|
||||
|
||||
<bool name="signature_policy_overlaid">false</bool>
|
||||
</resources>
|
||||
|
||||
19
core/tests/overlaytests/remount/test-apps/certs/Android.bp
Normal file
19
core/tests/overlaytests/remount/test-apps/certs/Android.bp
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright (C) 2020 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.
|
||||
|
||||
// development/tools/make_key rro-remounted-test-a '/CN=rro_test_a'
|
||||
android_app_certificate {
|
||||
name: "rro-remounted-test-a",
|
||||
certificate: "rro-remounted-test-a",
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDCzCCAfOgAwIBAgIUfphI+C6W6V6RomsP7+CW5dO5cGcwDQYJKoZIhvcNAQEL
|
||||
BQAwFTETMBEGA1UEAwwKcnJvX3Rlc3RfYTAeFw0yMDA1MTQxNjM4MDBaFw00NzA5
|
||||
MzAxNjM4MDBaMBUxEzARBgNVBAMMCnJyb190ZXN0X2EwggEiMA0GCSqGSIb3DQEB
|
||||
AQUAA4IBDwAwggEKAoIBAQCvXM8tcqQFwH7iQG6+8mAx2ADhwbtq+8Rcmiz7wviW
|
||||
Yf/eFDRuvZ/ma6lxeVJ7mcbF7A5rinEKdgN5hlW2UlbTmuX5YOiXnX3Y2J5t+8Pi
|
||||
aq787IvWxkawwkj0Oy1Hk01Z4w3HTYntYqi36bq4QyNpwh515VqgvEyCHT7IPtQi
|
||||
XjfwcTW0thUlSDyDkgxq9NxNEJgaHHOamKkeMCO8CkBWkhlcPXvjcM8DPFmyzDI9
|
||||
Czv8IYFZQbcG/N2GPH9hSteMnuC+zyoMio0V/VRctQGlAA8ATsheBkng0zcNRu9Z
|
||||
GIavk5AaClmBFTeQx01j3HFSO8UDdDJ5Hk8uDTqecPLpAgMBAAGjUzBRMB0GA1Ud
|
||||
DgQWBBSPbIdzSkPbzltj3qIS13LNDiyIiDAfBgNVHSMEGDAWgBSPbIdzSkPbzltj
|
||||
3qIS13LNDiyIiDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCH
|
||||
QvvMGyMvVJaWMEJwVdUnszdXiAlUtDd/2HpdGOxW6xVVAvveP8hJ71gWFQ7Qs3Mr
|
||||
3jxclbC37qVAPiQb8kkD8qUgoQYMC43asif6Jn65OU1QkDRF3bFHP+rZVSPEwtvl
|
||||
YMbOzHPOLr7HESwlM7TB6EoZ4oOso++jTYI/OSif1MOKOMbOt4X/DE/PXf81ayFs
|
||||
uRjpocBqnLwOourABMcaKbA92jB0LRTtgv5ngOJ3+5P1cTiHktFbnqVWa8/A3uSA
|
||||
dNR5dpOUjH+nCHTwPl64b7R70PgDxnoqMs0xI7VtJovXor64OZy9P8WTdurz5V/z
|
||||
k2IVSi032bf0aTxamvqV
|
||||
-----END CERTIFICATE-----
|
||||
@@ -41,7 +41,7 @@
|
||||
namespace android {
|
||||
|
||||
constexpr const static uint32_t kIdmapMagic = 0x504D4449u;
|
||||
constexpr const static uint32_t kIdmapCurrentVersion = 0x00000003u;
|
||||
constexpr const static uint32_t kIdmapCurrentVersion = 0x00000004u;
|
||||
|
||||
/**
|
||||
* In C++11, char16_t is defined as *at least* 16 bits. We do a lot of
|
||||
@@ -1746,6 +1746,9 @@ struct Idmap_header {
|
||||
uint32_t target_crc32;
|
||||
uint32_t overlay_crc32;
|
||||
|
||||
uint32_t fulfilled_policies;
|
||||
uint8_t enforce_overlayable;
|
||||
|
||||
uint8_t target_path[256];
|
||||
uint8_t overlay_path[256];
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -252,29 +252,6 @@ class ValueBodyPrinter : public ConstValueVisitor {
|
||||
Printer* printer_;
|
||||
};
|
||||
|
||||
std::string OverlayablePoliciesToString(PolicyFlags policies) {
|
||||
std::string str;
|
||||
|
||||
uint32_t remaining = policies;
|
||||
for (auto const& policy : kPolicyStringToFlag) {
|
||||
if ((policies & policy.second) != policy.second) {
|
||||
continue;
|
||||
}
|
||||
if (!str.empty()) {
|
||||
str.append("|");
|
||||
}
|
||||
str.append(policy.first.data());
|
||||
remaining &= ~policy.second;
|
||||
}
|
||||
if (remaining != 0) {
|
||||
if (!str.empty()) {
|
||||
str.append("|");
|
||||
}
|
||||
str.append(StringPrintf("0x%08x", remaining));
|
||||
}
|
||||
return !str.empty() ? str : "none";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& options,
|
||||
@@ -575,7 +552,7 @@ void Debug::DumpOverlayable(const ResourceTable& table, text::Printer* printer)
|
||||
overlayable_item.overlayable->name.c_str(),
|
||||
overlayable_item.overlayable->actor.c_str());
|
||||
const auto policy_subsection = StringPrintf(R"(policies="%s")",
|
||||
OverlayablePoliciesToString(overlayable_item.policies).c_str());
|
||||
android::idmap2::policy::PoliciesToDebugString(overlayable_item.policies).c_str());
|
||||
const auto value =
|
||||
StringPrintf("%s/%s", to_string(type->type).data(), entry->name.c_str());
|
||||
items.push_back(DumpOverlayableEntry{overlayable_section, policy_subsection, value});
|
||||
|
||||
Reference in New Issue
Block a user