From: Victor Julien Date: Thu, 24 Oct 2024 12:18:48 +0000 (+0200) Subject: smb: use lru for ssn2vecoffset_map; rename X-Git-Tag: suricata-8.0.0-beta1~720 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ce44d38ca86521cda5b85e033be7ba35f1ec02ad;p=thirdparty%2Fsuricata.git smb: use lru for ssn2vecoffset_map; rename Rename to read_offset_cache. Add `app-layer.protocols.smb.max-read-offset-cache-size` option to control the limit. Ticket: #5672. --- diff --git a/rust/src/smb/debug.rs b/rust/src/smb/debug.rs index f87180b6a8..e945de286e 100644 --- a/rust/src/smb/debug.rs +++ b/rust/src/smb/debug.rs @@ -69,10 +69,10 @@ impl SMBState { #[cfg(feature = "debug")] pub fn _debug_state_stats(&self) { - SCLogDebug!("ssn2vec_map {} guid2name_cache {} ssn2vecoffset_map {} ssn2tree_map {} ssnguid2vec_map {} file_ts_guid {} file_tc_guid {} transactions {}", + SCLogDebug!("ssn2vec_map {} guid2name_cache {} read_offset_cache {} ssn2tree_map {} ssnguid2vec_map {} file_ts_guid {} file_tc_guid {} transactions {}", self.ssn2vec_map.len(), self.guid2name_cache.len(), - self.ssn2vecoffset_map.len(), + self.read_offset_cache.len(), self.ssn2tree_map.len(), self.ssnguid2vec_map.len(), self.file_ts_guid.len(), diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index e69399c718..3ef84a3552 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -84,6 +84,8 @@ pub static mut SMB_CFG_MAX_WRITE_QUEUE_SIZE: u32 = 67108864; pub static mut SMB_CFG_MAX_WRITE_QUEUE_CNT: u32 = 64; /// max size of the per state guid2name cache pub static mut SMB_CFG_MAX_GUID_CACHE_SIZE: usize = 1024; +/// SMBState::read_offset_cache +pub static mut SMB_CFG_MAX_READ_OFFSET_CACHE_SIZE: usize = 128; static mut ALPROTO_SMB: AppProto = ALPROTO_UNKNOWN; @@ -704,7 +706,7 @@ pub struct SMBState<> { pub guid2name_cache: LruCache, Vec>, /// map ssn key to read offset - pub ssn2vecoffset_map: HashMap, + pub read_offset_cache: LruCache, pub ssn2tree_map: HashMap, @@ -781,7 +783,7 @@ impl SMBState { state_data:AppLayerStateData::new(), ssn2vec_map:HashMap::new(), guid2name_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_GUID_CACHE_SIZE }).unwrap()), - ssn2vecoffset_map:HashMap::new(), + read_offset_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_READ_OFFSET_CACHE_SIZE }).unwrap()), ssn2tree_map:HashMap::new(), ssnguid2vec_map:HashMap::new(), skip_ts:0, @@ -2455,6 +2457,18 @@ pub unsafe extern "C" fn rs_smb_register_parser() { SCLogError!("Invalid max-guid-cache-size value"); } } + let retval = conf_get("app-layer.protocols.smb.max-read-offset-cache-size"); + if let Some(val) = retval { + if let Ok(v) = val.parse::() { + if v > 0 { + SMB_CFG_MAX_READ_OFFSET_CACHE_SIZE = v; + } else { + SCLogError!("Invalid max-read-offset-cache-size value"); + } + } else { + SCLogError!("Invalid max-read-offset-cache-size value"); + } + } SCLogConfig!("read: max record size: {}, max queued chunks {}, max queued size {}", SMB_CFG_MAX_READ_SIZE, SMB_CFG_MAX_READ_QUEUE_CNT, SMB_CFG_MAX_READ_QUEUE_SIZE); SCLogConfig!("write: max record size: {}, max queued chunks {}, max queued size {}", diff --git a/rust/src/smb/smb1.rs b/rust/src/smb/smb1.rs index 731bedeb33..cce552de91 100644 --- a/rust/src/smb/smb1.rs +++ b/rust/src/smb/smb1.rs @@ -406,7 +406,7 @@ fn smb1_request_record_one(state: &mut SMBState, r: &SmbRecord, command: u8, and let mut fid = rr.fid.to_vec(); fid.extend_from_slice(&u32_as_bytes(r.ssn_id)); let fidoff = SMBFileGUIDOffset::new(fid, rr.offset); - state.ssn2vecoffset_map.insert(fid_key, fidoff); + state.read_offset_cache.put(fid_key, fidoff); }, _ => { events.push(SMBEvent::MalformedData); @@ -1038,7 +1038,7 @@ pub fn smb1_read_response_record(state: &mut SMBState, r: &SmbRecord, andx_offse return; } let fid_key = SMBCommonHdr::from1(r, SMBHDR_TYPE_OFFSET); - let (offset, file_fid) = match state.ssn2vecoffset_map.remove(&fid_key) { + let (offset, file_fid) = match state.read_offset_cache.pop(&fid_key) { Some(o) => (o.offset, o.guid), None => { SCLogDebug!("SMBv1 READ response: reply to unknown request: left {} {:?}", diff --git a/rust/src/smb/smb2.rs b/rust/src/smb/smb2.rs index f6c0d924f4..17603202aa 100644 --- a/rust/src/smb/smb2.rs +++ b/rust/src/smb/smb2.rs @@ -152,7 +152,7 @@ pub fn smb2_read_response_record(state: &mut SMBState, r: &Smb2Record, nbss_rema // get the request info. If we don't have it, there is nothing // we can do except skip this record. let guid_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_OFFSET); - let (offset, file_guid) = match state.ssn2vecoffset_map.remove(&guid_key) { + let (offset, file_guid) = match state.read_offset_cache.pop(&guid_key) { Some(o) => (o.offset, o.guid), None => { SCLogDebug!("SMBv2 READ response: reply to unknown request {:?}",rd); @@ -544,7 +544,7 @@ pub fn smb2_request_record(state: &mut SMBState, r: &Smb2Record) // store read guid,offset in map let guid_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_OFFSET); let guidoff = SMBFileGUIDOffset::new(rd.guid.to_vec(), rd.rd_offset); - state.ssn2vecoffset_map.insert(guid_key, guidoff); + state.read_offset_cache.put(guid_key, guidoff); } } else { events.push(SMBEvent::MalformedData); @@ -667,7 +667,7 @@ pub fn smb2_response_record(state: &mut SMBState, r: &Smb2Record) SCLogDebug!("SMBv2: read response => EOF"); let guid_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_OFFSET); - let file_guid = if let Some(o) = state.ssn2vecoffset_map.remove(&guid_key) { + let file_guid = if let Some(o) = state.read_offset_cache.pop(&guid_key) { o.guid } else { SCLogDebug!("SMBv2 READ response: reply to unknown request");