summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2022-04-07 22:50:23 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-04-07 22:50:23 +0000
commit1b92889acfbc85790c35849eed40a33a57fd8c41 (patch)
tree6dc6111839e0d715d03fbdf8a6d3982923add3b0
parentcacf53f444b5e19b4f98be3db992648c2488b8e6 (diff)
parent19785c374cfa67072ab54fa23065e972c8e3afe7 (diff)
downloadsecurity-1b92889acfbc85790c35849eed40a33a57fd8c41.tar.gz
Merge "[Odsign] Record compos artifacts related metrics" am: c3ab4bf4cf am: 1acbe31d32 am: 19785c374c
Original change: https://android-review.googlesource.com/c/platform/system/security/+/2020058 Change-Id: I2680ab33d0923ed9d176f1d8a976ad3a17c066f4 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--ondevice-signing/Android.bp1
-rw-r--r--ondevice-signing/StatsReporter.cpp67
-rw-r--r--ondevice-signing/StatsReporter.h44
-rw-r--r--ondevice-signing/odsign_main.cpp25
4 files changed, 134 insertions, 3 deletions
diff --git a/ondevice-signing/Android.bp b/ondevice-signing/Android.bp
index bdc94b7e..d73f8fe5 100644
--- a/ondevice-signing/Android.bp
+++ b/ondevice-signing/Android.bp
@@ -112,6 +112,7 @@ cc_binary {
"KeystoreKey.cpp",
"KeystoreHmacKey.cpp",
"odsign_main.cpp",
+ "StatsReporter.cpp",
],
header_libs: ["odrefresh_headers"],
diff --git a/ondevice-signing/StatsReporter.cpp b/ondevice-signing/StatsReporter.cpp
new file mode 100644
index 00000000..65e645a3
--- /dev/null
+++ b/ondevice-signing/StatsReporter.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include "StatsReporter.h"
+#include <android-base/logging.h>
+#include <stdlib.h>
+#include <string>
+#include <sys/stat.h>
+
+// Keep these constant in sync with COMPOS_METRIC_NAME & METRICS_FILE in OdsignStatsLogger.java.
+constexpr const char* kOdsignMetricsFile = "/data/misc/odsign/metrics/odsign-metrics.txt";
+constexpr const char* kComposMetricName = "comp_os_artifacts_check_record";
+
+StatsReporter::~StatsReporter() {
+ if (comp_os_artifacts_check_record_ == nullptr) {
+ LOG(INFO) << "Metrics report is empty";
+
+ // Remove the metrics file if any old version of the file already exists
+ if (std::filesystem::remove(kOdsignMetricsFile) != 0 &&
+ !((errno = ENOENT) || errno == ENOTDIR)) {
+ PLOG(ERROR) << "Could not remove already present file";
+ }
+ return;
+ }
+
+ std::ofstream odsign_metrics_file_;
+ odsign_metrics_file_.open(kOdsignMetricsFile, std::ios::trunc);
+ if (!odsign_metrics_file_) {
+ PLOG(ERROR) << "Could not open file: " << kOdsignMetricsFile;
+ return;
+ }
+
+ odsign_metrics_file_ << kComposMetricName << ' ';
+ odsign_metrics_file_ << comp_os_artifacts_check_record_->current_artifacts_ok << ' ';
+ odsign_metrics_file_ << comp_os_artifacts_check_record_->comp_os_pending_artifacts_exists
+ << ' ';
+ odsign_metrics_file_ << comp_os_artifacts_check_record_->use_comp_os_generated_artifacts
+ << '\n';
+ if (chmod(kOdsignMetricsFile, 0644) != 0) {
+ PLOG(ERROR) << "Could not set correct file permissions for " << kOdsignMetricsFile;
+ return;
+ }
+ odsign_metrics_file_.close();
+ if (!odsign_metrics_file_) {
+ PLOG(ERROR) << "Failed to close the file";
+ }
+}
+
+StatsReporter::CompOsArtifactsCheckRecord* StatsReporter::GetComposArtifactsCheckRecord() {
+ if (comp_os_artifacts_check_record_ == nullptr) {
+ comp_os_artifacts_check_record_ = std::make_unique<CompOsArtifactsCheckRecord>();
+ }
+ return comp_os_artifacts_check_record_.get();
+}
diff --git a/ondevice-signing/StatsReporter.h b/ondevice-signing/StatsReporter.h
new file mode 100644
index 00000000..2682b963
--- /dev/null
+++ b/ondevice-signing/StatsReporter.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#pragma once
+
+#include <fstream>
+
+// Class to store CompOsArtifactsCheck related metrics.
+// These are flushed to a file kOdsignMetricsFile and consumed by
+// System Server (in class OdsignStatsLogger) & sent to statsd.
+class StatsReporter {
+ public:
+ // Keep sync with EarlyBootCompOsArtifactsCheckReported
+ // definition in proto_logging/stats/atoms.proto.
+ struct CompOsArtifactsCheckRecord {
+ bool current_artifacts_ok = false;
+ bool comp_os_pending_artifacts_exists = false;
+ bool use_comp_os_generated_artifacts = false;
+ };
+
+ // The report is flushed (from buffer) into a file by the destructor.
+ ~StatsReporter();
+
+ // Get pointer to comp_os_artifacts_check_record, caller can then modify it.
+ // Note: pointer remains valid for the lifetime of this StatsReporter.
+ CompOsArtifactsCheckRecord* GetComposArtifactsCheckRecord();
+
+ private:
+ // Temporary buffer which stores the metrics.
+ std::unique_ptr<CompOsArtifactsCheckRecord> comp_os_artifacts_check_record_;
+};
diff --git a/ondevice-signing/odsign_main.cpp b/ondevice-signing/odsign_main.cpp
index fc558462..04679a59 100644
--- a/ondevice-signing/odsign_main.cpp
+++ b/ondevice-signing/odsign_main.cpp
@@ -33,6 +33,7 @@
#include "CertUtils.h"
#include "KeystoreKey.h"
+#include "StatsReporter.h"
#include "VerityUtils.h"
#include "odsign_info.pb.h"
@@ -365,19 +366,26 @@ Result<OdsignInfo> getComposInfo() {
return compos_info;
}
-art::odrefresh::ExitCode checkCompOsPendingArtifacts(const SigningKey& signing_key,
- bool* digests_verified) {
+art::odrefresh::ExitCode CheckCompOsPendingArtifacts(const SigningKey& signing_key,
+ bool* digests_verified,
+ StatsReporter* stats_reporter) {
+ StatsReporter::CompOsArtifactsCheckRecord* compos_check_record =
+ stats_reporter->GetComposArtifactsCheckRecord();
+
if (!directoryHasContent(kCompOsPendingArtifactsDir)) {
// No pending CompOS artifacts, all that matters is the current ones.
return checkArtifacts();
}
+ compos_check_record->comp_os_pending_artifacts_exists = true;
+
// CompOS has generated some artifacts that may, or may not, match the
// current state. But if there are already valid artifacts present the
// CompOS ones are redundant.
art::odrefresh::ExitCode odrefresh_status = checkArtifacts();
if (odrefresh_status != art::odrefresh::ExitCode::kCompilationRequired) {
if (odrefresh_status == art::odrefresh::ExitCode::kOkay) {
+ compos_check_record->current_artifacts_ok = true;
LOG(INFO) << "Current artifacts are OK, deleting pending artifacts";
removeDirectory(kCompOsPendingArtifactsDir);
}
@@ -432,6 +440,7 @@ art::odrefresh::ExitCode checkCompOsPendingArtifacts(const SigningKey& signing_k
// are pretty bad.
return art::odrefresh::ExitCode::kCleanupFailed;
}
+ compos_check_record->use_comp_os_generated_artifacts = true;
LOG(INFO) << "Persisted CompOS digests.";
*digests_verified = true;
return odrefresh_status;
@@ -455,6 +464,9 @@ art::odrefresh::ExitCode checkCompOsPendingArtifacts(const SigningKey& signing_k
} // namespace
int main(int /* argc */, char** argv) {
+ // stats_reporter is a pointer so that we can explicitly delete it
+ // instead of waiting for the program to die & its destrcutor be called
+ auto stats_reporter = std::make_unique<StatsReporter>();
android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
auto errorScopeGuard = []() {
@@ -516,7 +528,14 @@ int main(int /* argc */, char** argv) {
bool digests_verified = false;
art::odrefresh::ExitCode odrefresh_status =
- useCompOs ? checkCompOsPendingArtifacts(*key, &digests_verified) : checkArtifacts();
+ useCompOs ? CheckCompOsPendingArtifacts(*key, &digests_verified, stats_reporter.get())
+ : checkArtifacts();
+
+ // Explicitly reset the pointer - We rely on stats_reporter's
+ // destructor for actually writing the buffered metrics. This will otherwise not be called
+ // if the program doesn't exit normally (for ex, killed by init, which actually happens
+ // because odsign (after it finishes) sets kStopServiceProp instructing init to kill it).
+ stats_reporter.reset();
// The artifacts dir doesn't necessarily need to exist; if the existing
// artifacts on the system partition are valid, those can be used.