diff options
author | Jooyung Han <jooyung@google.com> | 2022-11-02 15:25:14 +0900 |
---|---|---|
committer | Jooyung Han <jooyung@google.com> | 2022-11-03 23:27:26 +0000 |
commit | 28b22dd408744618f5e02d3070b64b5b638d10fe (patch) | |
tree | fd5f4f682fc098849cd1922dfcf676555564a58d | |
parent | b7d06fa614768b2f62735df10d1162af746088b4 (diff) | |
download | apex-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.cpp | 13 | ||||
-rw-r--r-- | apexd/apexd_test.cpp | 78 |
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 |