]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb: use lru for ssnguid2vec_map; rename
authorVictor Julien <vjulien@oisf.net>
Thu, 24 Oct 2024 13:13:40 +0000 (15:13 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 6 Nov 2024 20:33:33 +0000 (21:33 +0100)
Reimplement the ssnguid2vec_map HashMap as a LruCache.

Since this is a DCERPC record cache, name it as such.

Default size is 128. Can be controlled by
`app-layer.protocols.smb.max-dcerpc-frag-cache-size`.

Ticket: #5672.

rust/src/smb/dcerpc.rs
rust/src/smb/debug.rs
rust/src/smb/smb.rs
rust/src/smb/smb1.rs

index de6b8def73b3742f769fa2bd167428b26cf33ce9..771e2538c2ac427f2042f2f57a7215c479e1a365 100644 (file)
@@ -455,7 +455,7 @@ pub fn smb_read_dcerpc_record(state: &mut SMBState,
     // msg_id 0 as this data crosses cmd/reply pairs
     let ehdr = SMBHashKeyHdrGuid::new(SMBCommonHdr::new(SMBHDR_TYPE_TRANS_FRAG,
             hdr.ssn_id, hdr.tree_id, 0_u64), guid.to_vec());
-    let mut prevdata = state.ssnguid2vec_map.remove(&ehdr).unwrap_or_default();
+    let mut prevdata = state.dcerpc_rec_frag_cache.pop(&ehdr).unwrap_or_default();
     SCLogDebug!("indata {} prevdata {}", indata.len(), prevdata.len());
     prevdata.extend_from_slice(indata);
     let data = prevdata;
@@ -476,7 +476,7 @@ pub fn smb_read_dcerpc_record(state: &mut SMBState,
                 if ntstatus == SMB_NTSTATUS_BUFFER_OVERFLOW && data.len() < dcer.frag_len as usize {
                     SCLogDebug!("short record {} < {}: storing partial data in state",
                             data.len(), dcer.frag_len);
-                    state.ssnguid2vec_map.insert(ehdr, data.to_vec());
+                    state.dcerpc_rec_frag_cache.put(ehdr, data.to_vec());
                     return true; // TODO review
                 }
 
index d4b28cb232c2cc75eb4568759c204492b923f575..f2c3d9a7a393d36df0037e11a21b7b1064bc1a1a 100644 (file)
@@ -69,12 +69,12 @@ impl SMBState {
 
     #[cfg(feature = "debug")]
     pub fn _debug_state_stats(&self) {
-        SCLogDebug!("ssn2vec_map {} guid2name_cache {} read_offset_cache {} ssn2tree_cache {} ssnguid2vec_map {} file_ts_guid {} file_tc_guid {} transactions {}",
+        SCLogDebug!("ssn2vec_map {} guid2name_cache {} read_offset_cache {} ssn2tree_cache {} dcerpc_rec_frag_cache {} file_ts_guid {} file_tc_guid {} transactions {}",
             self.ssn2vec_map.len(),
             self.guid2name_cache.len(),
             self.read_offset_cache.len(),
             self.ssn2tree_cache.len(),
-            self.ssnguid2vec_map.len(),
+            self.dcerpc_rec_frag_cache.len(),
             self.file_ts_guid.len(),
             self.file_tc_guid.len(),
             self.transactions.len());
index d195001daa6f658529ad0f6e99b9806183a06aa5..004bff9f2fae93aa9abe926d23689bf81bffbe00 100644 (file)
@@ -88,6 +88,8 @@ pub static mut SMB_CFG_MAX_GUID_CACHE_SIZE: usize = 1024;
 pub static mut SMB_CFG_MAX_READ_OFFSET_CACHE_SIZE: usize = 128;
 /// For SMBState::ssn2tree_cache
 pub static mut SMB_CFG_MAX_TREE_CACHE_SIZE: usize = 512;
+/// For SMBState::dcerpc_rec_frag_cache
+pub static mut SMB_CFG_MAX_FRAG_CACHE_SIZE: usize = 128;
 
 static mut ALPROTO_SMB: AppProto = ALPROTO_UNKNOWN;
 
@@ -712,9 +714,9 @@ pub struct SMBState<> {
     /// Map session key to SMBTree
     pub ssn2tree_cache: LruCache<SMBCommonHdr, SMBTree>,
 
-    // store partial data records that are transferred in multiple
-    // requests for DCERPC.
-    pub ssnguid2vec_map: HashMap<SMBHashKeyHdrGuid, Vec<u8>>,
+    /// store partial data records that are transferred in multiple
+    /// requests for DCERPC.
+    pub dcerpc_rec_frag_cache: LruCache<SMBHashKeyHdrGuid, Vec<u8>>,
 
     skip_ts: u32,
     skip_tc: u32,
@@ -787,7 +789,7 @@ impl SMBState {
             guid2name_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_GUID_CACHE_SIZE }).unwrap()),
             read_offset_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_READ_OFFSET_CACHE_SIZE }).unwrap()),
             ssn2tree_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_TREE_CACHE_SIZE }).unwrap()),
-            ssnguid2vec_map:HashMap::new(),
+            dcerpc_rec_frag_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_FRAG_CACHE_SIZE }).unwrap()),
             skip_ts:0,
             skip_tc:0,
             file_ts_left:0,
@@ -2483,6 +2485,18 @@ pub unsafe extern "C" fn rs_smb_register_parser() {
                 SCLogError!("Invalid max-tree-cache-size value");
             }
         }
+        let retval = conf_get("app-layer.protocols.smb.max-dcerpc-frag-cache-size");
+        if let Some(val) = retval {
+            if let Ok(v) = val.parse::<usize>() {
+                if v > 0 {
+                    SMB_CFG_MAX_FRAG_CACHE_SIZE = v;
+                } else {
+                    SCLogError!("Invalid max-dcerpc-frag-cache-size value");
+                }
+            } else {
+                SCLogError!("Invalid max-dcerpc-frag-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 {}",
index c169930d24d0215247f353ff73e0ac52f2c2e558..7c49b3bdc8d46ad86882f1554b2517297f3e75a5 100644 (file)
@@ -910,7 +910,7 @@ pub fn smb1_trans_response_record(state: &mut SMBState, r: &SmbRecord)
             if r.nt_status == SMB_NTSTATUS_BUFFER_OVERFLOW {
                 let key = SMBHashKeyHdrGuid::new(SMBCommonHdr::from1(r, SMBHDR_TYPE_TRANS_FRAG), fid);
                 SCLogDebug!("SMBv1/TRANS: queueing data for len {} key {:?}", rd.data.len(), key);
-                state.ssnguid2vec_map.insert(key, rd.data.to_vec());
+                state.dcerpc_rec_frag_cache.put(key, rd.data.to_vec());
             } else if is_dcerpc {
                 SCLogDebug!("SMBv1 TRANS TO PIPE");
                 let hdr = SMBCommonHdr::from1(r, SMBHDR_TYPE_HEADER);