Fuzzing highlighted an issue where a command sequence on the same file
id triggered a logging issue:
file data for id N
close id N
file data for id N
If this happened in a single blob of data passed to the parser, the
existing file tx would be reused, the file "reopened", confusing the
file logging logic. This would trigger a debug assert.
This patch makes sure a new file tx is created for the file data
coming in after the first file tx is closed.
Bug: #5567.
(cherry picked from commit
45eb038e63604766de2828f6f25d145fea040424)
return (tx_ref.unwrap(), files, flags)
}
- pub fn get_file_tx_by_fuid(&mut self, fuid: &Vec<u8>, direction: u8)
+ /// get file tx for a open file. Returns None if a file for the fuid exists,
+ /// but has already been closed.
+ pub fn get_file_tx_by_fuid_with_open_file(&mut self, fuid: &[u8], direction: u8)
+ -> Option<(&mut SMBTransaction, &mut FileContainer, u16)>
+ {
+ let f = fuid.to_vec();
+ for tx in &mut self.transactions {
+ let found = match tx.type_data {
+ Some(SMBTransactionTypeData::FILE(ref mut d)) => {
+ direction == d.direction && f == d.fuid && !d.file_tracker.is_done()
+ },
+ _ => { false },
+ };
+
+ if found {
+ SCLogDebug!("SMB: Found SMB file TX with ID {}", tx.id);
+ let (files, flags) = self.files.get(direction);
+ return Some((tx, files, flags));
+ }
+ }
+ SCLogDebug!("SMB: Failed to find SMB TX with FUID {:?}", fuid);
+ return None;
+ }
+
+ /// get file tx for a fuid. File may already have been closed.
+ pub fn get_file_tx_by_fuid(&mut self, fuid: &[u8], direction: u8)
-> Option<(&mut SMBTransaction, &mut FileContainer, u16)>
{
let f = fuid.to_vec();
None => b"<unknown>".to_vec(),
};
let mut set_event_fileoverlap = false;
- let found = match state.get_file_tx_by_fuid(&file_fid, STREAM_TOSERVER) {
+ let found = match state.get_file_tx_by_fuid_with_open_file(&file_fid, STREAM_TOSERVER) {
Some((tx, files, flags)) => {
let file_id : u32 = tx.id as u32;
if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
None => Vec::new(),
};
let mut set_event_fileoverlap = false;
- let found = match state.get_file_tx_by_fuid(&file_fid, STREAM_TOCLIENT) {
+ let found = match state.get_file_tx_by_fuid_with_open_file(&file_fid, STREAM_TOCLIENT) {
Some((tx, files, flags)) => {
if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
let file_id : u32 = tx.id as u32;
let mut set_event_fileoverlap = false;
// look up existing tracker and if we have it update it
- let found = match state.get_file_tx_by_fuid(&file_guid, STREAM_TOCLIENT) {
+ let found = match state.get_file_tx_by_fuid_with_open_file(&file_guid, STREAM_TOCLIENT) {
Some((tx, files, flags)) => {
if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
let file_id : u32 = tx.id as u32;
};
let mut set_event_fileoverlap = false;
- let found = match state.get_file_tx_by_fuid(&file_guid, STREAM_TOSERVER) {
+ let found = match state.get_file_tx_by_fuid_with_open_file(&file_guid, STREAM_TOSERVER) {
Some((tx, files, flags)) => {
if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
let file_id : u32 = tx.id as u32;