From 948dda363bc562619d2b30ec0a6bd9c4e87e1192 Mon Sep 17 00:00:00 2001 From: Moksh Goyal <221651574+MokshonWork@users.noreply.github.com> Date: Thu, 25 Jun 2026 18:27:26 +0530 Subject: [PATCH] Refactor garbage collection to prevent premature pruning and panic vulnerabilities Signed-off-by: Moksh Goyal <221651574+MokshonWork@users.noreply.github.com> --- lore-storage/src/maintenance.rs | 14 +++++++++++--- lore/src/repository.rs | 7 ++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lore-storage/src/maintenance.rs b/lore-storage/src/maintenance.rs index c8895d8..6a109b4 100644 --- a/lore-storage/src/maintenance.rs +++ b/lore-storage/src/maintenance.rs @@ -122,7 +122,8 @@ pub async fn gc( max_capacity: usize, sync_data: bool, sink: Option, -) { + grace_period: Option, +) -> Result<(), crate::gc::GcError> { let mut at = store.clone().compact_resume_at().await; if max_size > 0 { @@ -146,7 +147,7 @@ pub async fn gc( } Err(err) => { lore_base::lore_warn!("Store compactor failed: {err}"); - break; + return Err(crate::gc::GcError::CompactionFailed(err.to_string())); } } } @@ -154,9 +155,16 @@ pub async fn gc( } if max_capacity > 0 { - let _ = store.evict(max_capacity, sync_data, sink).await; + // Enforce staging leases and grace period timestamp checking for atomic rollbacks + let _transaction = crate::gc_lease::acquire_exclusive_sweep() + .map_err(|e| crate::gc::GcError::LeaseDenied(e.to_string()))?; + + store.evict_with_grace(max_capacity, sync_data, sink, grace_period).await + .map_err(|e| crate::gc::GcError::EvictionFailed(e.to_string()))?; lore_base::lore_debug!("Store evictor done"); } + + Ok(()) } /// Per-store running totals, collected purely as a byproduct of LOADING data from diff --git a/lore/src/repository.rs b/lore/src/repository.rs index ce22935..0e27e10 100644 --- a/lore/src/repository.rs +++ b/lore/src/repository.rs @@ -707,7 +707,12 @@ async fn flush_local( #[repr(C)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, LoreArgs)] #[handler(gc_local)] -pub struct LoreRepositoryGcArgs {} +pub struct LoreRepositoryGcArgs { + /// Grace period (in seconds) to spare newly created fragments from premature pruning + pub grace_period_sec: u64, + /// Minimum size threshold (in bytes) to trigger pruning + pub prune_threshold: u64, +} /// Runs garbage collection on the local repository store to reclaim space from unreferenced data. ///