summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJooyung Han <jooyung@google.com>2022-11-02 15:25:14 +0900
committerJooyung Han <jooyung@google.com>2022-11-03 23:27:26 +0000
commit28b22dd408744618f5e02d3070b64b5b638d10fe (patch)
treefd5f4f682fc098849cd1922dfcf676555564a58d
parentb7d06fa614768b2f62735df10d1162af746088b4 (diff)
downloadapex-28b22dd408744618f5e02d3070b64b5b638d10fe.tar.gz
AddBlockApex checks uniqueness for "factory" apexes
There can be many versions in /data/apex. Likewise, in AddBlockApex(), we need to allow duplicates for non-factory apexes. This is the case when "sharelibs" apexes are passed to VM because we need all versions of "sharedlibs" apexes from host. Bug: 256898152 Test: ApexTestCases Merged-In: I8e80f1e2a6c7f031b4a0eef40067c44584aa8503 Change-Id: I8e80f1e2a6c7f031b4a0eef40067c44584aa8503 (cherry picked from commit abee35d239f86ccb274ba0e794a56cf64df878d6)
-rw-r--r--apexd/apex_file_repository.cpp13
-rw-r--r--apexd/apexd_test.cpp78
2 files changed, 70 insertions, 21 deletions
diff --git a/apexd/apex_file_repository.cpp b/apexd/apex_file_repository.cpp
index e82feb4c..43b6f6e9 100644
--- a/apexd/apex_file_repository.cpp
+++ b/apexd/apex_file_repository.cpp
@@ -282,17 +282,14 @@ Result<int> ApexFileRepository::AddBlockApex(
block_apex_overrides_.emplace(name, std::move(overrides));
}
- // APEX should be unique.
- for (const auto* store : {&pre_installed_store_, &data_store_}) {
- auto it = store->find(name);
- if (it != store->end()) {
- return Error() << "duplicate of " << name << " found in "
- << it->second.GetPath();
- }
- }
// Depending on whether the APEX was a factory version in the host or not,
// put it to different stores.
auto& store = apex_config.is_factory() ? pre_installed_store_ : data_store_;
+ // We want "uniqueness" in each store.
+ if (auto it = store.find(name); it != store.end()) {
+ return Error() << "duplicate of " << name << " found in "
+ << it->second.GetPath();
+ }
store.emplace(name, std::move(*apex_file));
ret++;
diff --git a/apexd/apexd_test.cpp b/apexd/apexd_test.cpp
index 846499bd..732e23fb 100644
--- a/apexd/apexd_test.cpp
+++ b/apexd/apexd_test.cpp
@@ -214,10 +214,11 @@ class ApexdUnitTest : public ::testing::Test {
std::string AddBlockApex(const std::string& apex_name,
const std::string& public_key = "",
- const std::string& root_digest = "") {
- auto apex_path = vm_payload_disk_ + "2"; // second partition
+ const std::string& root_digest = "",
+ bool is_factory = true) {
+ auto apex_path = vm_payload_disk_ + std::to_string(block_device_index_++);
auto apex_file = GetTestFile(apex_name);
- WriteMetadata(apex_file, public_key, root_digest);
+ AddToMetadata(apex_name, public_key, root_digest, is_factory);
// loop_devices_ will be disposed after each test
loop_devices_.push_back(*WriteBlockApex(apex_file, apex_path));
return apex_path;
@@ -270,24 +271,23 @@ class ApexdUnitTest : public ::testing::Test {
DeleteDirContent(ApexSession::GetSessionsDir());
}
- void WriteMetadata(const std::string& apex_file,
+ void AddToMetadata(const std::string& apex_name,
const std::string& public_key,
- const std::string& root_digest) {
+ const std::string& root_digest, bool is_factory) {
android::microdroid::Metadata metadata;
+ // The first partition is metadata partition
+ auto metadata_partition = vm_payload_disk_ + "1";
+ if (access(metadata_partition.c_str(), F_OK) == 0) {
+ metadata = *android::microdroid::ReadMetadata(metadata_partition);
+ }
auto apex = metadata.add_apexes();
- apex->set_name("apex");
+ apex->set_name(apex_name);
apex->set_public_key(public_key);
apex->set_root_digest(root_digest);
- // In this test, block apeses are assumed as "factory".
- // ApexFileRepositoryTestAddBlockApex tests non-factory cases.
- apex->set_is_factory(true);
+ apex->set_is_factory(is_factory);
- // The first partition is metadata partition
- auto metadata_partition = vm_payload_disk_ + "1";
- LOG(INFO) << "Writing metadata to " << metadata_partition;
std::ofstream out(metadata_partition);
-
android::microdroid::WriteMetadata(metadata, out);
}
@@ -309,6 +309,7 @@ class ApexdUnitTest : public ::testing::Test {
std::string metadata_sepolicy_staged_dir_;
ApexdConfig config_;
std::vector<loop::LoopbackDeviceUniqueFd> loop_devices_; // to be cleaned up
+ int block_device_index_ = 2; // "1" is reserved for metadata;
};
// Apex that does not have pre-installed version, does not get selected
@@ -4061,6 +4062,57 @@ TEST_F(ApexdMountTest, OnStartInVmModeFailsWithDuplicateNames) {
ASSERT_EQ(1, OnStartInVmMode());
}
+TEST_F(ApexdMountTest, OnStartInVmSupportsMultipleSharedLibsApexes) {
+ MockCheckpointInterface checkpoint_interface;
+ InitializeVold(&checkpoint_interface);
+ SetBlockApexEnabled(true);
+
+ auto path1 =
+ AddBlockApex("apex.apexd_test.apex",
+ /*public_key=*/"", /*root_digest=*/"", /*is_factory=*/true);
+ auto path2 =
+ AddBlockApex("apex.apexd_test_v2.apex",
+ /*public_key=*/"", /*root_digest=*/"", /*is_factory=*/false);
+
+ ASSERT_EQ(0, OnStartInVmMode());
+ UnmountOnTearDown(path1);
+ UnmountOnTearDown(path2);
+}
+
+TEST_F(ApexdMountTest, OnStartInVmShouldRejectInDuplicateFactoryApexes) {
+ MockCheckpointInterface checkpoint_interface;
+ InitializeVold(&checkpoint_interface);
+ SetBlockApexEnabled(true);
+
+ auto path1 =
+ AddBlockApex("apex.apexd_test.apex",
+ /*public_key=*/"", /*root_digest=*/"", /*is_factory=*/true);
+ auto path2 =
+ AddBlockApex("apex.apexd_test_v2.apex",
+ /*public_key=*/"", /*root_digest=*/"", /*is_factory=*/true);
+
+ ASSERT_EQ(1, OnStartInVmMode());
+ UnmountOnTearDown(path1);
+ UnmountOnTearDown(path2);
+}
+
+TEST_F(ApexdMountTest, OnStartInVmShouldRejectInDuplicateNonFactoryApexes) {
+ MockCheckpointInterface checkpoint_interface;
+ InitializeVold(&checkpoint_interface);
+ SetBlockApexEnabled(true);
+
+ auto path1 =
+ AddBlockApex("apex.apexd_test.apex",
+ /*public_key=*/"", /*root_digest=*/"", /*is_factory=*/false);
+ auto path2 =
+ AddBlockApex("apex.apexd_test_v2.apex",
+ /*public_key=*/"", /*root_digest=*/"", /*is_factory=*/false);
+
+ ASSERT_EQ(1, OnStartInVmMode());
+ UnmountOnTearDown(path1);
+ UnmountOnTearDown(path2);
+}
+
TEST_F(ApexdMountTest, OnStartInVmModeFailsWithWrongPubkey) {
MockCheckpointInterface checkpoint_interface;
// Need to call InitializeVold before calling OnStart