summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavin Corkery <gavincorkery@google.com>2019-09-26 12:53:45 +0100
committerGavin Corkery <gavincorkery@google.com>2019-12-13 12:33:12 +0000
commita41373acd02cc04e2ffa4088eb6ee0a964fd3dec (patch)
treef76e5a071e6e1e91bdfdc5b35406c70070d364ed
parentff34b18d49a0966d60181aa728ff0ffc961932ee (diff)
Add build fingerprint checks to apexd
Staged sessions should be abandoned when the build fingerprint changes (in case of an OTA, for example). This change stores the build fingerprint as part of an APEX session, which is then verified upon reboot. Bug: 145840157 Test: Stage APEX install, reboot with same/different build fingerprints and verify session is completed/abandoned respectively Test: atest ApexServiceTest#SubmitStagedSessionStoresBuildFingerprint Change-Id: I90ff014e82e6913914f0d752bb43f10d5efc6f2c Merged-In: I90ff014e82e6913914f0d752bb43f10d5efc6f2c (cherry picked from commit 778cacee8bffc8d257245e71c05f705fa53078c1)
-rw-r--r--apexd/apexd.cpp12
-rw-r--r--apexd/apexd_session.cpp8
-rw-r--r--apexd/apexd_session.h2
-rw-r--r--apexd/apexservice_test.cpp15
-rw-r--r--proto/session_state.proto3
5 files changed, 40 insertions, 0 deletions
diff --git a/apexd/apexd.cpp b/apexd/apexd.cpp
index 4f5ca52..589b962 100644
--- a/apexd/apexd.cpp
+++ b/apexd/apexd.cpp
@@ -93,6 +93,8 @@ static constexpr const char* kApexStatusSysprop = "apexd.status";
static constexpr const char* kApexStatusStarting = "starting";
static constexpr const char* kApexStatusReady = "ready";
+static constexpr const char* kBuildFingerprintSysprop = "ro.build.fingerprint";
+
static constexpr const char* kApexVerityOnSystemProp =
"persist.apexd.verity_on_system";
static bool gForceDmVerityOnSystem =
@@ -1372,6 +1374,7 @@ Status scanPackagesDirAndActivate(const char* apex_package_dir) {
}
void scanStagedSessionsDirAndStage() {
+ using android::base::GetProperty;
LOG(INFO) << "Scanning " << kApexSessionsDir
<< " looking for sessions to be activated.";
@@ -1389,6 +1392,12 @@ void scanStagedSessionsDirAndStage() {
};
auto scope_guard = android::base::make_scope_guard(session_failed_fn);
+ std::string build_fingerprint = GetProperty(kBuildFingerprintSysprop, "");
+ if (session.GetBuildFingerprint().compare(build_fingerprint) != 0) {
+ LOG(ERROR) << "APEX build fingerprint has changed";
+ continue;
+ }
+
std::vector<std::string> dirsToScan;
if (session.GetChildSessionIds().empty()) {
dirsToScan.push_back(std::string(kStagedSessionsDir) + "/session_" +
@@ -1789,6 +1798,7 @@ void onAllPackagesReady() {
StatusOr<std::vector<ApexFile>> submitStagedSession(
const int session_id, const std::vector<int>& child_session_ids) {
+ using android::base::GetProperty;
bool needsBackup = true;
Status cleanup_status = ClearSessions();
if (!cleanup_status.Ok()) {
@@ -1843,6 +1853,8 @@ StatusOr<std::vector<ApexFile>> submitStagedSession(
return StatusOr<std::vector<ApexFile>>::MakeError(session.ErrorMessage());
}
(*session).SetChildSessionIds(child_session_ids);
+ std::string build_fingerprint = GetProperty(kBuildFingerprintSysprop, "");
+ (*session).SetBuildFingerprint(build_fingerprint);
Status commit_status =
(*session).UpdateStateAndCommit(SessionState::VERIFIED);
if (!commit_status.Ok()) {
diff --git a/apexd/apexd_session.cpp b/apexd/apexd_session.cpp
index c94585f..98180b7 100644
--- a/apexd/apexd_session.cpp
+++ b/apexd/apexd_session.cpp
@@ -168,6 +168,10 @@ SessionState::State ApexSession::GetState() const { return state_.state(); }
int ApexSession::GetId() const { return state_.id(); }
+std::string ApexSession::GetBuildFingerprint() const {
+ return state_.expected_build_fingerprint();
+}
+
bool ApexSession::IsFinalized() const {
switch (GetState()) {
case SessionState::SUCCESS:
@@ -194,6 +198,10 @@ void ApexSession::SetChildSessionIds(
child_session_ids.end()};
}
+void ApexSession::SetBuildFingerprint(const std::string& fingerprint) {
+ *(state_.mutable_expected_build_fingerprint()) = fingerprint;
+}
+
Status ApexSession::UpdateStateAndCommit(
const SessionState::State& session_state) {
state_.set_state(session_state);
diff --git a/apexd/apexd_session.h b/apexd/apexd_session.h
index 5f32198..7b6b703 100644
--- a/apexd/apexd_session.h
+++ b/apexd/apexd_session.h
@@ -43,9 +43,11 @@ class ApexSession {
const google::protobuf::RepeatedField<int> GetChildSessionIds() const;
::apex::proto::SessionState::State GetState() const;
int GetId() const;
+ std::string GetBuildFingerprint() const;
bool IsFinalized() const;
void SetChildSessionIds(const std::vector<int>& child_session_ids);
+ void SetBuildFingerprint(const std::string& fingerprint);
Status UpdateStateAndCommit(const ::apex::proto::SessionState::State& state);
Status DeleteSession() const;
diff --git a/apexd/apexservice_test.cpp b/apexd/apexservice_test.cpp
index cad7789..89ca62b 100644
--- a/apexd/apexservice_test.cpp
+++ b/apexd/apexservice_test.cpp
@@ -565,6 +565,21 @@ TEST_F(ApexServiceTest,
}
}
+TEST_F(ApexServiceTest, SubmitStagedSessionStoresBuildFingerprint) {
+ PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
+ "/data/app-staging/session_1547",
+ "staging_data_file");
+ if (!installer.Prepare()) {
+ return;
+ }
+ ApexInfoList list;
+ bool success;
+ ASSERT_TRUE(IsOk(service_->submitStagedSession(1547, {}, &list, &success)));
+
+ auto session = ApexSession::GetSession(1547);
+ ASSERT_FALSE(session->GetBuildFingerprint().empty());
+}
+
TEST_F(ApexServiceTest, SubmitStagedSessionFailDoesNotLeakTempVerityDevices) {
using android::dm::DeviceMapper;
diff --git a/proto/session_state.proto b/proto/session_state.proto
index addb703..f023353 100644
--- a/proto/session_state.proto
+++ b/proto/session_state.proto
@@ -39,4 +39,7 @@ message SessionState {
// Child session ids
repeated int32 child_session_ids = 3;
+
+ // Build fingerprint before reboot
+ string expected_build_fingerprint = 4;
}