diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2022-04-07 22:50:23 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-04-07 22:50:23 +0000 |
commit | 1b92889acfbc85790c35849eed40a33a57fd8c41 (patch) | |
tree | 6dc6111839e0d715d03fbdf8a6d3982923add3b0 | |
parent | cacf53f444b5e19b4f98be3db992648c2488b8e6 (diff) | |
parent | 19785c374cfa67072ab54fa23065e972c8e3afe7 (diff) | |
download | security-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.bp | 1 | ||||
-rw-r--r-- | ondevice-signing/StatsReporter.cpp | 67 | ||||
-rw-r--r-- | ondevice-signing/StatsReporter.h | 44 | ||||
-rw-r--r-- | ondevice-signing/odsign_main.cpp | 25 |
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. |