let chunk_offset;
let nfs_version;
+ let mut fill_bytes = 0;
+ let pad = reply.count % 4;
+ if pad != 0 {
+ fill_bytes = 4 - pad;
+ }
+
+ // linux defines a max of 1mb. Allow several multiples.
+ if reply.count == 0 || reply.count > 16777216 {
+ return 0;
+ }
+
match xidmapr {
Some(xidmap) => {
file_name = xidmap.file_name.to_vec();
SCLogDebug!("chunk_offset {}", chunk_offset);
let mut is_last = reply.eof;
- let mut fill_bytes = 0;
- let pad = reply.count % 4;
- if pad != 0 {
- fill_bytes = 4 - pad;
- }
SCLogDebug!("XID {} is_last {} fill_bytes {} reply.count {} reply.data_len {} reply.data.len() {}",
r.hdr.xid, is_last, fill_bytes, reply.count, reply.data_len, reply.data.len());
if !self.is_udp {
self.tc_chunk_xid = r.hdr.xid;
- self.tc_chunk_left = (reply.count as u32 + fill_bytes) - reply.data.len() as u32;
+ debug_validate_bug_on!(reply.data.len() as u32 > reply.count);
+ self.tc_chunk_left = reply.count - reply.data.len() as u32;
}
SCLogDebug!("REPLY {} to procedure {} blob size {} / {}: chunk_left {} chunk_xid {:04X}",
// we should have enough data to parse the RPC record
match parse_rpc_reply(cur_i, false) {
Ok((remaining, ref hdr)) => {
- match parse_nfs3_reply_read(hdr.prog_data) {
+ match parse_nfs3_reply_read(hdr.prog_data, false) {
Ok((_, ref r)) => {
// deal with the partial nfs read data
self.process_partial_read_reply_record(hdr, r);
}
/// Complete data expected
-fn parse_nfs3_request_write_data_complete(i: &[u8], file_len: usize, fill_bytes: usize) -> IResult<&[u8], &[u8]> {
+fn parse_nfs3_data_complete(i: &[u8], file_len: usize, fill_bytes: usize) -> IResult<&[u8], &[u8]> {
let (i, file_data) = take(file_len as usize)(i)?;
let (i, _) = cond(fill_bytes > 0, take(fill_bytes))(i)?;
Ok((i, file_data))
}
/// Partial data. We have all file_len, but need to consider fill_bytes
-fn parse_nfs3_request_write_data_partial(i: &[u8], file_len: usize, fill_bytes: usize) -> IResult<&[u8], &[u8]> {
+fn parse_nfs3_data_partial(i: &[u8], file_len: usize, fill_bytes: usize) -> IResult<&[u8], &[u8]> {
let (i, file_data) = take(file_len as usize)(i)?;
let fill_bytes = cmp::min(fill_bytes as usize, i.len());
let (i, _) = cond(fill_bytes > 0, take(fill_bytes))(i)?;
let fill_bytes = if file_len % 4 != 0 { 4 - file_len % 4 } else { 0 };
// Handle the various file data parsing logics
let (i, file_data) = if complete {
- parse_nfs3_request_write_data_complete(i, file_len as usize, fill_bytes as usize)?
+ parse_nfs3_data_complete(i, file_len as usize, fill_bytes as usize)?
} else if i.len() >= file_len as usize {
- parse_nfs3_request_write_data_partial(i, file_len as usize, fill_bytes as usize)?
+ parse_nfs3_data_partial(i, file_len as usize, fill_bytes as usize)?
} else {
rest(i)?
};
Ok((i, req))
}
-/*
-#[derive(Debug,PartialEq)]
-pub struct Nfs3ReplyRead<'a> {
- pub status: u32,
- pub attr_follows: u32,
- pub attr_blob: &'a[u8],
- pub count: u32,
- pub eof: bool,
- pub data_len: u32,
- pub data: &'a[u8], // likely partial
-}
-*/
-pub fn parse_nfs3_reply_read(i: &[u8]) -> IResult<&[u8], NfsReplyRead> {
+pub fn parse_nfs3_reply_read(i: &[u8], complete: bool) -> IResult<&[u8], NfsReplyRead> {
let (i, status) = be_u32(i)?;
let (i, attr_follows) = verify(be_u32, |&v| v <= 1)(i)?;
let (i, attr_blob) = take(84_usize)(i)?; // fixed size?
let (i, count) = be_u32(i)?;
let (i, eof) = verify(be_u32, |&v| v <= 1)(i)?;
- let (i, data_len) = be_u32(i)?;
- let (i, data) = take(data_len as usize)(i)?;
- let (i, _data_padding) = cond(data_len % 4 !=0, take(4 - (data_len % 4)))(i)?;
+ let (i, data_len) = verify(be_u32, |&v| v <= count)(i)?;
+ let fill_bytes = if data_len % 4 != 0 { 4 - data_len % 4 } else { 0 };
+ // Handle the various file data parsing logics
+ let (i, data) = if complete {
+ parse_nfs3_data_complete(i, data_len as usize, fill_bytes as usize)?
+ } else if i.len() >= data_len as usize {
+ parse_nfs3_data_partial(i, data_len as usize, fill_bytes as usize)?
+ } else {
+ rest(i)?
+ };
let reply = NfsReplyRead {
status,
attr_follows,
0x00, /*_data_padding*/
];
- let result = parse_nfs3_reply_read(buf).unwrap();
+ let result = parse_nfs3_reply_read(buf, true).unwrap();
match result {
(r, reply) => {
assert_eq!(r.len(), 0);