From: Victor Julien Date: Thu, 18 Mar 2021 10:05:35 +0000 (+0100) Subject: nfs: don't reuse file transactions X-Git-Tag: suricata-6.0.4~69 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8f2f2b55ee5ac729fbfb2706c8ed9f2be731a993;p=thirdparty%2Fsuricata.git nfs: don't reuse file transactions After a file has been closed (CLOSE, COMMIT command or EOF/SYNC part of READ/WRITE data block) mark it as such so that new file commands on that file do not reuse the transaction. When a file transfer is completed it will be flagged as such and not be found anymore by the NFSState::get_file_tx_by_handle() method. This forces a new transaction to be created. (cherry picked from commit 67759795c6405e449a80b282d290f84dc0fcd778) --- diff --git a/rust/src/nfs/nfs.rs b/rust/src/nfs/nfs.rs index 112abbd944..4ccd8c73d7 100644 --- a/rust/src/nfs/nfs.rs +++ b/rust/src/nfs/nfs.rs @@ -168,6 +168,7 @@ pub struct NFSTransaction { /// is a special file tx that we look up by file_handle instead of XID pub is_file_tx: bool, + pub is_file_closed: bool, /// file transactions are unidirectional in the sense that they track /// a single file on one direction pub file_tx_direction: u8, // STREAM_TOCLIENT or STREAM_TOSERVER @@ -203,6 +204,7 @@ impl NFSTransaction { response_done: false, nfs_version:0, is_file_tx: false, + is_file_closed: false, file_tx_direction: 0, file_handle:Vec::new(), type_data: None, @@ -634,7 +636,7 @@ impl NFSState { { let fh = file_handle.to_vec(); for tx in &mut self.transactions { - if tx.is_file_tx && + if tx.is_file_tx && !tx.is_file_closed && direction == tx.file_tx_direction && tx.file_handle == fh { @@ -677,6 +679,7 @@ impl NFSState { tdf.file_last_xid = r.hdr.xid; tx.is_last = true; tx.response_done = true; + tx.is_file_closed = true; } true } else { @@ -699,6 +702,7 @@ impl NFSState { tdf.file_last_xid = r.hdr.xid; tx.is_last = true; tx.request_done = true; + tx.is_file_closed = true; } } } @@ -856,9 +860,11 @@ impl NFSState { if tdf.file_tracker.is_done() { if direction == STREAM_TOCLIENT { tx.response_done = true; + tx.is_file_closed = true; SCLogDebug!("TX {} response is done now that the file track is ready", tx.id); } else { tx.request_done = true; + tx.is_file_closed = true; SCLogDebug!("TX {} request is done now that the file track is ready", tx.id); } } diff --git a/rust/src/nfs/nfs3.rs b/rust/src/nfs/nfs3.rs index f910b8a919..44701ca13a 100644 --- a/rust/src/nfs/nfs3.rs +++ b/rust/src/nfs/nfs3.rs @@ -126,6 +126,7 @@ impl NFSState { tdf.file_last_xid = r.hdr.xid; tx.is_last = true; tx.request_done = true; + tx.is_file_closed = true; } } } else { diff --git a/rust/src/nfs/nfs4.rs b/rust/src/nfs/nfs4.rs index 51d78800e3..1f50c0eb46 100644 --- a/rust/src/nfs/nfs4.rs +++ b/rust/src/nfs/nfs4.rs @@ -91,6 +91,7 @@ impl NFSState { tdf.file_last_xid = r.hdr.xid; tx.is_last = true; tx.request_done = true; + tx.is_file_closed = true; } } } @@ -99,6 +100,11 @@ impl NFSState { self.ts_chunk_left = w.write_len as u32 - file_data_len as u32; } + fn close_v4<'b>(&mut self, r: &RpcPacket<'b>, fh: &'b[u8]) + { + self.commit_v4(r, fh) + } + fn commit_v4<'b>(&mut self, r: &RpcPacket<'b>, fh: &'b[u8]) { SCLogDebug!("COMMIT, closing shop"); @@ -110,6 +116,7 @@ impl NFSState { tdf.file_last_xid = r.hdr.xid; tx.is_last = true; tx.request_done = true; + tx.is_file_closed = true; } } } @@ -188,6 +195,9 @@ impl NFSState { } &Nfs4RequestContent::Close(ref _rd) => { SCLogDebug!("CLOSEv4: {:?}", _rd); + if let Some(fh) = last_putfh { + self.close_v4(r, fh); + } } &Nfs4RequestContent::Create(ref rd) => { SCLogDebug!("CREATEv4: {:?}", rd);