summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-07-10 12:07:03 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-07-10 12:07:03 +0000
commit5f811d117cd5c5491dbc18e752cc1c21b97d91cf (patch)
treecdf3c0b493cf0ae0636cba27ab6b7ef23ffd4274
parentcf00a632a175c1302083277aeb3a72fbc3b7d562 (diff)
parent193f9f7d4dbdf1099cbef7cff8015ba93c5d3658 (diff)
downloadsecurity-5f811d117cd5c5491dbc18e752cc1c21b97d91cf.tar.gz
Snap for 7538072 from 193f9f7d4dbdf1099cbef7cff8015ba93c5d3658 to mainline-media-swcodec-release
Change-Id: Iabbf078b37d63471f5d603604110524a2f410c2b
-rw-r--r--keystore2/aidl/android/security/metrics/AtomID.aidl1
-rw-r--r--keystore2/aidl/android/security/metrics/CrashStats.aidl23
-rw-r--r--keystore2/aidl/android/security/metrics/KeystoreAtomPayload.aidl2
-rw-r--r--keystore2/src/keystore2_main.rs4
-rw-r--r--keystore2/src/metrics_store.rs69
-rw-r--r--keystore2/system_property/Android.bp1
-rw-r--r--keystore2/system_property/lib.rs26
7 files changed, 124 insertions, 2 deletions
diff --git a/keystore2/aidl/android/security/metrics/AtomID.aidl b/keystore2/aidl/android/security/metrics/AtomID.aidl
index dc3768a2..166e7538 100644
--- a/keystore2/aidl/android/security/metrics/AtomID.aidl
+++ b/keystore2/aidl/android/security/metrics/AtomID.aidl
@@ -31,4 +31,5 @@ enum AtomID {
KEY_OPERATION_WITH_PURPOSE_AND_MODES_INFO = 10122,
KEY_OPERATION_WITH_GENERAL_INFO = 10123,
RKP_ERROR_STATS = 10124,
+ CRASH_STATS = 10125,
} \ No newline at end of file
diff --git a/keystore2/aidl/android/security/metrics/CrashStats.aidl b/keystore2/aidl/android/security/metrics/CrashStats.aidl
new file mode 100644
index 00000000..8ca043bf
--- /dev/null
+++ b/keystore2/aidl/android/security/metrics/CrashStats.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2021, 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.
+ */
+
+package android.security.metrics;
+
+/** @hide */
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+parcelable CrashStats {
+ int count_of_crash_events;
+} \ No newline at end of file
diff --git a/keystore2/aidl/android/security/metrics/KeystoreAtomPayload.aidl b/keystore2/aidl/android/security/metrics/KeystoreAtomPayload.aidl
index b8a3aba3..a3e4dd68 100644
--- a/keystore2/aidl/android/security/metrics/KeystoreAtomPayload.aidl
+++ b/keystore2/aidl/android/security/metrics/KeystoreAtomPayload.aidl
@@ -25,6 +25,7 @@ import android.security.metrics.StorageStats;
import android.security.metrics.Keystore2AtomWithOverflow;
import android.security.metrics.RkpErrorStats;
import android.security.metrics.RkpPoolStats;
+import android.security.metrics.CrashStats;
/** @hide */
@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
@@ -38,4 +39,5 @@ union KeystoreAtomPayload {
KeyOperationWithPurposeAndModesInfo keyOperationWithPurposeAndModesInfo;
KeyOperationWithGeneralInfo keyOperationWithGeneralInfo;
RkpErrorStats rkpErrorStats;
+ CrashStats crashStats;
} \ No newline at end of file
diff --git a/keystore2/src/keystore2_main.rs b/keystore2/src/keystore2_main.rs
index 2c7d4a00..cf2ba043 100644
--- a/keystore2/src/keystore2_main.rs
+++ b/keystore2/src/keystore2_main.rs
@@ -18,6 +18,7 @@ use keystore2::entropy;
use keystore2::globals::ENFORCEMENTS;
use keystore2::maintenance::Maintenance;
use keystore2::metrics::Metrics;
+use keystore2::metrics_store;
use keystore2::remote_provisioning::RemoteProvisioningService;
use keystore2::service::KeystoreService;
use keystore2::{apc::ApcManager, shared_secret_negotiation};
@@ -51,6 +52,9 @@ fn main() {
let mut args = std::env::args();
args.next().expect("That's odd. How is there not even a first argument?");
+ // Write/update keystore.crash_count system property.
+ metrics_store::update_keystore_crash_sysprop();
+
// Keystore 2.0 cannot change to the database directory (typically /data/misc/keystore) on
// startup as Keystore 1.0 did because Keystore 2.0 is intended to run much earlier than
// Keystore 1.0. Instead we set a global variable to the database path.
diff --git a/keystore2/src/metrics_store.rs b/keystore2/src/metrics_store.rs
index 32fe353e..32067b95 100644
--- a/keystore2/src/metrics_store.rs
+++ b/keystore2/src/metrics_store.rs
@@ -29,7 +29,8 @@ use android_hardware_security_keymint::aidl::android::hardware::security::keymin
SecurityLevel::SecurityLevel,
};
use android_security_metrics::aidl::android::security::metrics::{
- Algorithm::Algorithm as MetricsAlgorithm, AtomID::AtomID, EcCurve::EcCurve as MetricsEcCurve,
+ Algorithm::Algorithm as MetricsAlgorithm, AtomID::AtomID, CrashStats::CrashStats,
+ EcCurve::EcCurve as MetricsEcCurve,
HardwareAuthenticatorType::HardwareAuthenticatorType as MetricsHardwareAuthenticatorType,
KeyCreationWithAuthInfo::KeyCreationWithAuthInfo,
KeyCreationWithGeneralInfo::KeyCreationWithGeneralInfo,
@@ -43,12 +44,17 @@ use android_security_metrics::aidl::android::security::metrics::{
RkpPoolStats::RkpPoolStats, SecurityLevel::SecurityLevel as MetricsSecurityLevel,
Storage::Storage as MetricsStorage,
};
-use anyhow::Result;
+use anyhow::{Context, Result};
+use keystore2_system_property::{write, PropertyWatcher, PropertyWatcherError};
use lazy_static::lazy_static;
use std::collections::HashMap;
use std::sync::Mutex;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
+// Note: Crash events are recorded at keystore restarts, based on the assumption that keystore only
+// gets restarted after a crash, during a boot cycle.
+const KEYSTORE_CRASH_COUNT_PROPERTY: &str = "keystore.crash_count";
+
lazy_static! {
/// Singleton for MetricsStore.
pub static ref METRICS_STORE: MetricsStore = Default::default();
@@ -92,6 +98,16 @@ impl MetricsStore {
return pull_attestation_pool_stats();
}
+ // Process keystore crash stats.
+ if AtomID::CRASH_STATS == atom_id {
+ return Ok(vec![KeystoreAtom {
+ payload: KeystoreAtomPayload::CrashStats(CrashStats {
+ count_of_crash_events: read_keystore_crash_count()?,
+ }),
+ ..Default::default()
+ }]);
+ }
+
// It is safe to call unwrap here since the lock can not be poisoned based on its usage
// in this module and the lock is not acquired in the same thread before.
let metrics_store_guard = self.metrics_store.lock().unwrap();
@@ -582,6 +598,55 @@ pub fn log_rkp_error_stats(rkp_error: MetricsRkpError) {
METRICS_STORE.insert_atom(AtomID::RKP_ERROR_STATS, rkp_error_stats);
}
+/// This function tries to read and update the system property: keystore.crash_count.
+/// If the property is absent, it sets the property with value 0. If the property is present, it
+/// increments the value. This helps tracking keystore crashes internally.
+pub fn update_keystore_crash_sysprop() {
+ let crash_count = read_keystore_crash_count();
+ let new_count = match crash_count {
+ Ok(count) => count + 1,
+ Err(error) => {
+ // If the property is absent, this is the first start up during the boot.
+ // Proceed to write the system property with value 0. Otherwise, log and return.
+ if !matches!(
+ error.root_cause().downcast_ref::<PropertyWatcherError>(),
+ Some(PropertyWatcherError::SystemPropertyAbsent)
+ ) {
+ log::warn!(
+ concat!(
+ "In update_keystore_crash_sysprop: ",
+ "Failed to read the existing system property due to: {:?}.",
+ "Therefore, keystore crashes will not be logged."
+ ),
+ error
+ );
+ return;
+ }
+ 0
+ }
+ };
+
+ if let Err(e) = write(KEYSTORE_CRASH_COUNT_PROPERTY, &new_count.to_string()) {
+ log::error!(
+ concat!(
+ "In update_keystore_crash_sysprop:: ",
+ "Failed to write the system property due to error: {:?}"
+ ),
+ e
+ );
+ }
+}
+
+/// Read the system property: keystore.crash_count.
+pub fn read_keystore_crash_count() -> Result<i32> {
+ let mut prop_reader = PropertyWatcher::new("keystore.crash_count").context(concat!(
+ "In read_keystore_crash_count: Failed to create reader a PropertyWatcher."
+ ))?;
+ prop_reader
+ .read(|_n, v| v.parse::<i32>().map_err(std::convert::Into::into))
+ .context("In read_keystore_crash_count: Failed to read the existing system property.")
+}
+
/// Enum defining the bit position for each padding mode. Since padding mode can be repeatable, it
/// is represented using a bitmap.
#[allow(non_camel_case_types)]
diff --git a/keystore2/system_property/Android.bp b/keystore2/system_property/Android.bp
index 9e7b0565..773804d9 100644
--- a/keystore2/system_property/Android.bp
+++ b/keystore2/system_property/Android.bp
@@ -31,6 +31,7 @@ rust_bindgen {
"--size_t-is-usize",
"--allowlist-function=__system_property_find",
"--allowlist-function=__system_property_read_callback",
+ "--allowlist-function=__system_property_set",
"--allowlist-function=__system_property_wait",
],
}
diff --git a/keystore2/system_property/lib.rs b/keystore2/system_property/lib.rs
index be13c886..b993c879 100644
--- a/keystore2/system_property/lib.rs
+++ b/keystore2/system_property/lib.rs
@@ -15,6 +15,7 @@
//! This crate provides the PropertyWatcher type, which watches for changes
//! in Android system properties.
+use anyhow::{anyhow, Context, Result as AnyhowResult};
use keystore2_system_property_bindgen::prop_info as PropInfo;
use std::os::raw::c_char;
use std::ptr::null;
@@ -48,6 +49,9 @@ pub enum PropertyWatcherError {
/// read callback returned an error
#[error("Callback failed")]
CallbackError(#[from] anyhow::Error),
+ /// Failure in setting the system property
+ #[error("__system_property_set failed.")]
+ SetPropertyFailed,
}
/// Result type specific for this crate.
@@ -189,3 +193,25 @@ impl PropertyWatcher {
Ok(())
}
}
+
+/// Writes a system property.
+pub fn write(name: &str, value: &str) -> AnyhowResult<()> {
+ if
+ // Unsafe required for FFI call. Input and output are both const and valid strings.
+ unsafe {
+ // If successful, __system_property_set returns 0, otherwise, returns -1.
+ keystore2_system_property_bindgen::__system_property_set(
+ CString::new(name)
+ .context("In keystore2::system_property::write: Construction CString from name.")?
+ .as_ptr(),
+ CString::new(value)
+ .context("In keystore2::system_property::write: Constructing CString from value.")?
+ .as_ptr(),
+ )
+ } == 0
+ {
+ Ok(())
+ } else {
+ Err(anyhow!(PropertyWatcherError::SetPropertyFailed))
+ }
+}