Delete staged SEPolicy files if the session is aborted
Bug: 218672709
Test: manual tests and ApexdMountTest#AbortSepolicyApexInstall
Change-Id: I09116b95866b93ddf65a2713b1961477b4529312
diff --git a/apexd/apexd.cpp b/apexd/apexd.cpp
index 52d31da..055c641 100644
--- a/apexd/apexd.cpp
+++ b/apexd/apexd.cpp
@@ -905,6 +905,8 @@
return {};
}
+static constexpr auto kSepolicyApexName = "com.android.sepolicy.apex";
+
// A version of apex verification that happens on SubmitStagedSession.
// This function contains checks that might be expensive to perform, e.g. temp
// mounting a package and reading entire dm-verity device, and shouldn't be run
@@ -916,7 +918,7 @@
}
const auto validate_fn = [&apex_file](const std::string& mount_point) {
- if (apex_file.GetManifest().name() == "com.android.sepolicy.apex") {
+ if (apex_file.GetManifest().name() == kSepolicyApexName) {
return CopySepolicyToMetadata(mount_point);
}
return Result<void>{};
@@ -1675,17 +1677,40 @@
return ErrnoError() << "Cannot find matching package for: " << packageName;
}
+Result<void> DeleteStagedSepolicy() {
+ const auto staged_dir =
+ std::string(gConfig->metadata_sepolicy_staged_dir) + "/";
+ LOG(DEBUG) << "Deleting " << staged_dir;
+ std::error_code ec;
+ auto removed = std::filesystem::remove_all(staged_dir, ec);
+ if (removed == 0) {
+ LOG(INFO) << staged_dir << " already deleted.";
+ } else if (ec) {
+ return Error() << "Failed to clear " << staged_dir << ": " << ec.message();
+ }
+ return {};
+}
+
/**
* Abort individual staged session.
*
* Returns without error only if session was successfully aborted.
**/
Result<void> AbortStagedSession(int session_id) {
- // TODO(b/218672709): Delete staged SEPolicy file if the session is aborted.
auto session = ApexSession::GetSession(session_id);
if (!session.ok()) {
return Error() << "No session found with id " << session_id;
}
+
+ const auto& apex_names = session->GetApexNames();
+ if (std::find(std::begin(apex_names), std::end(apex_names),
+ kSepolicyApexName) != std::end(apex_names)) {
+ const auto result = DeleteStagedSepolicy();
+ if (!result.ok()) {
+ return result.error();
+ }
+ }
+
switch (session->GetState()) {
case SessionState::VERIFIED:
[[clang::fallthrough]];
@@ -2196,7 +2221,6 @@
LOG(ERROR) << "Cannot open apex file during staging: " << apex;
continue;
}
- session.AddApexName(apex_file->GetManifest().name());
}
const Result<void> result = StagePackages(apexes);
@@ -3100,6 +3124,9 @@
session->SetHasRollbackEnabled(has_rollback_enabled);
session->SetIsRollback(is_rollback);
session->SetRollbackId(rollback_id);
+ for (const auto& apex_file : ret) {
+ session->AddApexName(apex_file.GetManifest().name());
+ }
Result<void> commit_status =
(*session).UpdateStateAndCommit(SessionState::VERIFIED);
if (!commit_status.ok()) {
diff --git a/apexd/apexd_test.cpp b/apexd/apexd_test.cpp
index e2fe9e7..327ceaf 100644
--- a/apexd/apexd_test.cpp
+++ b/apexd/apexd_test.cpp
@@ -139,7 +139,8 @@
ota_reserved_dir_ = StringPrintf("%s/ota-reserved", td_.path);
hash_tree_dir_ = StringPrintf("%s/apex-hash-tree", td_.path);
staged_session_dir_ = StringPrintf("%s/staged-session-dir", td_.path);
- metadata_sepolicy_dir_ = StringPrintf("%s/metadata-sepolicy-dir", td_.path);
+ metadata_sepolicy_staged_dir_ =
+ StringPrintf("%s/metadata-sepolicy-staged-dir", td_.path);
vm_payload_disk_ = StringPrintf("%s/vm-payload", td_.path);
@@ -150,7 +151,7 @@
ota_reserved_dir_.c_str(),
hash_tree_dir_.c_str(),
staged_session_dir_.c_str(),
- metadata_sepolicy_dir_.c_str(),
+ metadata_sepolicy_staged_dir_.c_str(),
kTestVmPayloadMetadataPartitionProp,
kTestActiveApexSelinuxCtx};
}
@@ -164,7 +165,9 @@
return StringPrintf("%s/session_%d", staged_session_dir_.c_str(),
session_id);
}
- const std::string& GetMetadataSepolicyDir() { return metadata_sepolicy_dir_; }
+ const std::string& GetMetadataSepolicyStagedDir() {
+ return metadata_sepolicy_staged_dir_;
+ }
std::string GetRootDigest(const ApexFile& apex) {
if (apex.IsCompressed()) {
@@ -247,7 +250,7 @@
ASSERT_EQ(mkdir(ota_reserved_dir_.c_str(), 0755), 0);
ASSERT_EQ(mkdir(hash_tree_dir_.c_str(), 0755), 0);
ASSERT_EQ(mkdir(staged_session_dir_.c_str(), 0755), 0);
- ASSERT_EQ(mkdir(metadata_sepolicy_dir_.c_str(), 0755), 0);
+ ASSERT_EQ(mkdir(metadata_sepolicy_staged_dir_.c_str(), 0755), 0);
DeleteDirContent(ApexSession::GetSessionsDir());
}
@@ -287,7 +290,7 @@
std::string vm_payload_disk_;
std::string vm_payload_metadata_path_;
std::string staged_session_dir_;
- std::string metadata_sepolicy_dir_;
+ std::string metadata_sepolicy_staged_dir_;
ApexdConfig config_;
std::vector<loop::LoopbackDeviceUniqueFd> loop_devices_; // to be cleaned up
};
@@ -4295,11 +4298,27 @@
/* is_rollback= */ false, /* rollback_id= */ -1),
Ok());
- auto metadata_dir = GetMetadataSepolicyDir();
- ASSERT_THAT(PathExists(metadata_dir + "/SEPolicy.zip"), HasValue(true));
- ASSERT_THAT(PathExists(metadata_dir + "/SEPolicy.zip.sig"), HasValue(true));
- ASSERT_THAT(PathExists(metadata_dir + "/SEPolicy.zip.fsv_sig"),
- HasValue(true));
+ auto staged_dir = GetMetadataSepolicyStagedDir();
+ ASSERT_THAT(PathExists(staged_dir + "/SEPolicy.zip"), HasValue(true));
+ ASSERT_THAT(PathExists(staged_dir + "/SEPolicy.zip.sig"), HasValue(true));
+ ASSERT_THAT(PathExists(staged_dir + "/SEPolicy.zip.fsv_sig"), HasValue(true));
+}
+
+TEST_F(ApexdMountTest, AbortSepolicyApexInstall) {
+ std::string file_path = AddPreInstalledApex("com.android.sepolicy.apex");
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
+ ASSERT_THAT(CreateStagedSession("com.android.sepolicy.apex", 666), Ok());
+ ASSERT_THAT(
+ SubmitStagedSession(666, {}, /* has_rollback_enabled= */ false,
+ /* is_rollback= */ false, /* rollback_id= */ -1),
+ Ok());
+
+ auto staged_dir = GetMetadataSepolicyStagedDir();
+ ASSERT_THAT(PathExists(staged_dir), HasValue(true));
+ ASSERT_FALSE(IsEmptyDirectory(staged_dir));
+
+ ASSERT_THAT(AbortStagedSession(666), Ok());
+ ASSERT_THAT(PathExists(staged_dir), HasValue(false));
}
class ApexActivationFailureTests : public ApexdMountTest {};