diff --git a/attestation_agent/agent_restful/src/get_evidence_controller.rs b/attestation_agent/agent_restful/src/get_evidence_controller.rs index 9f964593818a04d65ba9094b8b953fd4b26a7531..fbb52d0f4d627a4351fbcce06bba733af904bd05 100644 --- a/attestation_agent/agent_restful/src/get_evidence_controller.rs +++ b/attestation_agent/agent_restful/src/get_evidence_controller.rs @@ -15,7 +15,6 @@ use log::info; use serde_json::Value; use crate::response_error::create_error_response; use challenge::evidence::{EvidenceManager, GetEvidenceRequest}; - use std::thread; /// Main entry point for evidence collection requests diff --git a/attestation_agent/challenge/Cargo.toml b/attestation_agent/challenge/Cargo.toml index 379753fada07f1b96f61de0fbd31f8b85f4c57a6..597b4fc7059591e2038bf8bbc59d9428682c1f09 100644 --- a/attestation_agent/challenge/Cargo.toml +++ b/attestation_agent/challenge/Cargo.toml @@ -4,13 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -libc = "0.2" -tokio.workspace = true +parking_lot.workspace = true once_cell.workspace = true -futures.workspace = true log.workspace = true serde_json.workspace = true -lazy_static.workspace = true base64.workspace = true serde = { workspace = true, features = ["derive"] } reqwest = { workspace = true, features = ["json"] } diff --git a/attestation_agent/challenge/src/challenge.rs b/attestation_agent/challenge/src/challenge.rs index 64bbbae9da0d91978ce9111fd3e4be5c085e95ec..4f56a9df9941c33e9c8422235ecd9cce349aab05 100644 --- a/attestation_agent/challenge/src/challenge.rs +++ b/attestation_agent/challenge/src/challenge.rs @@ -12,17 +12,17 @@ use serde::{Deserialize, Serialize}; use crate::challenge_error::ChallengeError; -use crate::acquire_process_lock; use log; use config::{AGENT_CONFIG, PluginConfig}; use plugin_manager::{PluginManagerInstance, AgentPlugin, AgentHostFunctions, PluginManager}; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex as StdMutex}; use reqwest::Method; use agent_utils::Client; use serde_json::Value; use once_cell::sync::Lazy; use base64::engine::general_purpose::STANDARD; use base64::Engine; +use parking_lot::{Mutex, MutexGuard}; #[derive(Debug, Clone)] pub struct NodeToken { @@ -30,8 +30,10 @@ pub struct NodeToken { token: Value, } +static GLOBAL_TPM: Lazy> = Lazy::new(|| Mutex::new(())); + // Global cached tokens for reuse between requests (sync Mutex) -pub static GLOBAL_TOKENS: Lazy>> = Lazy::new(|| Mutex::new(Vec::new())); +pub static GLOBAL_TOKENS: Lazy>> = Lazy::new(|| StdMutex::new(Vec::new())); #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] /// Information about an attester, including type and policy IDs @@ -98,6 +100,12 @@ impl GetEvidenceResponse { } } +/// Acquire a global thread lock to protect TPM access, with 120s timeout +fn acquire_thread_lock() -> Result, ChallengeError> { + GLOBAL_TPM.try_lock_for(std::time::Duration::from_secs(120)) + .ok_or_else(|| ChallengeError::InternalError("TPM mutex lock acquire timeout".to_string())) +} + /// Set the global cached tokens (async) pub fn set_cached_tokens(tokens: &[NodeToken]) { let mut global = GLOBAL_TOKENS.lock().unwrap(); @@ -228,7 +236,8 @@ fn collect_evidence( }) }).transpose()?; - let _tpm_lock = acquire_process_lock()?; + let _lock_guard = acquire_thread_lock()?; + match plugin.collect_evidence(Some(&node_id), nonce_bytes.as_deref()) { Ok(evidence_value) => { log::info!("Evidence collected for attester_type: {}", attester_type); diff --git a/attestation_agent/challenge/src/lib.rs b/attestation_agent/challenge/src/lib.rs index b7fcec681f1a1accf1f1724be0d9b8a9b221781d..fac415c2fa849bf986f13b215b78c7c4f6c61765 100644 --- a/attestation_agent/challenge/src/lib.rs +++ b/attestation_agent/challenge/src/lib.rs @@ -14,8 +14,6 @@ pub mod challenge; pub mod challenge_error; pub mod token; pub mod evidence; -pub mod process_lock; pub use challenge::{AttesterInfo, do_challenge, get_cached_token_for_current_node, set_cached_tokens}; -pub use challenge_error::ChallengeError; -pub use process_lock::platform::acquire_process_lock; \ No newline at end of file +pub use challenge_error::ChallengeError; \ No newline at end of file diff --git a/attestation_agent/challenge/src/process_lock.rs b/attestation_agent/challenge/src/process_lock.rs deleted file mode 100644 index e344973358f005af9fb568e3dfeb94d7f1925943..0000000000000000000000000000000000000000 --- a/attestation_agent/challenge/src/process_lock.rs +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * Global Trust Authority is licensed under the Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - * PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -// Cross-platform process lock trait and Linux implementation (POSIX semaphore). To extend for Windows, add implementation in this file. -use std::time::Duration; -use crate::challenge_error::ChallengeError; - -/// Process lock guard trait -pub trait LockGuard {} - -/// Cross-platform process lock trait -pub trait TpmLock: Send + Sync { - fn acquire(&self, timeout: Duration) -> Result, ChallengeError>; -} - -// ===== Linux implementation ===== -#[cfg(target_os = "linux")] -pub mod platform { - use super::*; - use std::ffi::CString; - use std::os::raw::c_uint; - use std::sync::Arc; - use std::time::{Duration, Instant}; - use std::thread::sleep; - use libc::{sem_t, sem_open, sem_trywait, sem_post, O_CREAT, O_RDWR, S_IRUSR, S_IWUSR, SEM_FAILED}; - use std::sync::Mutex; - - struct SemPtr(*mut sem_t); - unsafe impl Send for SemPtr {} - unsafe impl Sync for SemPtr {} - pub struct GlibcSemaphoreLock { - sem: Arc>, - name: CString, - } - pub struct GlibcSemaphoreGuard { - sem: Arc>, - name: CString, - } - - impl LockGuard for GlibcSemaphoreGuard {} - - impl Drop for GlibcSemaphoreGuard { - fn drop(&mut self) { - let sem = self.sem.lock().unwrap(); - unsafe { - if sem_post(sem.0) != 0 { - log::warn!("Failed to post semaphore in Drop"); - } - } - } - } - - impl GlibcSemaphoreLock { - pub fn new() -> Result { - let c_name = CString::new("/tpm_lock").unwrap(); - let sem = unsafe { - sem_open( - c_name.as_ptr(), - O_CREAT | O_RDWR, - S_IRUSR | S_IWUSR, - 1 as c_uint, - ) - }; - if sem == SEM_FAILED { - log::error!("Failed to open POSIX semaphore"); - return Err(ChallengeError::InternalError("Failed to open POSIX semaphore".to_string())); - } - Ok(Self { sem: Arc::new(Mutex::new(SemPtr(sem))), name: c_name }) - } - } - - impl TpmLock for GlibcSemaphoreLock { - fn acquire(&self, timeout: Duration) -> Result, ChallengeError> { - let start = Instant::now(); - while start.elapsed() < timeout { - let sem = self.sem.lock().unwrap(); - let ret = unsafe { sem_trywait(sem.0) }; - drop(sem); - if ret == 0 { - return Ok(Box::new(GlibcSemaphoreGuard { - sem: Arc::clone(&self.sem), - name: self.name.clone(), - })); - } else { - sleep(Duration::from_millis(50)); - } - } - - log::error!("TPM semaphore lock acquire timeout"); - Err(ChallengeError::InternalError("TPM semaphore lock acquire timeout".to_string())) - } - } - - pub fn acquire_process_lock() -> Result, ChallengeError> { - GlibcSemaphoreLock::new()?.acquire(Duration::from_secs(120)) - } -} - -// ===== Other platforms stub ===== -#[cfg(not(target_os = "linux"))] -pub mod platform { - use super::*; - pub fn acquire_process_lock() -> Result, ChallengeError> { - log::error!("acquire_process_lock is only supported on Linux platform, not implemented on other platforms!"); - Err(ChallengeError::InternalError("acquire_process_lock is only supported on Linux platform, not implemented on other platforms!".to_string())) - } -} \ No newline at end of file