diff options
author | Rajesh Nyamagoud <nyamagoud@google.com> | 2022-07-29 00:33:48 +0000 |
---|---|---|
committer | Rajesh Nyamagoud <nyamagoud@google.com> | 2022-08-31 18:27:03 +0000 |
commit | 01d4cde74ac734b1e7d527f9c30bba82bbc0a7e4 (patch) | |
tree | 048d572222550631b9a4826d2b96e0724845d5cb /keystore2/tests | |
parent | 6ec53e3489dc7a24b72c5fadeaad60a6c04610d4 (diff) | |
download | security-01d4cde74ac734b1e7d527f9c30bba82bbc0a7e4.tar.gz |
Adding a test to simulate `OPERATION_BUSY` error from keystore.
The test tries to create a race condition: It creates an operation
and starts two threads, each trying to use the operation repeatedly
until it gets `OPERATION_BUSY` or finishes successfully.
Bug: 194359114
Test: atest keystore2_client_test
Change-Id: Ib3549d6bcad4e24bf621960f0f399481bf2da7c7
Diffstat (limited to 'keystore2/tests')
-rw-r--r-- | keystore2/tests/keystore2_client_operation_tests.rs | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/keystore2/tests/keystore2_client_operation_tests.rs b/keystore2/tests/keystore2_client_operation_tests.rs index d8b85f6f..e1102ddc 100644 --- a/keystore2/tests/keystore2_client_operation_tests.rs +++ b/keystore2/tests/keystore2_client_operation_tests.rs @@ -14,12 +14,15 @@ use nix::unistd::{getuid, Gid, Uid}; use rustutils::users::AID_USER_OFFSET; +use std::thread; +use std::thread::JoinHandle; use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{ Digest::Digest, ErrorCode::ErrorCode, KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel, }; use android_system_keystore2::aidl::android::system::keystore2::{ - CreateOperationResponse::CreateOperationResponse, Domain::Domain, ResponseCode::ResponseCode, + CreateOperationResponse::CreateOperationResponse, Domain::Domain, + IKeystoreOperation::IKeystoreOperation, ResponseCode::ResponseCode, }; use keystore2_test_utils::{ @@ -57,6 +60,25 @@ pub fn create_operations( .collect() } +/// Executes an operation in a thread. Expect an `OPERATION_BUSY` error in case of operation +/// failure. Returns True if `OPERATION_BUSY` error is encountered otherwise returns false. +fn perform_op_busy_in_thread(op: binder::Strong<dyn IKeystoreOperation>) -> JoinHandle<bool> { + thread::spawn(move || { + for _n in 1..1000 { + match key_generations::map_ks_error(op.update(b"my message")) { + Ok(_) => continue, + Err(e) => { + assert_eq!(Error::Rc(ResponseCode::OPERATION_BUSY), e); + return true; + } + } + } + let sig = op.finish(None, None).unwrap(); + assert!(sig.is_some()); + false + }) +} + /// This test verifies that backend service throws BACKEND_BUSY error when all /// operations slots are full. This test creates operations in child processes and /// collects the status of operations performed in each child proc and determines @@ -402,3 +424,29 @@ fn keystore2_forced_op_success_test() { }); } } + +/// Create an operation and try to use this operation handle in multiple threads to perform +/// operations. Test should fail to perform an operation with an error response `OPERATION_BUSY` +/// when multiple threads try to access the operation handle at same time. +#[test] +fn keystore2_op_fails_operation_busy() { + let op_response = create_signing_operation( + ForcedOp(false), + KeyPurpose::SIGN, + Digest::SHA_2_256, + Domain::APP, + -1, + Some("op_busy_alias_test_key".to_string()), + ) + .unwrap(); + + let op: binder::Strong<dyn IKeystoreOperation> = op_response.iOperation.unwrap(); + + let th_handle_1 = perform_op_busy_in_thread(op.clone()); + let th_handle_2 = perform_op_busy_in_thread(op); + + let result1 = th_handle_1.join().unwrap(); + let result2 = th_handle_2.join().unwrap(); + + assert!(result1 || result2); +} |