diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-10 12:07:03 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-10 12:07:03 +0000 |
commit | 5f811d117cd5c5491dbc18e752cc1c21b97d91cf (patch) | |
tree | cdf3c0b493cf0ae0636cba27ab6b7ef23ffd4274 | |
parent | cf00a632a175c1302083277aeb3a72fbc3b7d562 (diff) | |
parent | 193f9f7d4dbdf1099cbef7cff8015ba93c5d3658 (diff) | |
download | security-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.aidl | 1 | ||||
-rw-r--r-- | keystore2/aidl/android/security/metrics/CrashStats.aidl | 23 | ||||
-rw-r--r-- | keystore2/aidl/android/security/metrics/KeystoreAtomPayload.aidl | 2 | ||||
-rw-r--r-- | keystore2/src/keystore2_main.rs | 4 | ||||
-rw-r--r-- | keystore2/src/metrics_store.rs | 69 | ||||
-rw-r--r-- | keystore2/system_property/Android.bp | 1 | ||||
-rw-r--r-- | keystore2/system_property/lib.rs | 26 |
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)) + } +} |